ServletRequest

简述

其实就是对于请求报文的封装,一般就是HttpServletRequest。

常用方法

  1. package com.simon.request;
  2. import javax.servlet.ServletException;
  3. import javax.servlet.annotation.WebServlet;
  4. import javax.servlet.http.HttpServlet;
  5. import javax.servlet.http.HttpServletRequest;
  6. import javax.servlet.http.HttpServletResponse;
  7. import java.io.IOException;
  8. import java.util.Enumeration;
  9. @WebServlet("/request1")
  10. public class RequestServlet1 extends HttpServlet {
  11. protected void doPost(HttpServletRequest request, HttpServletResponse response)
  12. throws ServletException, IOException {
  13. }
  14. protected void doGet(HttpServletRequest request, HttpServletResponse response)
  15. throws ServletException, IOException {
  16. //
  17. String method = request.getMethod();
  18. // /app/request1
  19. String requestURI = request.getRequestURI();
  20. // http://localhost/app/request1 requestURL = 协议 + 主机端口号 + requestURI
  21. String requestURL = request.getRequestURL().toString();
  22. String protocol = request.getProtocol();
  23. System.out.println(method + " " + requestURI + " " + protocol);
  24. System.out.println(method + " " + requestURL + " " + protocol);
  25. Enumeration<String> headerNames = request.getHeaderNames();
  26. while (headerNames.hasMoreElements()){
  27. String key = headerNames.nextElement();
  28. String value = request.getHeader(key);
  29. System.out.println(key + ":" + value);
  30. }
  31. //请求体
  32. //request.getInputStream();
  33. }
  34. }

除此之外还可以获取到客户端和服务器主机的一些信息:

  1. package com.simon.request;
  2. import javax.servlet.ServletException;
  3. import javax.servlet.annotation.WebServlet;
  4. import javax.servlet.http.HttpServlet;
  5. import javax.servlet.http.HttpServletRequest;
  6. import javax.servlet.http.HttpServletResponse;
  7. import java.io.IOException;
  8. import java.util.Enumeration;
  9. @WebServlet("/request2")
  10. public class RequestServlet2 extends HttpServlet {
  11. protected void doPost(HttpServletRequest request, HttpServletResponse response)
  12. throws ServletException, IOException {
  13. }
  14. protected void doGet(HttpServletRequest request, HttpServletResponse response)
  15. throws ServletException, IOException {
  16. //request还可以获取客户机和服务器主机的一些信息
  17. String localAddr = request.getLocalAddr();
  18. int localPort = request.getLocalPort();
  19. String remoteAddr = request.getRemoteAddr();
  20. int remotePort = request.getRemotePort();
  21. System.out.println("客户机:" + remoteAddr + "使用端口号:" + remotePort +
  22. "访问了服务器主机:" + localAddr + " 服务器端口号:" + localPort);
  23. }
  24. }

Web服务器收到客户端的http请求,会针对每一次请求,分别创建一个用于代表请求的request对象、和代表响应的response对象
那么,频繁地去刷新同一个链接,会创建多个request对象还是一个request对象呢?多个request对象.

使用场景

