Request概述
request是Servlet.service()方法的一个参数,类型为javax.servlet.http.HttpServletRequest。在客户端发出每个请求时,服务器都会创建一个request对象,并把请求数据封装到request中,然后在调用Servlet.service()方法时传递给service()方法,这说明在service()方法中可以通过request对象来获取请求数据。
request的功能可以分为以下几种:
-
封装了请求头数据。
-
封装了请求正文数据,如果是GET请求,那么就没有正文。
-
request是一个域对象,可以把它当成Map来添加获取数据。
-
request提供了请求转发和请求包含功能。
Request域方法
request是域对象,在JavaWeb中一共四个域对象,其中ServletContext就是域对象,它在整个应用中只创建一个ServletContext对象。request其中一个,request可以在一个请求中共享数据。一个请求会创建一个request对象,如果在一个请求中经历了多个Servlet,那么多个Servlet就可以使用request来共享数据。request的域方法:
-
void setAttribute(String name, Object value)
:用来存储一个对象,也可以称之为存储一个域属性,例如:servletContext.setAttribute(“xxx”, “XXX”)
,在request中保存了一个域属性,域属性名称为xxx,域属性的值为XXX。请注意,如果多次调用该方法,并且使用相同的name,那么会覆盖上一次的值,这一特性与Map相同。 -
Object getAttribute(String name)
:用来获取request中的数据,当前在获取之前需要先去存储才行,例如:String value=(String)request.getAttribute(“xxx”);
,获取名为xxx的域属性。 -
void removeAttribute(String name)
:用来移除request中的域属性,如果参数name指定的域属性不存在,那么本方法什么都不做。 -
Enumeration getAttributeNames()
:获取所有域属性的名称。
Request获取请求头数据
request与请求头相关的方法有:
-
String getHeader(String name)
:获取指定名称的请求头。 -
Enumeration getHeaderNames()
:获取所有请求头名称。 -
int getIntHeader(String name)
:获取值为int类型的请求头。
Request获取请求相关的其它方法
request中还提供了与请求相关的其他方法,有些方法是为了我们更加便捷的方法请求头数据而设计,有些是与请求URL相关的方法。
-
int getContentLength()
:获取请求体的字节数,GET请求没有请求体,没有请求体返回-1。 -
String getContentType()
:获取请求类型,如果请求是GET,那么这个方法返回null;如果是POST请求,那么默认为application/x-www-form-urlencoded
,表示请求体内容使用了URL编码。 -
String getMethod()
:返回请求方法,例如:GET。 -
Locale getLocale()
:返回当前客户端浏览器的Locale。java.util.Locale表示国家和言语,这个东西在国际化中很有用。 -
String getCharacterEncoding()
:获取请求编码,如果没有setCharacterEncoding(),那么返回null,表示使用ISO-8859-1编码。 -
void setCharacterEncoding(String code)
:设置请求编码,只对请求体有效。注意,对于GET而言,没有请求体,所以此方法只能对POST请求中的参数有效。 -
String getContextPath()
:返回上下文路径,例如:/hello。 -
String getQueryString()
:返回请求URL中的参数,例如:name=zhangSan。 -
String getRequestURI()
:返回请求URI路径,例如:/hello/oneServlet。 -
StringBuffer getRequestURL()
:返回请求URL路径,例如:http://localhost/hello/oneServlet
,即返回除了参数以外的路径信息。 -
String getServletPath()
:返回Servlet路径,例如:/oneServlet。 -
String getRemoteAddr()
:返回当前客户端的IP地址。 -
String getRemoteHost()
:返回当前客户端的主机名,但这个方法的实现还是获取IP地址。 -
String getScheme()
:返回请求协议,例如:http。 -
String getServerName()
:返回主机名,例如:localhost。 -
int getServerPort()
:返回服务器端口号,例如:8080。
System.out.println("request.getContentLength(): " + request.getContentLength());
System.out.println("request.getContentType(): " + request.getContentType());
System.out.println("request.getContextPath(): " + request.getContextPath());
System.out.println("request.getMethod(): " + request.getMethod());
System.out.println("request.getLocale(): " + request.getLocale());
System.out.println("request.getQueryString(): " + request.getQueryString());
System.out.println("request.getRequestURI(): " + request.getRequestURI());
System.out.println("request.getRequestURL(): " + request.getRequestURL());
System.out.println("request.getServletPath(): " + request.getServletPath());
System.out.println("request.getRemoteAddr(): " + request.getRemoteAddr());
System.out.println("request.getRemoteHost(): " + request.getRemoteHost());
System.out.println("request.getRemotePort(): " + request.getRemotePort());
System.out.println("request.getScheme(): " + request.getScheme());
System.out.println("request.getServerName(): " + request.getServerName());
System.out.println("request.getServerPort(): " + request.getServerPort());
Request获取请求参数
最为常见的客户端传递参数方式有两种:
-
浏览器地址栏直接输入:一定是GET请求。
-
超链接:一定是GET请求。
-
表单:可以是GET,也可以是POST,这取决与
<form>
的method属性值。
GET请求和POST请求的区别:
GET请求:
-
请求参数会在浏览器的地址栏中显示,所以不安全;
-
请求参数长度限制长度在1K之内;
-
GET请求没有请求体,无法通过request.setCharacterEncoding()来设置参数的编码;
POST请求:
-
请求参数不会显示浏览器的地址栏,相对安全;
-
请求参数长度没有限制;
表单:
<body>
<form action="http://localhost:8080/coydone_servlet/parameterServlet" method="get">
用户名:<input type="text" name="username"><br/>
密码:<input type="password" name="password"><br/>
兴趣爱好:<input type="checkbox" name="hobby" value="cpp">C++
<input type="checkbox" name="hobby" value="java">Java
<input type="checkbox" name="hobby" value="js">JavaScript<br/>
<input type="submit">
</form>
</body>
Java代码:
public class ParameterServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取请求参数
String username = req.getParameter("username");
String password = req.getParameter("password");
String[] hobby = req.getParameterValues("hobby");
System.out.println("用户名:" + username);
System.out.println("密码:" + password);
System.out.println("兴趣爱好:" + Arrays.asList(hobby));
}
}
GET请求的中文乱码解决:
// 获取请求参数
String username = req.getParameter("username");
//1 先以 iso8859-1 进行编码
//2 再以 utf-8 进行解码
username = new String(username.getBytes("iso-8859-1"), "UTF-8");
POST 请求的中文乱码解决 :
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 设置请求体的字符集为 UTF-8**,从而解决 post 请求的中文乱码问题
req.setCharacterEncoding("UTF-8");
// 获取请求参数
String username = req.getParameter("username");
String password = req.getParameter("password");
String[] hobby = req.getParameterValues("hobby");
System.out.println("**用户名:"** + username);
System.out.println("**密码:"** + password);
System.out.println("*兴趣爱好:"** + Arrays.asList*(hobby));
}
建议在创建servlet的时候,添加如下代码解决乱码问题:
//放在doGet()方法的开头。
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
请求的转发
请求转发是指,服务器收到请求后,从一次资源跳转到另一个资源的操作叫请求转发。
web.xml
<servlet>
<servlet-name>ServletDemo01</servlet-name>
<servlet-class>com.coydone.servlet.ServletDemo01</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ServletDemo01</servlet-name>
<url-pattern>/servletDemo01</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>ServletDemo02</servlet-name>
<servlet-class>com.coydone.servlet.ServletDemo02</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ServletDemo02</servlet-name>
<url-pattern>/servletDemo02</url-pattern>
</servlet-mapping>
ServletDemo01.java
public class ServletDemo01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取请求的参数
String username = req.getParameter("username");
System.out.println("ServletDemo01中请求的参数:"+username);
//把参数传递到ServletDemo02中
req.setAttribute("key","ServletDemo01");
//请求转发必须要以/开头,/表示地址为:http://ip:port/工程名/,映射到web目录
RequestDispatcher requestDispatcher = req.getRequestDispatcher("/servletDemo02");
//走向servletDemo02
requestDispatcher.forward(req,resp);
}
}
ServletDemo02.java
public class ServletDemo02 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取请求的参数
String username = req.getParameter("username");
System.out.println("ServletDemo02中请求的参数:"+username);
//从servletDemo01中获取数据
Object key = req.getAttribute("key");
System.out.println("从servletDemo01来的数据:"+key);
//处理自己的业务
System.out.println("servletDemo02处理自己的业务");
}
}
浏览器输入http://localhost:8080/coydone_servlet/servletDemo01?username=done
看测试结果。
请求包含在AServlet中,把请求包含到BServlet。
RequestDispatcher rd = request.getRequestDispatcher("/BServlet");
rd.include(request, response);
请求转发与请求包含比较:
-
如果在AServlet中请求转发到BServlet,那么在AServlet中就不允许再输出响应体,即不能再使用
response.getWriter()
和response.getOutputStream()
向客户端输出,这一工作应该由BServlet来完成;如果是使用请求包含,那么没有这个限制。 -
请求转发虽然不能输出响应体,但还是可以设置响应头的,例如:
response.setContentType(”text/html;charset=utf-8”);
-
请求包含大多是应用在JSP页面中,完成多页面的合并。
-
请求转发大多是应用在Servlet中,转发目标大多是JSP页面。
base标签
<!DOCTYPE html>
<html lang="zh_CN">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!--base标签设置页面相对路径工作时参照的地址
href 属性就是参数的地址值 -->
<base href="http://localhost:8080/07_servlet/a/b/">
</head>
<body>
这是 a 下的 b 下的 c.html 页面<br/>
<a href="../../index.html">跳回首页</a><br/>
</body>
</html>
相对路径/绝对路径
在javaWeb中,路径分为相对路径和绝对路径两种:
相对路径是:
. 表示当前目录
.. 表示上一级目录
资源名 表示当前目录/资源名
绝对路径: http://ip:port/工程路径/资源路径
在实际开发中,路径都使用绝对路径,而不简单的使用相对路径。
1、绝对路径
2、base+相对
Web中 /
斜杠的不同意义
在 web 中 / 斜杠 是一种绝对路径。
/ 斜杠 如果被浏览器解析,得到的地址是:http://ip:port/
<a href="/">斜杠</a>
/ 斜杠 如果被服务器解析,得到的地址是:http://ip:port/工程路径
1、<url-pattern>/servlet1</url-pattern>
2、servletContext.getRealPath(“/”);
3、request.getRequestDispatcher(“/”);
特殊情况: response.sendRediect(“/”);
把斜杠发送给浏览器解析。得到 http://ip:port/
评论区