Servlet的请求处理
1-Servlet的请求处理
通过前面的学习我们能够创建并运行一个简单的Servlet 程序,完成浏览器和服务器的简单交互,但是我们编写的Servlet 代码是没有对浏览器的请求进行处理的。现在我们开始学习
如何使用Servlet 进行浏览器请求的处理。
Request 对象:
问题:
浏览器发起请求到服务器,会遵循HTTP 协议将请求数据发送给服务器。
那么服务器接受到请求的数据改怎么存储呢?不但要存,而且要保证完成性。
解决:
使用对象进行存储,服务器每接受一个请求,就创建一个对象专门的存储此次请求的请求数据。
request 对象解释:
服务器接收到浏览器的请求后,会创建一个 Request 对象,对象中存储了此次请求相关的请求数据。服务器在调用 Servlet 时会将创建的Request 对象作为实参传递给 Servlet 的方法,比如:service 方法。
使用:
获取请求头数据
获取请求行数据获取用户数据
读取 HTTP 头的方法
下面的方法可用在 Servlet 程序中读取 HTTP 头。这些方法通过 HttpServletRequest 对象可用。
方法 & 描述:
Cookie[] getCookies()
返回一个数组,包含客户端发送该请求的所有的 Cookie 对象。
1 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 2 3 // TODO Auto-generated method stub 4 5 response.getWriter().append("Served at: ").append(request.getContextPath()); 6 7 8 9 //new一个cookie 10 11 Cookie cookie = new Cookie("user", "wangwu"); 12 13 response.addCookie(cookie); 14 15 //1 获取cookie的数据 16 17 Cookie[] cookies = request.getCookies(); 18 19 for (int i = 0; i < cookies.length; i++) { 20 21 response.getWriter().println("\n"+cookies[i].getName()+":"+cookies[i].getValue()); 22 23 }
Object getAttribute(String name)
以对象形式返回已命名属性的值,如果没有给定名称的属性存在,则返回 null。
String getCharacterEncoding()
返回请求主体中使用的字符编码的名称。
1 /* 3 2 3 * String getCharacterEncoding() 4 5 * 返回请求主体中使用的字符编码的名称。 6 7 */ 8 9 response.getWriter().println("\n"+request.getCharacterEncoding()); 10 11 //null
String getContextPath()
返回指示请求上下文的请求 URI 部分。
/* 4 * String getContextPath() 返回指示请求上下文的请求 URI 部分。 */ response.getWriter().println("\n"+request.getContextPath()); // /12_4request
String getHeader(String name)
以字符串形式返回指定的请求头的值。
/* 5 * String getHeader(String name) 以字符串形式返回指定的请求头的值。 */ response.getWriter().println("\n"+request.getHeader("Set-Cookie")); //null
String getMethod()
返回请求的 HTTP 方法的名称,例如,GET、POST 或 PUT。
/* 6 * String getMethod() 返回请求的 HTTP 方法的名称,例如,GET、POST 或 PUT。 */ response.getWriter().println("\n"+request.getMethod()); //GET
String getParameter(String name)
以字符串形式返回请求参数的值,或者如果参数不存在则返回 null。
/* 7 * String getParameter(String name) 以字符串形式返回请求参数的值,或者如果参数不存在则返回 null。 */ response.getWriter().println("\n"+request.getParameter("username")); //http://localhost:8080/12_4request/Request?&username=cxk //返回cxk
String getPathInfo()
当请求发出时,返回与客户端发送的 URL 相关的任何额外的路径信息。
/* 8 * String getPathInfo() 当请求发出时,返回与客户端发送的 URL 相关的任何额外的 路径信息。 */ response.getWriter().println("\n"+"8:"+request.getPathInfo()); //返回null
String getProtocol()
返回请求协议的名称和版本,即获取协议信息。http/https
/* 9 * String getProtocol() 返回请求协议的名称和版本。http/https */ response.getWriter().println("\n"+"9:"+request.getProtocol()); //返回HTTP/1.1
String getQueryString()
返回包含在路径后的请求 URL 中的查询字符串,即获取查询字符串。
/* 10 * String getcString() 返回包含在路径后的请求 URL 中的查询字符串,即获取查询字符串。 */ response.getWriter().println("\n"+"10:"+request.getQueryString()); //返回&username=cxk&password=pass
String getRemoteAddr()
返回发送请求的客户端的互联网协议(IP)地址。
/* 11 * String getRemoteAddr() 返回发送请求的客户端的互联网协议(IP)地址。 */ response.getWriter().println("\n"+"11:"+request.getRemoteAddr()); //返回0:0:0:0:0:0:0:1
String getRequestURI()
从协议名称直到 HTTP 请求的第一行的查询字符串中,返回该请求的 URL 的一部分,
即返回请求根路径后面的路径内容。
/* 12 * String getRequestURI() 从协议名称直到 HTTP 请求的第一行的查询字符串中,返回该请求的 URL 的一部分。 */ response.getWriter().println("\n"+"12:"+request.getRequestURI()); //返回/12_4request/Request
String getServletPath()
返回调用 JSP 的请求的 URL 的一部分,即获取servlet路径。
/* 13 * String getServletPath() 返回调用 JSP 的请求的 URL 的一部分。 */ response.getWriter().println("\n"+"13:"+request.getServletPath()); //返回/Request
String[] getParameterValues(String name)
Parameter:提交的数据 getParameter("hero")//getParameter("name")
返回一个字符串对象的数组,包含所有给定的请求参数的值,如果参数不存在则返回 null。
/* 14 * String[] getParameterValues(String name) 返回一个字符串对象的数组,包含所有给定的请求参数的值,如果参数不存在则返回 null。 */ String[] parameterValues = request.getParameterValues("likehero"); response.getWriter().print("\n"+"14:"); for (int i = 0; i < parameterValues.length; i++) { response.getWriter().print(parameterValues[i]+" "); //返回xiaoyu ruiwen }
int getIntHeader(String name)
返回指定的请求头的值为一个 int 值,即获取请求头字段的内容值是整数。
/* 15 * int getIntHeader(String name) 返回指定的请求头的值为一个 int 值。 */ response.getWriter().println("\n"+"15:"+request.getIntHeader("Upgrade-Insecure-Requests")); //返回1
int getServerPort()
返回接收到这个请求的端口号。
/* 16 * int getServerPort() 返回接收到这个请求的端口号。 */ response.getWriter().println("\n"+"16:"+request.getServerPort()); //返回8080
int getParameterMap()
将参数封装成 Map 类型。
/* 17 * int getParameterMap() 将参数封装成 Map 类型。 */ response.getWriter().println("\n"+"17:"+request.getParameterMap()); //返回{username=[Ljava.lang.String;@22365c4d, password=[Ljava.lang.String;@2609dcd3, likehero=[Ljava.lang.String;@630b5676}
案例解析:
前端判断userAgent,显示PC还是移动端页面的流程
User --> 发送请求http://www.baidu.com ---> 返回PC端页面(JS开始执行判断浏览器是什么浏览器(直接通过js自动适配移动端页面)) ----> location.href = http://m.baidu.com --> 发送请求到百度移动端页面
后端判断userAgent,显示PC还是移动端页面的流程
User --> 发送请求http://www.baidu.com -->servlet分析判断浏览器是什么浏览器 ---》返回移动端页面或者是PC页面
Response 对象:
问题:
在使用 Request 对象获取了请求数据并进行处理后,处理的结果如何显示到浏览器中呢?
解决:使用 Response 对象
服务器在调用指定的 Servlet 进行请求处理的时候,会给 Servlet 的方法传递两个实参 request 和 response。
其中 request 中封存了请求相关的请求数据,
而 response 则是用来进行响应的一个对象。
使用:
设置响应头
//设置响应头 response.setHeader("Content-Type", "text/json");
设置响应编码格式
//设置响应编码 request.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8"); //影响response中Content-Type: text/html;charset=UTF-8的charset
设置响应类型
//设置响应类型 //response.setContentType("text/html;charset=utf-8"); response.setContentType("text/html");
设置 HTTP 响应报头的方法
下面的方法可用于在 Servlet 程序中设置 HTTP 响应报头。这些方法通过 HttpServletResponse 对象可用。
方法 & 描述
void addCookie(Cookie cookie)
把指定的 cookie 添加到响应。
void addHeader(String name, String value)
添加一个带有给定的名称和值的响应报头。
void sendRedirect(String location)
使用指定的重定向位置 URL 发送临时重定向响应到客户端。
String webName = request.getParameter("webName"); //重新让客户端进行新的请求 webName="baidu";//跳转到百度 response.sendRedirect("http://www."+webName+".com");
void setCharacterEncoding(String charset)
设置被发送到客户端的响应的字符编码(MIME 字符集)例如,UTF-8。
void setContentType(String type)
如果响应还未被提交,设置被发送到客户端的响应的内容类型。
void setHeader(String name, String value)
设置一个带有给定的名称和值的响应报头。
void setIntHeader(String name, int value)
设置一个带有给定的名称和整数值的响应报头。
void setStatus(int sc)
为该响应设置状态码。
设置响应实体
请求乱码问题解决:
使用 String 进行重新编码:
uname=new String(uname.getBytes("iso8859-1"),"utf-8");
解决链接中出现乱码的问题:
Get 方式请求:
在 service 方法中使用: req.setCharacterEncoding(“utf-8”);
在 tomcat 服务器目录下的 conf 文件下找到 server.xml 文件,打开进行如下配置:
Post 方式请求:
在 service 方法中使用: req.setCharacterEncoding(“utf-8”);
流程总结:
Servlet 的使用流程:
设置请求编码格式设置响应编码格式获取请求信息
处理请求信息响应处理结果
数据流转流程:
浏览器------>服务器 >数据库
浏览器<------服务器<数据库
请求转发:
问题:
服务器在接收到浏览器的请求后, 仅仅使用一个
Servlet 进行请求处理,会造成不同的 Servlet 逻辑代码冗余,Servlet 的职责不明确。
解决:
使用请求转发。特点:
一次请求
地址栏信息不改变。
Request 对象作用域
问题:使用请求转发后,不同的 Servlet 之间怎么进行数据的共享呢?或者说数据怎么从一个servlet 流转给另外一个Servlet 呢?
解决:使用request 对象的作用域使用:
request.setAttribute(object name,Object value); request.getAttribute(Object obj)
作用:解决了一次请求内的不同Servlet 的数据(请求数据+其他数据)共享问题。
作用域:基于请求转发,一次请求中的所有Servlet 共享。注意:
使用Request 对象进行数据流转,数据只在一次请求内有效。特点:
服务器创建
每次请求都会创建生命周期一次请求
重定向
问题:
如果当前的请求,Servlet 无法进行处理怎么办?
如果使用请求转发,造成表单数据重复提交怎么办? 解决:
使用重定向使用:
response.sendRedirect(“路径”).
本地路径为:uri
网络路径为:定向资源的URL 信息特点:
两次请求
浏览器地址栏信息改变避免表单重复提交