最常用的使用场景就是获取请求参数,比如登录一个网站,需要用户输入用户名密码。点击登录,会发送一个HTTP请求,HTTP请求报文、用户名、密码会随着HTTP请求报文携带到服务器上面去;
用户名、密码在请求报文中,接下来,我们需要做的就是从请求报文中取出用户名、密码,做校验。

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. </head>
  7. <body>
  8. <form action="/servlet/login" method="post">
  9. 用户名:<input type="text" name="username"/><br>
  10. 密码:<input type="password" name="password"/><br>
  11. <input type="checkbox" name="hobby" value="Java">Java<br>
  12. <input type="checkbox" name="hobby" value="PHP">PHP<br>
  13. <input type="submit"/>
  14. </form>
  15. </body>
  16. </html>
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. </head>
  7. <body>
  8. what happen
  9. </body>
  10. </html>
  1. package com.simon.request;
  2. import javax.servlet.RequestDispatcher;
  3. import javax.servlet.ServletException;
  4. import javax.servlet.annotation.WebServlet;
  5. import javax.servlet.http.HttpServlet;
  6. import javax.servlet.http.HttpServletRequest;
  7. import javax.servlet.http.HttpServletResponse;
  8. import java.io.IOException;
  9. import java.util.Arrays;
  10. import java.util.Enumeration;
  11. @WebServlet("/login")
  12. public class LoginServlet extends HttpServlet {
  13. @Override
  14. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  15. req.setCharacterEncoding("utf-8");
  16. //getParameter()方法不仅可以获取请求体里面的请求参数,还可以获取在请求行的请求参数
  17. //但是该方法也有限定条件,它只能获取key=value&key=value型的数据
  18. String username = req.getParameter("username");
  19. String password = req.getParameter("password");
  20. if ("zs".equals(username)&&"abc".equals(password)){
  21. Enumeration<String> parameterNames = req.getParameterNames();
  22. while (parameterNames.hasMoreElements()){
  23. String parameterName = parameterNames.nextElement();
  24. String[] parameterValues = req.getParameterValues(parameterName);
  25. if (1 == parameterValues.length ){
  26. System.out.println(parameterName + ":" + parameterValues[0]);
  27. }else {
  28. System.out.println(parameterName + ":" + Arrays.toString(parameterValues));
  29. }
  30. }
  31. resp.setContentType("text/html;charset=utf-8");
  32. resp.getWriter().println("恭喜,登陆成功即将跳转....");
  33. RequestDispatcher dispatcher = req.getRequestDispatcher("/success.html");
  34. dispatcher.forward(req,resp);
  35. }
  36. }
  37. }

image.png

Request域

共享空间。Request对象中存在一个map,如果能够拿到同一个request对象,那么就能够共享这个map
但是,哪些组件可以拿到同一个request对象
刷新同一个页面的多个请求可以共享request域吗?
不可以
转发的两个组件之间 共享request域。
如果某个servlet需要将数据和另外一个servlet进行共享,不仅仅可以通过context域进行共享,还可以利用request域来共享
比如某个servlet运行时获取到了商品的数据,接下来需要在另外一个servlet中去做一些格式化,Wed 2020-
context域:范围很大。所有的servlet均可以共享
request域:很小,只有这两个组件之间可以共享。假设你的场景需求就是在这个请求内需要共享,出了这个请求,就不需要共享,那么完全可以使用request域,而不需要使用context域,有点浪费

ServletResponse

常规API

  1. package com.simon.response;
  2. import javax.servlet.ServletException;
  3. import javax.servlet.annotation.WebServlet;
  4. import javax.servlet.http.HttpServlet;
  5. import javax.servlet.http.HttpServletRequest;
  6. import javax.servlet.http.HttpServletResponse;
  7. import java.io.IOException;
  8. @WebServlet("/response1")
  9. public class ServletResponseDemo1 extends HttpServlet {
  10. @Override
  11. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  12. resp.setStatus(404);
  13. resp.setHeader("Content-Type","text/html");
  14. resp.getWriter().println("<h1 style='color:red'>File Not Found</h1>");
  15. //服务器接收参数和发送参数,都可设置编码格式;
  16. //接收时,我设置请求报文的编码格式供我解析
  17. //发送时,指定utf-8,但要告知给客户端,放在响应头/体,让客户端也以这个格式解析我
  18. resp.setContentType("text/html;charset=utf-8");
  19. resp.getWriter().println("你好");
  20. }
  21. }

缺省Servlet

