JSP&Servlet学习笔记(3): 请求与响应
2018-02-28 22:19
295 查看
从容器到HttpServlet
有关HTTP请求的相关信息,是如何变成相对应的Java对象的呢?当请求来到HTTP服务器,服务器将请求转交给Web容器的时候,Web容器会创建一个代表当次请求的HttpServletRequest对象,并给这个对象设置请求的相关信息。同时,容器也会创建一个作为稍后对客户端进行响应的HttpServletResponse对象。
接着,容器会根据读取的@WebServlet标注或web.xml的设置,找出处理该请求的Servlet,调用它的service()方法,将创建的HttpServletRequest对象和HttpServletResponse对象传入作为参数,service()方法中会根据HTTP请求的方式,调用对应的doxxx()方法。
例如,若为GET,调用doGet()方法,那么在该方法中就可以使用两个传入的对象了。可以使用getParameter()取得请求参数,使用getWriter()取得输出用的PrintWriter()对象,并进行各项响应处理。对PrintWriter做的输出操作,最后由容器转换为HTTP响应,再由HTTP服务器对浏览器进行响应。之后容器将做对象销毁回收,该次请求响应结束。
在GET与POST都需要相同处理的情境下,通常可以在继承HttpServlet之后,在doGet()、doPost()中都调用一个自定义的processRequest()。
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { processRequest(req, resp); } protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { processRequest(req, resp); } protected void processRequest(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //处理请求... }
关于HttpServletRequest
处理请求参数与标头
HttpServletRequest定义了取得一些通用请求信息的方法:1. getParameter():指定请求参数名称来取得对应的值。 String username = request.getParameter("name"); 2. getParameterValues():可复选,多值。 String[] values = request.getParameterValues("param"); 取得所有请求参数名称: Enumeration<String> e = req.getParameterNames(); while(e.hasMoreElements()) { String param = e.nextElement(); ... } 3.getParameterMap():键是请求参数名称,值是请求参数值。
对于HTTP的标头(描述客户端或者服务器的属性、被传输的资源以及应该实现的连接 ),可以用以下方法取得:
getHeader() getHeaders() getHeaderName() *转换:getIntHeader()或getDateHeader()
另外,getContextPath()可以取得Web应用程序环境路径。
请求参数编码处理
POST如果浏览器以UTF-8来发送请求,那么接收时也要使用UTF-8编码字符串,所以在取得任何参数前调用执行该语句:
req.setCharacterEncoding("UTF-8");
GET
Tomcat在GET时,使用setCharacterEncoding()方法设置编码就不会有作用。所以是通过String的getBytes()指定编码来取得该字符串的字节数组,然后再重新构造为正确编码的字符串:
name = new String(name.getBytes("ISO-8859-1"),"UTF-8");
getReader()读取Body内容
HttpServletRequest上定义有getReader()方法,可以取得一个BufferedReader对象,通过该对象取得请求的Body数据。... String body = readBody(request); ... } private String readBody(HttpServletRequest request) throws IOException { BufferedReader reader = request.getReader(); String input = null; String requestBody = ""; while((input = reader.readLine()) != null) { requestBody = requestBody = input + "<BR>"; } return requestBody; } }
在同一个请求期间,getReader()与getIntputStream()只能择一调用,若两者都有调用,会抛出IllegalStatExcption异常。
getPart()、getParts()取得上传文件
编写一个Servlet来进行文件上传的处理,使用getPart()来处理上传的文件:package cc.openhome; import com.sun.xml.internal.fastinfoset.tools.FI_DOM_Or_XML_DOM_SAX_SAXEvent; import java.io.*; import javax.servlet.ServletException; import javax.servlet.annotation.MultipartConfig; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.Part; @MultipartConfig //Tomcat中必须设置此标注才能使用getPart()相关API @WebServlet("/upload.do") public class UploadServlet extends HttpServlet { @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { Part part = req.getPart("photo"); //使用getPart()取得Part对象 String filename = getFilename(part); writeTo(filename, part); } private String getFilename(Part part) { //取得上传文件名 String header = part.getHeader("Content-Disposit 4000 ion"); String filename = header.substring(header.indexOf("filename=\"") + 10, header.lastIndexOf("\"")); return filename; } private void writeTo(String filename, Part part) throws IOException, FileNotFoundException { //储存文件 InputStream in = part.getInputStream(); OutputStream out = new FileOutputStream("/home/hxll/桌面/" + filename); byte[] buffer = new byte[1024]; int length = -1; while ((length = in.read(buffer)) != -1) { out.write(buffer, 0, length); } in.close(); out.close(); } }
其实,Part有个方便的write()方法,可以直接将上传文件指定文件名写入磁盘中:
part.write(filename);
如果有多个文件要上传,可以调用getParts()方法,这会返回一个Collection< Part>,其中是每个上传文件的Part对象。
for(Part part : req.getParts()) { //迭代Collection中所有Part对象 if(part.getName().startsWith("file")) { //只处理上传文件区段(因为"上传"按钮也会是其中一个Part对象,所以用if判断名称是不是以file开头) String filename = getFilename(part); part.write(filename); } }
使用RequestDispatcher调派请求
使用include()方法,可以将另一个Servlet的操作流程包括至目前Servlet操作流程之中... @WebServlet("/some.view") ... PrintWriter out = resp.getWriter(); out.println("Some do one..."); RequestDispatcher dispatcher = req.getRequestDispatcher("other.view"); dispatcher.include(req, resp); out.println("Some do two..."); out.close(); } } -------------------------------------------------------------------------- ... @WebServlet("other.view") ... PrintWriter out = resp.getWriter(); out.println("Other do one..."); } }
则网页上见到的响应顺序是Some do one…Other do one…Some do two…
使用forward()方法,将请求处理转发给别的Servlet
若要调用forward()方法,目前的Servlet不能有任何响应确认
@WebServlet("/hello.do") public class HelloController extends HttpServlet { private HelloModel model = new HelloModel(); @Override protected void doGet(........ { String name = request.getParameter("user"); //收集请求参数 String message = model.doHello(name); //委托HelloModel对象处理 request.setAttribute("message", message); //将结果信息设置请求对象成为属性 request.getRequestDispatcher("/hello.view").forward(request, response); //转发给hello.view进行响应
HelloController会收集请求参数并委托一个HelloModel对象处理。HelloModel对象处理的结果,会设置为请求对象中的属性。
请求属性范围
在调派中,如果有必须共享的“对象”,可以设置给请求对象成为属性,称为请求属性范围。setAttribute() 指定名称与对象设置属性 getAttribute() 指定名称取得属性 getAttributeNames() 取得所有属性名称 removeAttribute() 指定名称移除属性
关于HttpServletResponse
设置响应标头、缓冲区
所有的标头设置,必须在响应确认之前,否则会被容器忽略容器可以对响应进行缓冲:
getBufferSize() setBufferSize() isCommitted() 查看响应是否已确认 reset() 重置所有响应信息,连同已设置的标头一并清除 resetBuffer() 重置响应内容,但不清除标头 flushBuffer() 清除所有缓冲区中已设置的响应信息至客户端
setBufferSize()必须在调用getWriter()之前使用
reset()、resetBuffer()必须在响应未确认前调用
使用getWriter()输出字符
设置Localeresp.setLocale(Locale.xxxx);
使用setCharacterEncoding()或setContentType()
resp.setCharacterEncoding("UTF-8"); resp.setContentType("text/html; charset=UTF-8");
如果指定了charset,则setLocale()就会被忽略。
使用getOutputStream()输出二进制字符
有时候需要直接对浏览器进行字节输出,可以使用HttpServletResponse的getOutputStream()方法取得ServletOutputStream实例,它是OutputStream的子类。... response.setContentType("application/pdf"); InputStream in = getServletContext().getResourceAsStream("/WEB-INF/xxx.pdf"); OutputStream out = response.getOutputStream(); //取得输出串流 writeBytes(in, out); } private void writeBytes(InputStream in, OutputStream out) throws IOException { byte[] buffer = new byte[1024]; int length = -1; while ((length = in.read(buffer)) != -1) { out.write(buffer, 0, length); } in.close(); out.close(); } }
使用sendRedirect()、sendError()
可以使用HttpServletResponse的sendRedirect()要求浏览器重新请求另一个URL,又称为重定向:response.sendRedirect("http://openhome.cc");
在响应未确认输出前执行。
如果在处理请求的过程中发现一些错误,而你想要传送服务器默认的状态与错误信息,可以使用sendError()方法:
response.sendError(HttpServletResponse.SC_NOT_FOUND);
在响应未确认输出前执行。
相关文章推荐
- JSP&Servlet学习笔记-第三章:请求与响应
- JSP网络编程-请求和响应-HttpServletRequest-HttpServletResponse-学习笔记
- JSP&&SERVLET学习笔记(五):请求参数编码处理
- Servlet&JSP随堂学习笔记
- JSP&Servlet学习笔记(6): 监听器
- Jsp&Servlet学习 --- get与post请求
- JSP&Servlet学习笔记----第5章
- JSP&Servlet学习笔记(4): 会话管理
- 【Head First Servlets and JSP】笔记6:什么是响应首部 & 快速搭建一个简单的测试环境
- JSP&Servlet学习笔记(8): 使用JSP
- JSP&Servlet学习笔记(1): Web应用程序简介
- Servlet&JSP学习笔记:Web应用程序基础知识
- JSP&Servlet学习笔记----第5章
- Head First Servlet & JSP 学习笔记(1)
- JSP&&SERVLET学习笔记(二):Web.xml
- JSP&Servlet学习笔记(1)Web开发基础理论
- JSP&Servlet学习笔记----第5章
- Head First Servlet&Jsp 学习笔记(一) 一些基础知识
- JSP&Servlet学习笔记----第4章
- Servlets&JSP学习笔记:作为Servlet