Servlet详解 
一、什么是Servlet 
1、Servlet 是 JavaEE 规范之一。规范就是接口
二、手动实现HelloServlet程序 
1、导入依赖 
1 2 3 4 5 6 7 8 9 10 11 12 13 <dependency >     <groupId > jakarta.servlet.jsp</groupId >      <artifactId > jakarta.servlet.jsp-api</artifactId >      <version > 3.0.0</version >      <scope > provided</scope >  </dependency > <dependency >     <groupId > jakarta.servlet</groupId >      <artifactId > jakarta.servlet-api</artifactId >      <version > 5.0.0</version >      <scope > provided</scope >  </dependency > 
2、编写servlet类继承HttpServlet 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public  class  HelloServlet  extends  HttpServlet      @Override      protected  void  doGet (HttpServletRequest req, HttpServletResponse resp)  throws  ServletException, IOException          System.out.println("进入了doGet" );                  resp.setContentType("text/html" );          resp.setCharacterEncoding("utf-8" );         PrintWriter out = resp.getWriter();          out.print("HelloServlet" );     }     @Override      protected  void  doPost (HttpServletRequest req, HttpServletResponse resp)  throws  ServletException, IOException          doGet(req, resp);     } } 
3、到 web.xml 中去配置映射 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 <?xml version="1.0" encoding="UTF-8"?> <web-app  xmlns ="https://jakarta.ee/xml/ns/jakartaee"  xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation ="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd" version ="5.0"  metadata-complete ="true" >          <servlet >                    <servlet-name > HelloServlet</servlet-name >                    <servlet-class > com.nichu.servlet.HelloServlet</servlet-class >       </servlet >            <servlet-mapping >            <servlet-name > HelloServlet</servlet-name >                   <url-pattern > /hello</url-pattern >       </servlet-mapping >  </web-app > 
4、配置Tomcat 
5、启动项目,访问路径 
三、Servlet原理 
Servlet是由Web服务器调用,web服务器在收到浏览器请求之后,会:
四、Mapping问题 
1. 一个Servlet可以指定一个映射路径 
1 2 3 4 <servlet-mapping >     <servlet-name > hello</servlet-name >      <url-pattern > /hello</url-pattern >  </servlet-mapping > 
2. 一个Servlet可以指定多个映射路径 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 <servlet-mapping >     <servlet-name > hello</servlet-name >      <url-pattern > /hello</url-pattern >  </servlet-mapping > <servlet-mapping >     <servlet-name > hello</servlet-name >      <url-pattern > /hello2</url-pattern >  </servlet-mapping > <servlet-mapping >     <servlet-name > hello</servlet-name >      <url-pattern > /hello3</url-pattern >  </servlet-mapping > <servlet-mapping >     <servlet-name > hello</servlet-name >      <url-pattern > /hello4</url-pattern >  </servlet-mapping > <servlet-mapping >     <servlet-name > hello</servlet-name >      <url-pattern > /hello5</url-pattern >  </servlet-mapping > 
3. 一个Servlet可以指定通用映射路径 
1 2 3 4 <servlet-mapping >     <servlet-name > hello</servlet-name >      <url-pattern > /hello/*</url-pattern >  </servlet-mapping > 
4. 默认请求路径 
1 2 3 4 5 <servlet-mapping >     <servlet-name > hello</servlet-name >      <url-pattern > /*</url-pattern >  </servlet-mapping > 
5. 指定一些后缀或者前缀等等…. 
1 2 3 4 5 6 7 8 <servlet-mapping >     <servlet-name > hello</servlet-name >      <url-pattern > *.nichu</url-pattern >  </servlet-mapping > 
6. 优先级问题 
指定了固有的映射路径优先级最高,如果找不到就会走默认的处理请求(404);
1 2 3 4 5 6 7 8 9 <servlet >     <servlet-name > error</servlet-name >      <servlet-class > com.kuang.servlet.ErrorServlet</servlet-class >  </servlet > <servlet-mapping >     <servlet-name > error</servlet-name >      <url-pattern > /*</url-pattern >  </servlet-mapping > 
五、ServletContext 
web容器在启动的时候,它会为每个web程序都创建一个对应的ServletContext对象,它代表了当前的web应用
应用: 
1. 共享数据 
在一个Servlet中写入的数据,在另一个Servlet中可以访问。 
 
1 2 3 4 5 6 7 8 9 10 11 public  class  Servlet01  extends  HttpServlet      @Override      protected  void  doGet (HttpServletRequest req, HttpServletResponse resp)  throws  ServletException, IOException          PrintWriter writer = resp.getWriter();         writer.print("hello,Servlet" );         ServletContext contest = this .getServletContext();         String name="倪矗" ;         contest.setAttribute("name" ,name);     } } 
1 2 3 4 5 6 7 8 9 10 public  class  Servlet02  extends  HttpServlet      @Override      protected  void  doGet (HttpServletRequest req, HttpServletResponse resp)  throws  ServletException, IOException          ServletContext context = this .getServletContext();         resp.setContentType("text/html" );         resp.setCharacterEncoding("utf-8" );         String name = (String) context.getAttribute("name" );         resp.getWriter().print("name:" +name);     } } 
2. 获得初始化参数 
1 2 3 4 5 6 7 8 9 10 11 12 13 14   <context-param >      <param-name > url</param-name >      <param-value > jdbc:mysql://localhost:3306/mybatis</param-value >    </context-param >    <servlet >      <servlet-name > url</servlet-name >      <servlet-class > com.nichu.servlet.Servlet03</servlet-class >    </servlet >    <servlet-mapping >      <servlet-name > url</servlet-name >      <url-pattern > /DB</url-pattern >    </servlet-mapping >  
1 2 3 4 5 6 7 8 9 10 public  class  Servlet03  extends  HttpServlet      @Override      protected  void  doGet (HttpServletRequest req, HttpServletResponse resp)  throws  ServletException, IOException                   ServletContext context = this .getServletContext();                  String url = context.getInitParameter("url" );         resp.getWriter().println(url);     } } 
3. 请求转发(getRequestDispatcher) 
1 2 3 4 5 6 7 8 9 10 11 public  class  Servlet04  extends  HttpServlet      @Override      protected  void  doGet (HttpServletRequest req, HttpServletResponse resp)  throws  ServletException, IOException          ServletContext context = this .getServletContext();                  RequestDispatcher requestDispatcher = context.getRequestDispatcher("/DB" );                  requestDispatcher.forward(req,resp);     } } 
4. 读取资源文件 
1 2 3 username=root password=12354654  
1 2 3 4 5 6 7 8 9 10 11 12 13 protected  void  doGet (HttpServletRequest req, HttpServletResponse resp)  throws  ServletException, IOException     ServletContext context = this .getServletContext();              InputStream is = context.getResourceAsStream("/WEB-INF/classes/db.properties" );              Properties properties = new  Properties();              properties.load(is);              String usr = properties.getProperty("username" );     String pwd = properties.getProperty("password" );     resp.getWriter().println(usr+":" +pwd); } 
访问测试即可;
五、HttpServletResponse 
web服务器接收到客户端的http请求,针对这个请求,分别创建一个代表请求的HttpServletRequest对象,代表响应的一个HttpServletResponse;
如果要获取客户端请求过来的参数:找HttpServletRequest 
如果要给客户端响应一些信息:找HttpServletResponse 
 
1. 简单分类 
负责向浏览器发送数据的方法
1 2 ServletOutputStream getOutputStream ()  throws  IOException ;PrintWriter getWriter ()  throws  IOException ;
负责向浏览器发送响应头的方法
1 2 3 4 5 6 7 8 9 10 void  setCharacterEncoding (String var1) void  setContentLength (int  var1) void  setContentLengthLong (long  var1) void  setContentType (String var1) void  setDateHeader (String var1, long  var2) void  addDateHeader (String var1, long  var2) void  setHeader (String var1, String var2) void  addHeader (String var1, String var2) void  setIntHeader (String var1, int  var2) void  addIntHeader (String var1, int  var2) 
响应的状态码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 int  SC_CONTINUE = 100 ;int  SC_SWITCHING_PROTOCOLS = 101 ;int  SC_OK = 200 ;int  SC_CREATED = 201 ;int  SC_ACCEPTED = 202 ;int  SC_NON_AUTHORITATIVE_INFORMATION = 203 ;int  SC_NO_CONTENT = 204 ;int  SC_RESET_CONTENT = 205 ;int  SC_PARTIAL_CONTENT = 206 ;int  SC_MULTIPLE_CHOICES = 300 ;int  SC_MOVED_PERMANENTLY = 301 ;int  SC_MOVED_TEMPORARILY = 302 ;int  SC_FOUND = 302 ;int  SC_SEE_OTHER = 303 ;int  SC_NOT_MODIFIED = 304 ;int  SC_USE_PROXY = 305 ;int  SC_TEMPORARY_REDIRECT = 307 ;int  SC_BAD_REQUEST = 400 ;int  SC_UNAUTHORIZED = 401 ;int  SC_PAYMENT_REQUIRED = 402 ;int  SC_FORBIDDEN = 403 ;int  SC_NOT_FOUND = 404 ;int  SC_METHOD_NOT_ALLOWED = 405 ;int  SC_NOT_ACCEPTABLE = 406 ;int  SC_PROXY_AUTHENTICATION_REQUIRED = 407 ;int  SC_REQUEST_TIMEOUT = 408 ;int  SC_CONFLICT = 409 ;int  SC_GONE = 410 ;int  SC_LENGTH_REQUIRED = 411 ;int  SC_PRECONDITION_FAILED = 412 ;int  SC_REQUEST_ENTITY_TOO_LARGE = 413 ;int  SC_REQUEST_URI_TOO_LONG = 414 ;int  SC_UNSUPPORTED_MEDIA_TYPE = 415 ;int  SC_REQUESTED_RANGE_NOT_SATISFIABLE = 416 ;int  SC_EXPECTATION_FAILED = 417 ;int  SC_INTERNAL_SERVER_ERROR = 500 ;int  SC_NOT_IMPLEMENTED = 501 ;int  SC_BAD_GATEWAY = 502 ;int  SC_SERVICE_UNAVAILABLE = 503 ;int  SC_GATEWAY_TIMEOUT = 504 ;int  SC_HTTP_VERSION_NOT_SUPPORTED = 505 ;
2. 下载文件 
要获取下载文件的路径 
下载的文件名是啥? 
设置想办法让浏览器能够支持下载我们需要的东西 
获取下载文件的输入流 
创建缓冲区 
获取OutputStream对象 
将FileOutputStream流写入到buffer缓冲区 
使用OutputStream将缓冲区中的数据输出到客户端! 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 protected  void  doGet (HttpServletRequest req, HttpServletResponse resp)  throws  ServletException, IOException          String realPath ="/Users/haikez/Desktop/javaweb/javaweb-01-servlet/javaweb-02-servlet/src/main/resources/1.png" ;          String filename = realPath.substring(realPath.lastIndexOf("/" )+1 );          resp.setHeader("Content-Disposition" ,"attachment;filename=" + URLEncoder.encode(filename,"UTF-8" ));          FileInputStream in = new  FileInputStream(new  File(realPath));          int  len = 0 ;     byte [] buffer = new  byte [1024 ];          ServletOutputStream out = resp.getOutputStream();          while  ((len=in.read(buffer)) != -1 ) {         out.write(buffer,0 ,len);     }     in.close();     out.close(); } 
4. 验证码功能 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 public  class  ImageServlet  extends  HttpServlet      @Override      protected  void  doGet (HttpServletRequest req, HttpServletResponse resp)  throws  ServletException, IOException                   resp.setHeader("refresh" ,"3" );                  BufferedImage image = new  BufferedImage(80 ,20 ,BufferedImage.TYPE_INT_RGB);                  Graphics2D g = (Graphics2D) image.getGraphics();                   g.setColor(Color.white);         g.fillRect(0 ,0 ,80 ,20 );                  g.setColor(Color.BLUE);         g.setFont(new  Font(null ,Font.BOLD,20 ));         g.drawString(makeNum(),0 ,20 );                  resp.setContentType("image/jpeg" );                  resp.setDateHeader("expires" ,-1 );         resp.setHeader("Cache-Control" ,"no-cache" );         resp.setHeader("Pragma" ,"no-cache" );                  ImageIO.write(image,"jpg" , resp.getOutputStream());     }          private  String makeNum ()          Random random = new  Random();         String num = random.nextInt(9999999 ) + "" ;         StringBuffer sb = new  StringBuffer();         for  (int  i = 0 ; i < 7 -num.length() ; i++) {             sb.append("0" );         }         num = sb.toString() + num;         return  num;     }     @Override      protected  void  doPost (HttpServletRequest req, HttpServletResponse resp)  throws  ServletException, IOException          doGet(req, resp);     } } 
5. 实现重定向(resp.sendRedirect(“/r/success.jsp”)) 
重定向和转发的区别? 
请求转发url不会产生变化,重定向会发生变化 
请求转发可以携带参数,重定向不能携带参数 
请求转发只能发送一个请求,重定向至少发送两次请求 
 
简单实现登录重定向: 
1 2 3 4 5 6 7 <%--这里提交的路径,需要寻找到项目的路径--%> <%--${pageContext.request.contextPath}代表当前的项目--%> <form action="${pageContext.request.contextPath}/login"  method="get" >     用户名:<input type="text"  name="username" > <br>     密码:<input type="password"  name="password" > <br>     <input type="submit" > </form> 
1 2 3 4 5 6 7 8 9 @Override protected  void  doGet (HttpServletRequest req, HttpServletResponse resp)  throws  ServletException, IOException          String username = req.getParameter("username" );     String password = req.getParameter("password" );     System.out.println(username+":" +password);          resp.sendRedirect("/r/success.jsp" ); } 
1 2 3 4 5 6 7 8 <servlet >   <servlet-name > requset</servlet-name >    <servlet-class > com.kuang.servlet.RequestTest</servlet-class >  </servlet > <servlet-mapping >   <servlet-name > requset</servlet-name >    <url-pattern > /login</url-pattern >  </servlet-mapping > 
1 2 3 4 5 6 7 8 9 <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html > <head >     <title > Title</title >  </head > <body > <h1 > Success</h1 > </body > </html > 
六、HttpServletRequest 
HttpServletRequest代表客户端的请求,用户通过Http协议访问服务器,HTTP请求中的所有信息会被封装到HttpServletRequest,通过这个HttpServletRequest的方法,获得客户端的所有信息;
1 2 3 4 5 6 7 8 9 10 @WebServlet("/req") public  class  ReqServlet  extends  HttpServlet      @Override      protected  void  doGet (HttpServletRequest req, HttpServletResponse resp)  throws  ServletException, IOException          System.out.println("url路径:" +req.getRequestURL());         System.out.println("uri路径:" +req.getRequestURI());         System.out.println("context路径:" +req.getContextPath());         req.getRequestDispatcher("/file" ).forward(req,resp);     } } 
狂笔记