本文是javaweb的第二篇,介绍了Servlet,Servlet是JavaWeb最为核心的内容,它是Java提供的一门动态web资源开发技术。概述了Request请求与响应,并且主要分析了Request请求。
上一篇:JavaWeb《一》概念、服务器部署及servlet
下一篇:敬请期待
Servlet是JavaWeb最为核心的内容,它是Java提供的一门动态web资源开发技术。使用Servlet就可以实现,根据不同的登录用户在页面上动态显示不同内容。上一篇通过seevlet的入门案例,实现了浏览器发出访问请求,我们的idea中可以有所表示。
我们编写一个Servlet就必须要实现Servlet接口,重写接口中的5个方法,但是这样是比较麻烦的,这个过程中我们关注的其实只有service方法。
开发B/S架构的web项目,都是针对HTTP协议,所以我们自定义Servlet可以通过继承HttpServlet
来完成。
在上一个基础案例后,继续写一个Servletdemo类继承HttpServlet
,重新启动服务器后会自动打包,在浏览器中访问http://localhost:8080/Webapp2_war/demo2
。
@WebServlet("/demo2")
public class ServletDemo extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//TODO GET 请求方式处理逻辑System.out.println("get...");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//TODO Post 请求方式处理逻辑System.out.println("post...");}
}
浏览器页面因为本来没内容就是空白,刷新一次在控制台就会get。
而想发送一个post请求servlet,需要使用form
表单了。可以直接在webapp下创建一个index.html
页面,在里面加入表单使用post方法,设置action
为/Webapp2_war/demo2
(和servlet对应),在浏览器页面访问这个页面提交内容就可以看到post了。
发送GET和POST请求的时候,参数的位置不一致,GET请求参数在请求行中,POST请求参数在请求体中,所以HttpServlet会根据请求方式的不同,调用不同的方法。
我们可以打开HttpServlet
看到他实现上层的GenericServlet
的service方法,然后调用自己的service:
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {if (req instanceof HttpServletRequest && res instanceof HttpServletResponse) {HttpServletRequest request = (HttpServletRequest)req;HttpServletResponse response = (HttpServletResponse)res;this.service(request, response);} else {throw new ServletException("non-HTTP request or response");}}
继续看到service,首先获取到了请求的方法,然后判断类型:
Servlet类编写好后,要想被访问到,就需要配置其访问路径:urlPattern
urlPattern可以配置多个,配置规则也有多种
在此前我们一个Servlet只写了一个访问路径,其实它是可以配置多个urlPattern的。
只需要参数:urlPatterns = {“/demo1”,“/demo2”},就可以输入不同链接来访问servlet了。
注意这个路径是不能和别人重复了,会报错:
Caused by: java.lang.IllegalArgumentException: 名为 [ServletDemo1]和 [ServletDemo2] 的servlet不能映射为一个url模式(url-pattern) [/demo1]
精确匹配
我们此前使用的就是精确匹配,服务路径和配置一致。
目录匹配
配置为:/user/*
访问:***/user/aaa
、***/user/aab
或者***/user/abc
都可以,就是说配置中的*
可以任意替代。
该方法的优先级低于精确匹配。
扩展名匹配
配置为:*.do
访问:***/aaa.do
或者***/abc.do
都可以,配置中的*
可以任意替代。
任意匹配
配置为:/
、/*
访问:任意都可以。但是会导致你的静态资源html都不能访问了。
在Servlet的配置中我们都使用的是@WebServlet
注解方法,这个是Servlet 3.0
版本后开始支持注解配置,3.0版本前只支持XML配置文件的配置方法。所以可以了解一下xml配置。
xml配置方法完成Servlet类就不需要加注解了,然后打开WEB_INF
里面的web.xml,
demo3 Webapp2_war.ServletDemo3 demo3 /demo3
在前面的
Servlet
或者HttpServlet
中,我们都可以看到:ServletRequest req, ServletResponse res
参数,这两个参数的作用是什么?
Request
是请求对象,Response
是响应对象。
我们再写一个Servlet类,在get里面获取请求数据和设置响应数据。
@WebServlet("/demo8")
public class ServletDemo3 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//使用request对象 获取请求数据String name = request.getParameter("name");//使用response对象 设置响应数据response.setHeader("content-type","text/html;charset=utf-8");response.getWriter().write(""+name+",欢迎您!
");}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("Post...");}
}
访问的时候在链接后面加上?name=zhangsan
,因为这就是直接的get方法。
当然你也可以重写Post方法,然后在静态页面用post表单传入数据。
HTTP请求数据总共分为三部分内容,分别是
请求行
、请求头
、请求体
,这三部分内容的数据该如何获取。
请求方式
、请求资源路径
、HTTP协议及版本
获取的内容 | 方法 |
---|---|
请求方式 | String getMethod() |
虚拟目录(项目访问路径) | String getContextPath() |
URL(统一资源定位符) | StringBuffer getRequestURL() |
URI(统一资源标识符) | String getRequestURI() |
请求参数 | String getQueryString() |
get一下:
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// String getMethod():获取请求方式: GETString method = req.getMethod();System.out.println(method);//GET// String getContextPath():获取虚拟目录(项目访问路径):/request-demoString contextPath = req.getContextPath();System.out.println(contextPath);// StringBuffer getRequestURL(): 获取URL(统一资源定位符):http://localhost:8080/request-demo/req1StringBuffer url = req.getRequestURL();System.out.println(url.toString());// String getRequestURI():获取URI(统一资源标识符): /request-demo/req1String uri = req.getRequestURI();System.out.println(uri);// String getQueryString():获取请求参数(GET方式): username=zhangsanString queryString = req.getQueryString();System.out.println(queryString);
}
key: value
,根据请求头名称获取对应值的方法为:String getHeader(String name)
1、ServletInputStream getInputStream()
获取字节输入流,如果前端发送的是字节数据,比如传递的是文件数据,则使用该方法;
2、BufferedReader getReader()
获取字符输入流,如果前端发送的是纯文本数据,则使用该方法。
参数在请求体中,请求参数获取
BufferedReader getReader()
1.准备一个静态页面,添加form表单发送post请求
2.doPost方法获取数据
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//获取post 请求体:请求参数//1. 获取字符输入流BufferedReader br = req.getReader();//2. 读取数据String line = br.readLine();System.out.println(line);
}
点击页面的提交
按钮后,就可以在控制台看到前端所发送的请求数据。
3.post具有多个值的参数
如下的hobby就具有两个参数:
request
对象为我们提供了如下方法,后面还会提到这里:
Map getParameterMap()
String[] getParameterValues(String name)
String getParameter(String name)
例如:
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("post~");Map map = req.getParameterMap();for (String key : map.keySet()) {System.out.print(key + ":");String[] values = map.get(key);for (String value : values) {System.out.print(value + " ");}System.out.println();}
}
前面我们进行了POSTt的请求参数获取(BufferedReader getReader()
),GET请求和POST请求获取请求参数的方式不一样,GET请求的请求参数在请求行中,在获取请求参数这块该如何实现呢》》》String getQueryString();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String result = req.getQueryString();System.out.println(result);
}
GET请求方式和POST请求方式区别主要在于获取请求参数的方式不一样,可以采取一种统一获取请求参数的方式,从而统一doGet和doPost方法内的代码。
getMethod()
来获取请求方式。public class RequestDemo1 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//获取请求方式String method = req.getMethod();//获取请求参数String params = "";if("GET".equals(method)){params = req.getQueryString();}else if("POST".equals(method)){BufferedReader reader = req.getReader();params = reader.readLine();}System.out.println(params); }@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {this.doGet(req,resp);}
}
方法 | M |
---|---|
获取所有参数Map集合 | Map |
根据名称获取参数值(数组) | String[] getParameterValues(String name) |
根据名称获取参数值(单个值) | String getParameter(String name) |
request对象已经将上述获取请求参数的方法进行了封装,并且request提供的方法实现的功能更强大,以后只需要调用request提供的方法即可:
public class RequestDemo1 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//采用request提供的获取请求参数的通用方式来获取请求参数//编写其他的业务代码...}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {this.doGet(req,resp);}
}
提交中文内容可能在控制台出现乱码。
浏览器把中文参数按照UTF-8
进行URL编码,Tomcat对获取到的内容进行了ISO-8859-1
的URL解码,编解码不一致因此出现乱码。
request.setCharacterEncoding("UTF-8");
new String(username.getBytes("ISO-8859-1"),"UTF-8");
在Tomcat8.0之后,已将GET请求乱码问题解决,设置默认的解码方式为UTF-8。
/*** 中文乱码问题解决方案*/
@WebServlet("/req4")
public class RequestDemo4 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//1. 解决乱码:POST,getReader()//request.setCharacterEncoding("UTF-8");//设置字符输入流的编码//2. 获取usernameString username = request.getParameter("username");System.out.println("解决乱码前:"+username);//3. GET,获取参数的方式:getQueryString// 乱码原因:tomcat进行URL解码,默认的字符集ISO-8859-1/* //3.1 先对乱码数据进行编码:转为字节数组byte[] bytes = username.getBytes(StandardCharsets.ISO_8859_1);//3.2 字节数组解码username = new String(bytes, StandardCharsets.UTF_8);*/username = new String(username.getBytes(StandardCharsets.ISO_8859_1),StandardCharsets.UTF_8);System.out.println("解决乱码后:"+username);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}
解决:
跳到第一页☝
☕物有本末,事有终始,知所先后。🍭
🍎☝☝☝☝☝我的CSDN☝☝☝☝☝☝🍓