要求:在当前应用中实现缺省Servlet的功能,url-pattern必须是/,把这些文件正常显示出来;如果文件不存在,显示404。

  1. package com.simon.response;
  2. import javax.servlet.ServletException;
  3. import javax.servlet.ServletOutputStream;
  4. import javax.servlet.annotation.WebServlet;
  5. import javax.servlet.http.HttpServlet;
  6. import javax.servlet.http.HttpServletRequest;
  7. import javax.servlet.http.HttpServletResponse;
  8. import java.io.File;
  9. import java.io.FileInputStream;
  10. import java.io.IOException;
  11. @WebServlet("/")
  12. public class ServletResponseDemo2 extends HttpServlet {
  13. @Override
  14. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  15. //显示处缺省servlet的某一个文件,比如2.html
  16. //ServletOutputStream:只需要将文件写入到response的缓冲区即可,tomcat会读取这个response里面
  17. //的内容,然后生成响应报文
  18. ServletOutputStream outputStream = resp.getOutputStream();
  19. String realPath = getServletContext().getRealPath("WEB-INF/2.html");
  20. FileInputStream inputStream = new FileInputStream(new File(realPath));
  21. int length = 0;
  22. byte[] bytes = new byte[1024];
  23. while ((length = inputStream.read(bytes)) != -1){
  24. outputStream.write(bytes,0,length);
  25. }
  26. inputStream.close();
  27. ////输出流可以关闭也可以不关闭,如果不关闭,tomcat会帮你关闭
  28. outputStream.close();
  29. }
  30. }

image.png

重定向、刷新和转发

  1. package com.simon.response;
  2. import javax.servlet.ServletException;
  3. import javax.servlet.annotation.WebServlet;
  4. import javax.servlet.http.HttpServlet;
  5. import javax.servlet.http.HttpServletRequest;
  6. import javax.servlet.http.HttpServletResponse;
  7. import java.io.IOException;
  8. @WebServlet("/redirect")
  9. public class ServletResponseDemo4 extends HttpServlet {
  10. @Override
  11. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  12. resp.sendRedirect("url="+req.getContextPath()+"/1.html");
  13. }
  14. }
  1. package com.simon.response;
  2. import javax.servlet.ServletException;
  3. import javax.servlet.annotation.WebServlet;
  4. import javax.servlet.http.HttpServlet;
  5. import javax.servlet.http.HttpServletRequest;
  6. import javax.servlet.http.HttpServletResponse;
  7. import java.io.IOException;
  8. import java.text.SimpleDateFormat;
  9. import java.util.Date;
  10. @WebServlet("/refresh")
  11. public class ServletResponseDemo3 extends HttpServlet {
  12. @Override
  13. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  14. //refresh有2个作用:①定时刷新 ②页面跳转
  15. SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  16. String dateFormat = simpleDateFormat.format(new Date());
  17. //每2秒刷新一次
  18. resp.getWriter().println(dateFormat);
  19. resp.setHeader("refresh","2");
  20. // resp.setHeader("refresh","3;url=https://www.baidu.com");
  21. resp.setHeader("refresh","3;url="+req.getContextPath()+"/login.html");
  22. }
  23. }
  1. package com.simon.request;
  2. import javax.servlet.RequestDispatcher;
  3. import javax.servlet.ServletException;
  4. import javax.servlet.annotation.WebServlet;
  5. import javax.servlet.http.HttpServlet;
  6. import javax.servlet.http.HttpServletRequest;
  7. import javax.servlet.http.HttpServletResponse;
  8. import java.io.IOException;
  9. import java.util.Arrays;
  10. import java.util.Enumeration;
  11. @WebServlet("/login")
  12. public class LoginServlet extends HttpServlet {
  13. @Override
  14. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  15. req.setCharacterEncoding("utf-8");
  16. String username = req.getParameter("username");
  17. String password = req.getParameter("password");
  18. if ("zs".equals(username)&&"abc".equals(password)){
  19. Enumeration<String> parameterNames = req.getParameterNames();
  20. while (parameterNames.hasMoreElements()){
  21. String parameterName = parameterNames.nextElement();
  22. String[] parameterValues = req.getParameterValues(parameterName);
  23. if (1 == parameterValues.length ){
  24. System.out.println(parameterName + ":" + parameterValues[0]);
  25. }else {
  26. System.out.println(parameterName + ":" + Arrays.toString(parameterValues));
  27. }
  28. }
  29. resp.setContentType("text/html;charset=utf-8");
  30. resp.getWriter().println("恭喜,登陆成功即将跳转....");
  31. RequestDispatcher dispatcher = req.getRequestDispatcher("/success.html");
  32. dispatcher.forward(req,resp);
  33. }
  34. }
  35. }

三个页面跳转之间的区别

联系:都可以进行页面的跳转
区别:
1.状态码不同。重定向是302,转发、刷新都是200
2.能否共享request域。转发可以共享request域,其他两种是不可以的
3.响应头不一致。转发没有响应头;刷新是refresh响应头;重定向是Location响应头
4.请求次数不同。转发只发了一次请求,刷新、重定向都是多次
5.介导对象不同。转发是request介导的;刷新、重定向是response介导的
6.请求方法不同。转发前后请求方法不变(转发前是post请求,转发后还是post请求),但是对于刷新、重定向,后面会变成get请求
7.跳转的范围不同。转发只可以在当前应用下调转,刷新、重定向是没有限制的

文件下载

  1. package com.simon.download;
  2. import javax.servlet.ServletException;
  3. import javax.servlet.ServletOutputStream;
  4. import javax.servlet.annotation.WebServlet;
  5. import javax.servlet.http.HttpServlet;
  6. import javax.servlet.http.HttpServletRequest;
  7. import javax.servlet.http.HttpServletResponse;
  8. import java.io.FileInputStream;
  9. import java.io.IOException;
  10. @WebServlet("/download")
  11. public class DownloadServlet extends HttpServlet {
  12. @Override
  13. protected void doGet(HttpServletRequest req, HttpServletResponse resp)
  14. throws ServletException, IOException {
  15. //将WEB-INF目录下的1.txt文件下载到本地硬盘上面,而不是直接打开该文件
  16. String realPath = getServletContext().getRealPath("WEB-INF/1.txt");
  17. FileInputStream inputStream = new FileInputStream(realPath);
  18. //key code line
  19. resp.setHeader("Content-Disposition","attachment;filename=1.txt");
  20. ServletOutputStream outputStream = resp.getOutputStream();
  21. int length = 0;
  22. byte[] bytes = new byte[1024];
  23. while ((length=inputStream.read(bytes)) != -1){
  24. outputStream.write(bytes,0,length);
  25. }
  26. }
  27. }

image.png
使用场景:做后台管理系统,会有导出的功能。

三种查看图片文件的方式

image.png

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. </head>
  7. <body>
  8. <a href="/app/threeGirls.jpg">点我直接查看图片</a>
  9. <a href="/app/pic/view">点我通过servlet查看图片</a>
  10. <a href="/app/pic/download">点我下载图片</a>
  11. <a href="/app/pic2?op=view2">点我通过servlet查看图片,改进版</a>
  12. <a href="/app/pic2?op=download2">点我下载图片,改进版</a>
  13. </body>
  14. </html>

初级版

  1. package com.simon.download;
  2. import javax.servlet.ServletException;
  3. import javax.servlet.ServletOutputStream;
  4. import javax.servlet.annotation.WebServlet;
  5. import javax.servlet.http.HttpServlet;
  6. import javax.servlet.http.HttpServletRequest;
  7. import javax.servlet.http.HttpServletResponse;
  8. import java.io.FileInputStream;
  9. import java.io.FileNotFoundException;
  10. import java.io.IOException;
  11. @WebServlet("/pic/*")
  12. public class ShowServlet extends HttpServlet {
  13. @Override
  14. protected void doGet(HttpServletRequest req, HttpServletResponse resp)
  15. throws ServletException, IOException {
  16. String requestURI = req.getRequestURI();
  17. String action = requestURI.replace(req.getContextPath() + "/pic/", "");
  18. if ("view".equals(action)){
  19. show(req,resp);
  20. }
  21. if ("download".equals(action)){
  22. resp.setHeader("Content-Disposition","attachment;filename=threeGirls.jpg");
  23. show(req,resp);
  24. }
  25. }
  26. private void show(HttpServletRequest req, HttpServletResponse resp)
  27. throws IOException {
  28. String realPath = getServletContext().getRealPath("/threeGirls.jpg");
  29. FileInputStream inputStream = new FileInputStream(realPath);
  30. ServletOutputStream outputStream = resp.getOutputStream();
  31. int length = 0;
  32. byte[] bytes = new byte[1024];
  33. while ((length = inputStream.read(bytes)) != -1) {
  34. outputStream.write(bytes, 0, length);
  35. }
  36. }
  37. }

改进版

  1. package com.simon.download;
  2. import javax.servlet.ServletException;
  3. import javax.servlet.ServletOutputStream;
  4. import javax.servlet.annotation.WebServlet;
  5. import javax.servlet.http.HttpServlet;
  6. import javax.servlet.http.HttpServletRequest;
  7. import javax.servlet.http.HttpServletResponse;
  8. import java.io.FileInputStream;
  9. import java.io.IOException;
  10. @WebServlet("/pic2")
  11. public class ShowServlet2 extends HttpServlet {
  12. @Override
  13. protected void doGet(HttpServletRequest req, HttpServletResponse resp)
  14. throws ServletException, IOException {
  15. // String requestURI = req.getRequestURI();
  16. // String action = requestURI.replace(req.getContextPath() + "/pic/", "");
  17. String action = req.getParameter("op");
  18. if ("view2".equals(action)){
  19. show(req,resp);
  20. }
  21. if ("download2".equals(action)){
  22. resp.setHeader("Content-Disposition","attachment;filename=threeGirls.jpg");
  23. show(req,resp);
  24. }
  25. }
  26. private void show(HttpServletRequest req, HttpServletResponse resp)
  27. throws IOException {
  28. String realPath = getServletContext().getRealPath("/threeGirls.jpg");
  29. FileInputStream inputStream = new FileInputStream(realPath);
  30. ServletOutputStream outputStream = resp.getOutputStream();
  31. int length = 0;
  32. byte[] bytes = new byte[1024];
  33. while ((length = inputStream.read(bytes)) != -1) {
  34. outputStream.write(bytes, 0, length);
  35. }
  36. }
  37. }

文件上传

需求:将一个图片文件上传到web目录下的image目录的threeGirls.jpg文件去。

失败版

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. </head>
  7. <body>
  8. <form action="/app/upload1" enctype="multipart/form-data" method="post">
  9. <input type="file" name="image"><br>
  10. <input type="submit">
  11. </form>
  12. </body>
  13. </html>
  1. package com.simon.upload;
  2. import javax.servlet.ServletException;
  3. import javax.servlet.ServletInputStream;
  4. import javax.servlet.annotation.WebServlet;
  5. import javax.servlet.http.HttpServlet;
  6. import javax.servlet.http.HttpServletRequest;
  7. import javax.servlet.http.HttpServletResponse;
  8. import java.io.File;
  9. import java.io.FileOutputStream;
  10. import java.io.IOException;
  11. @WebServlet("/upload1")
  12. public class UploadServlet1 extends HttpServlet {
  13. @Override
  14. protected void doPost(HttpServletRequest req, HttpServletResponse resp)
  15. throws ServletException, IOException {
  16. //先拿到请求报文的输入流
  17. ServletInputStream inputStream = req.getInputStream();
  18. //放到服务器的某个地方,比如部署根目录的image/threeGirls.jpg
  19. String realPath = getServletContext().getRealPath("/image/threeGirls.jpg");
  20. File file = new File(realPath);
  21. if (!file.getParentFile().exists()){
  22. file.getParentFile().mkdirs();
  23. }
  24. FileOutputStream outputStream = new FileOutputStream(file);
  25. byte[] bytes = new byte[1024];
  26. int length = 0;
  27. while ((length=inputStream.read(bytes)) != -1){
  28. outputStream.write(bytes,0,length);
  29. }
  30. outputStream.close();
  31. }
  32. }

image.png

解决办法

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. </head>
  7. <body>
  8. <form action="/app/upload2" enctype="multipart/form-data" method="post">
  9. <input type="file" name="image"><br>
  10. <input type="text" name="username"><br>
  11. <input type="password" name="password"><br>
  12. <input type="submit">
  13. </form>
  14. </body>
  15. </html>
  1. package com.simon.upload;
  2. import org.apache.commons.fileupload.FileItem;
  3. import org.apache.commons.fileupload.FileUploadException;
  4. import org.apache.commons.fileupload.disk.DiskFileItemFactory;
  5. import org.apache.commons.fileupload.servlet.ServletFileUpload;
  6. import javax.servlet.ServletContext;
  7. import javax.servlet.ServletException;
  8. import javax.servlet.ServletInputStream;
  9. import javax.servlet.annotation.WebServlet;
  10. import javax.servlet.http.HttpServlet;
  11. import javax.servlet.http.HttpServletRequest;
  12. import javax.servlet.http.HttpServletResponse;
  13. import java.io.File;
  14. import java.io.FileOutputStream;
  15. import java.io.IOException;
  16. import java.util.Iterator;
  17. import java.util.List;
  18. //提交含文件的表单,上传到服务器
  19. @WebServlet("/upload2")
  20. public class UploadServlet2 extends HttpServlet {
  21. @Override
  22. protected void doPost(HttpServletRequest req, HttpServletResponse resp)
  23. throws ServletException, IOException {
  24. List<FileItem> fileItems = null;
  25. DiskFileItemFactory itemFactory = null;
  26. FileItem item = null;
  27. //确保request对象包含上传的文件
  28. boolean isMultipart = ServletFileUpload.isMultipartContent(req);
  29. if (!isMultipart) return;
  30. //创建对应form表单key-value工厂,用以缓存临时文件
  31. DiskFileItemFactory factory = new DiskFileItemFactory();
  32. ServletContext servletContext = getServletContext();
  33. File repository = (File) servletContext
  34. .getAttribute("javax.servlet.context.tempdir");
  35. factory.setRepository(repository);
  36. //将缓存区的文件提交给request以供后续对象来解析
  37. ServletFileUpload upload = new ServletFileUpload(factory);
  38. try {
  39. fileItems = upload.parseRequest(req);
  40. Iterator<FileItem> iterator = fileItems.iterator();
  41. while (iterator.hasNext()){
  42. item = iterator.next();
  43. if (item.isFormField()){
  44. processUploadedFile(item);
  45. }else {
  46. processFormField(item);
  47. }
  48. }
  49. } catch (FileUploadException e) {
  50. e.printStackTrace();
  51. }
  52. //根据form表单里key值是否为文件类型,分类解析
  53. //最终将文件写入到硬盘的某个位置
  54. String realPath = getServletContext().getRealPath("/image/OIP.jpg");
  55. File file = new File(realPath);
  56. }
  57. private void processFormField(FileItem item) {
  58. String name = item.getFieldName();
  59. String value = item.getString();
  60. System.out.println("name:" + name);
  61. System.out.println("value:" + value);
  62. }
  63. private void processUploadedFile(FileItem item) {
  64. String fieldName = item.getFieldName();
  65. String fileName = item.getName();
  66. String contentType = item.getContentType();
  67. boolean isInMemory = item.isInMemory();
  68. long sizeInBytes = item.getSize();
  69. System.out.println("fieldName:" + fieldName);
  70. System.out.println("fileName:" + fileName);
  71. System.out.println("contentType:" + contentType);
  72. System.out.println("isInMemory:" + isInMemory);
  73. System.out.println("sizeBytes:" + sizeInBytes);
  74. String image = getServletContext().getRealPath("image");
  75. String realPath = image + "/" + fileName;
  76. File file = new File(realPath);
  77. try {
  78. item.write(file);
  79. } catch (Exception e) {
  80. e.printStackTrace();
  81. }
  82. }
  83. }

image.png
image.pngimage.png
又失败了,嘤嘤嘤~~~~