6. Servlet

6.1 Servlet简介

Servlet就是sun公司开发动态web的一门技术

sun在这些API中提供一个接口叫做Servlet,如果想开发一个Servlet程序,只需要完成两个小步骤

  • 编写一个类,实现Servlet接口

  • 把开发好的Java类部署到web服务器中

把实现了Servlet接口的Java程序叫做Servlet

6.2 HelloServlet

  1. 构建一个普通的maven项目,删掉里边的src目录,以后学习就要在这个项目内建立Model,这个空的工程就是Maven的主工程;

  2. 关于Maven父子工程的理解

父项目中会有

 <modules>
         <module>Servlet</module>
     </modules>

 

子项目会有

 <parent>
         <artifactId>JavaWeb-Servlet</artifactId>
         <groupId>com.zhou</groupId>
         <version>1.0-SNAPSHOT</version>
     </parent>

 

父项目中的Java子项目可以直接使用

 son extends father
  1. Maven环境优化

    1. 修改web.xml为最新版本,此后在此处进行Servlet类class的注册,确定相应的Servlet类(Servlet-class)对应的相应域名映射(Servlet-mapping)

       <?xml version="1.0" encoding="UTF-8"?>
       <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                                http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
                version="4.0"
                metadata-complete="true">
       </web-app>

       

    2. 将maven的结构搭建完整

  2. 编写一个Servlet程序

    1. 编写一个普通类

    2. 实现Servlet接口,直接继承HttpServlet

 
 1 package Servlet;
 2  3  import javax.servlet.ServletException;
 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.io.PrintWriter;
 9 10  public class HelloServlet extends HttpServlet {
11      @Override
12      protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
13          PrintWriter writer = resp.getWriter();//响应流
14          writer.print("Hello,Servlet");
15      }
16 17      @Override
18      protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
19          doGet(req, resp);
20      }
21  }

 

  1. 编写Servlet的映射

为什么需要映射?

写的是Java程序,但是要通过浏览器访问,而浏览器需要连接web服务器,所以需要在web服务器中注册写的Servlet,还续给它一个浏览器能够访问的路径

 <!--        注册Servlet-->
     <servlet>
       <servlet-name>hello</servlet-name>
       <servlet-class>Servlet.HelloServlet</servlet-class>
     </servlet>
 <!--        Servlet的请求路径-->
     <servlet-mapping>
       <servlet-name>hello</servlet-name>
       <url-pattern>/hello</url-pattern>
     </servlet-mapping>

 

  1. 配置Tomcat

    注意:配置项目发布的路径

    和5.7类似,可能没有Artifact,有解决方法:

    idea配置 Tomcat Deployment添加时没有Artifact...选择的解决方案

    https://blog.csdn.net/Jae_Wang/article/details/81208706

  2. 启动测试

点击启动按钮,即可弹出浏览器,选择合适的网址查看效果

 

 

 

后台控制台:

 

 

 

6.3 Servlet原理

Servlet是由Web服务器调用,web服务器在收到浏览器请求之后

 

 

 

 

 

 

6.4 Mapping问题

  1. 一个Servlet可以指定一个映射路径

     <servlet-mapping>
       <servlet-name>hello</servlet-name>
       <url-pattern>/hello</url-pattern>
     </servlet-mapping>

     

  2. 一个Servlet可以指定多个映射路径

     1  <servlet-mapping>
     2        <servlet-name>hello</servlet-name>
     3        <url-pattern>/hello</url-pattern>
     4      </servlet-mapping>
     5      <servlet-mapping>
     6        <servlet-name>hello</servlet-name>
     7        <url-pattern>/hello1</url-pattern>
     8      </servlet-mapping>
     9      <servlet-mapping>
    10        <servlet-name>hello</servlet-name>
    11        <url-pattern>/hello2</url-pattern>
    12      </servlet-mapping>
    13      <servlet-mapping>
    14        <servlet-name>hello</servlet-name>
    15        <url-pattern>/hello3</url-pattern>
    16      </servlet-mapping>
    17      <servlet-mapping>
    18        <servlet-name>hello</servlet-name>
    19        <url-pattern>/hello4</url-pattern>
    20      </servlet-mapping>
    21      <servlet-mapping>
    22        <servlet-name>hello</servlet-name>
    23        <url-pattern>/hello5</url-pattern>
    24      </servlet-mapping>

     

  3. 一个Servlet可以指定通用映射路径 

    <servlet-mapping>
       <servlet-name>hello</servlet-name>
       <url-pattern>/hello/*</url-pattern>
     </servlet-mapping>

     

  4. 默认请求路径

     <servlet-mapping>
       <servlet-name>hello</servlet-name>
       <url-pattern>/*</url-pattern>
     </servlet-mapping>

     

  5. 指定一些后缀或者前缀等等

     <!--  可以自定义后缀实现请求映射
     注意点:*前面不能加项目映射的路径-->
         <servlet-mapping>
             <servlet-name>hello</servlet-name>
             <url-pattern>*.xxx</url-pattern>
         </servlet-mapping>

     

  6. 优先级问题

    指定了固有的映射路径优先级最高,如果找不到就会走默认的处理请求

 <!--    404-->
     <servlet>
         <servlet-name>error</servlet-name>
         <servlet-class>Servlet.ErrorServlet</servlet-class>
     </servlet>
     <servlet-mapping>
         <servlet-name>error</servlet-name>
         <url-pattern>/*</url-pattern>
     </servlet-mapping>

 

 

 

 

/*表示在加入/Servlet之后的默认(后边输入什么都一样)打开执行ErrorServlet程序

 1  package Servlet;
 2  3  import javax.servlet.ServletException;
 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.io.PrintWriter;
 9 10  public class ErrorServlet extends HttpServlet {
11      @Override
12      protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
13          resp.setContentType("text/html");
14          resp.setCharacterEncoding("utf-8");
15          PrintWriter writer = resp.getWriter();
16          writer.print("<h1>404</h1>");
17      }
18 19      @Override
20      protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
21          doGet(req,resp);
22      }
23  }

 

6.5 ServletContext对象

web容器在启动的时候,它会为每个web程序都创建一个对应的ServletContext对象,它代表了当前的web应用。

1. 共享数据

  • 在这个Servlet中保存的数据,可以在另外一个Servlet中拿到

首先创建一个键值对setAttribute

 1  package com.zhou.servlet;
 2  3  import javax.servlet.ServletContext;
 4  import javax.servlet.ServletException;
 5  import javax.servlet.http.HttpServlet;
 6  import javax.servlet.http.HttpServletRequest;
 7  import javax.servlet.http.HttpServletResponse;
 8  import java.io.IOException;
 9 10  public class HelloServlet extends HttpServlet {
11      @Override
12      protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
13  //        this.getInitParameter();      初始化参数
14  //        this.getServletConfig();      Servlet配置
15  //        this.getServletContext();       Servlet上下文
16          ServletContext context = this.getServletContext();
17 18          String username = "zhou";//数据
19          context.setAttribute("username",username);//设置键值对,将一个数据保存在ServletContext中,名字为username,值为username
20 21          System.out.println("Hello");
22      }
23  }

 

然后进行读取

 
 1 package com.zhou.servlet;
 2  3  import javax.servlet.ServletContext;
 4  import javax.servlet.ServletException;
 5  import javax.servlet.http.HttpServlet;
 6  import javax.servlet.http.HttpServletRequest;
 7  import javax.servlet.http.HttpServletResponse;
 8  import java.io.IOException;
 9 10  public class GetServlet extends HttpServlet {
11      @Override
12      protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
13          ServletContext context = this.getServletContext();
14          String username = (String) context.getAttribute("username");
15 16          resp.setContentType("text/html");
17          resp.setCharacterEncoding("utf-8");
18          resp.getWriter().print("名字"+username);
19      }
20 21      @Override
22      protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
23          super.doPost(req, resp);
24      }
25  }

 

然后配置xml

 <servlet>
     <servlet-name>getServlet</servlet-name>
     <servlet-class>com.zhou.servlet.GetServlet</servlet-class>
 </servlet>
 <servlet-mapping>
     <servlet-name>getServlet</servlet-name>
     <url-pattern>/getServlet</url-pattern>
 </servlet-mapping>

 

测试访问结果:先访问/hello,然后访问/getServlet,可以将数据读取

 

 

 

控制台Services变中文的方法:Tomcat文件夹的conf文件夹中找到logging.properties文件打开,UTF-8换成GBK

再创建一个Module和HelloServlet类,测试后台输出程序

 package com.zhou.servlet;
 ​
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 ​
 public class HelloServlet extends HttpServlet {
     @Override
     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         System.out.println("Hello");
     }
 }

 

在web.xml中注册

 <?xml version="1.0" encoding="UTF-8"?>
 <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                          http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
          version="4.0"
          metadata-complete="true">
 <!--    新添加注册信息-->
     <servlet>
         <servlet-name>hello</servlet-name>
         <servlet-class>com.zhou.servlet.HelloServlet</servlet-class>
     </servlet>
     <servlet-mapping>
         <servlet-name>hello</servlet-name>
         <!--        新添加后缀/hello后可访问hello指代的HelloServlet类-->
         <url-pattern>/hello</url-pattern>
     </servlet-mapping>
 </web-app>

 

运行Tomcat前添加Servlet组件Artifact,同6.2.6

之后运行,在地址后缀添加/hello

可在后台输出看到打印的Hello

 

 

 

2. 初始化参数InitParameter

 package com.zhou.servlet;
 ​
 import javax.servlet.ServletContext;
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 ​
 public class ServletDemo extends HttpServlet {
     @Override
     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         ServletContext context = this.getServletContext();
         String url = context.getInitParameter("url");
         resp.getWriter().print(url);
     }
 ​
     @Override
     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         super.doPost(req, resp);
     }
 }
<servlet>
     <servlet-name>gp</servlet-name>
     <servlet-class>com.zhou.servlet.ServletDemo</servlet-class>
 </servlet>
 <servlet-mapping>
     <servlet-name>gp</servlet-name>
     <url-pattern>/gp</url-pattern>
 </servlet-mapping>

3. 请求转发

重定向与转发的区别

A要拿C的资源,B没有,B做转发

A要拿C的资源,B没有,B告诉A去找C,重定向

 package com.zhou.servlet;
 ​
 import javax.servlet.RequestDispatcher;
 import javax.servlet.ServletContext;
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 ​
 public class ServletDemo02 extends HttpServlet {
     @Override
     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         System.out.println("进入了ServletDemo02");
         ServletContext context = this.getServletContext();
         RequestDispatcher requestDispatcher = context.getRequestDispatcher("/gp");//转发的请求路径
         requestDispatcher.forward(req,resp);//调用forward实现请求转发
         //转发跳转到了/gp页面
     }
 ​
     @Override
     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         super.doPost(req, resp);
     }
 }

 

 <servlet>
     <servlet-name>s02</servlet-name>
     <servlet-class>com.zhou.servlet.ServletDemo02</servlet-class>
 </servlet>
 <servlet-mapping>
     <servlet-name>s02</servlet-name>
     <url-pattern>/s02</url-pattern>
 </servlet-mapping>

 

 

 

 

转发跳到了/gp的页面

4. 读取资源文件

Properties

  • 在java目录下新建properties

  • 在resource目录下新建properties

都被打包到了同一个路径下:classes,这个路径为classpath

思路:需要一个文件流

 package com.zhou.servlet;
 ​
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.Properties;
 ​
 public class ServletDemo03 extends HttpServlet {
     @Override
     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");
         Properties prop = new Properties();
         prop.load(is);
         String user = prop.getProperty("username");
         String pwd = prop.getProperty("password");
         resp.getWriter().print(user+":"+pwd);
     }
 ​
     @Override
     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         super.doPost(req, resp);
     }
 }

 

 <servlet>
     <servlet-name>s03</servlet-name>
     <servlet-class>com.zhou.servlet.ServletDemo03</servlet-class>
 </servlet>
 <servlet-mapping>
     <servlet-name>s03</servlet-name>
     <url-pattern>/s03</url-pattern>
 </servlet-mapping>

 

db.properties

 username=root
 password=123456

进行访问测试

 

 

 

6.6 HttpServletResponse

web服务器接收到客户端的http请求,针对这个请求,分别创建一个代表请求的HttpServletResponse对象,代表相应的一个HttpServletResponse

  • 如果要获取客户端请求过来的参数:找HttpServletRequest

  • 如果要给客户端响应一些信息:找HttpServletResponse

1. 简单分类

负责向浏览器发送数据的方法

 ServletOutputStream getOutputStream() throws IOException;
 ​
 PrintWriter getWriter() throws IOException;

 

负责向浏览器发送响应头的方法

 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);

 

响应的状态码

重点:200 404 500

 1  int SC_CONTINUE = 100;
 2  int SC_SWITCHING_PROTOCOLS = 101;
 3  int SC_OK = 200;
 4  int SC_CREATED = 201;
 5  int SC_ACCEPTED = 202;
 6  int SC_NON_AUTHORITATIVE_INFORMATION = 203;
 7  int SC_NO_CONTENT = 204;
 8  int SC_RESET_CONTENT = 205;
 9  int SC_PARTIAL_CONTENT = 206;
10  int SC_MULTIPLE_CHOICES = 300;
11  int SC_MOVED_PERMANENTLY = 301;
12  int SC_MOVED_TEMPORARILY = 302;
13  int SC_FOUND = 302;
14  int SC_SEE_OTHER = 303;
15  int SC_NOT_MODIFIED = 304;
16  int SC_USE_PROXY = 305;
17  int SC_TEMPORARY_REDIRECT = 307;
18  int SC_BAD_REQUEST = 400;
19  int SC_UNAUTHORIZED = 401;
20  int SC_PAYMENT_REQUIRED = 402;
21  int SC_FORBIDDEN = 403;
22  int SC_NOT_FOUND = 404;
23  int SC_METHOD_NOT_ALLOWED = 405;
24  int SC_NOT_ACCEPTABLE = 406;
25  int SC_PROXY_AUTHENTICATION_REQUIRED = 407;
26  int SC_REQUEST_TIMEOUT = 408;
27  int SC_CONFLICT = 409;
28  int SC_GONE = 410;
29  int SC_LENGTH_REQUIRED = 411;
30  int SC_PRECONDITION_FAILED = 412;
31  int SC_REQUEST_ENTITY_TOO_LARGE = 413;
32  int SC_REQUEST_URI_TOO_LONG = 414;
33  int SC_UNSUPPORTED_MEDIA_TYPE = 415;
34  int SC_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
35  int SC_EXPECTATION_FAILED = 417;
36  int SC_INTERNAL_SERVER_ERROR = 500;
37  int SC_NOT_IMPLEMENTED = 501;
38  int SC_BAD_GATEWAY = 502;
39  int SC_SERVICE_UNAVAILABLE = 503;
40  int SC_GATEWAY_TIMEOUT = 504;
41  int SC_HTTP_VERSION_NOT_SUPPORTED = 505;

 

2. 常见应用

  1. 向浏览器输出消息getWriter等等

  2. 下载文件

    1. 要获取下载的路径

    2. 下载的文件名

    3. 设置想办法让浏览器能够支持下载需要的东西

    4. 获取下载文件的输入流

    5. 创建缓冲区

    6. 获取OutputStream对象

    7. 将FileOutputStream流写入到buffer缓冲区

    8. 使用OutputStream将缓冲区中的数据输出到客户端

     1  import javax.servlet.ServletException;
     2  import javax.servlet.ServletOutputStream;
     3  import javax.servlet.http.HttpServlet;
     4  import javax.servlet.http.HttpServletRequest;
     5  import javax.servlet.http.HttpServletResponse;
     6  import java.io.FileInputStream;
     7  import java.io.IOException;
     8  import java.net.URLEncoder;
     9 10  public class FileServlet extends HttpServlet {
    11      @Override
    12      protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    13          //1.获取下载文件的路径
    14          String realPath = "C:\\Users\\88534\\Desktop\\Java入门\\JavaWeb-Servlet\\Response\\src\\main\\resources\\Java.jpg";
    15          System.out.println("下载文件的路径;"+realPath);
    16          //2.下载的文件名
    17          //截取字符串,选取\后边的文字
    18          String fileName = realPath.substring(realPath.lastIndexOf("\\")+1);
    19          //3.设置办法让浏览器能够支持下载需要的东西
    20          // attachment后边是分号不是冒号,UTF -8转码表示可以下载带中文名的文件,否则有可能会乱码
    21          resp.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode(fileName,"UTF-8"));
    22          //4.获取下载文件的输入流
    23          FileInputStream in = new FileInputStream(realPath);
    24          //5.创建缓冲区
    25          int len = 0;
    26          byte[] buffer = new byte[1024];
    27          //6.获取OutputStream
    28          ServletOutputStream out = resp.getOutputStream();
    29          //7.将FileOutputStream流写入到buffer缓冲区,使用OutputStream将缓冲区中的数据输出到客户端
    30          while ((len = in.read(buffer))>0){
    31              out.write(buffer,0,len);
    32          }
    33          in.close();
    34          out.close();
    35      }
    36 37      @Override
    38      protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    39          super.doPost(req, resp);
    40      }
    41  }

     

 <servlet>
     <servlet-name>fileDownload</servlet-name>
     <servlet-class>FileServlet</servlet-class>
 </servlet>
 <servlet-mapping>
     <servlet-name>fileDownload</servlet-name>
     <url-pattern>/down</url-pattern>
 </servlet-mapping>

 

运行Tomcat,地址输入\down就可以下载文件

 

 

 

3. 验证码功能

验证的来源:

前端获取

后端获取:

 1  import javax.imageio.ImageIO;
 2  import javax.servlet.ServletException;
 3  import javax.servlet.http.HttpServlet;
 4  import javax.servlet.http.HttpServletRequest;
 5  import javax.servlet.http.HttpServletResponse;
 6  import java.awt.*;
 7  import java.awt.image.BufferedImage;
 8  import java.io.IOException;
 9  import java.util.Random;
10 11  public class ImageServlet extends HttpServlet {
12      @Override
13      protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
14          //让 浏览器3s自动刷新一次
15          resp.setHeader("refresh","3");
16 17          //在内存中创建一个图片
18          BufferedImage image = new BufferedImage(80, 20, BufferedImage.TYPE_INT_RGB);
19          //得到图片
20          Graphics2D g = (Graphics2D) image.getGraphics();//21          //设置图片的背景颜色
22          g.setColor(Color.white);
23          g.fillRect(0,0,80,20);//画矩形
24          //给图片写数据
25          g.setColor(Color.blue);
26          g.setFont(new Font(null,Font.BOLD,20));
27          g.drawString(makeNum(),0,20);
28          //告诉浏览器,这个请求用图片的方式打开
29          resp.setContentType("image/jpg");
30          //此时网页存在缓存,不让浏览器缓存
31          resp.setDateHeader("expires",-1);
32          resp.setHeader("Cache-Control","no-cache");
33          resp.setHeader("Pragma","no-cache");
34          //把图片写到浏览器
35          ImageIO.write(image,"jpg",resp.getOutputStream());
36      }
37 38      //生成随机数
39      private String makeNum(){
40          Random random = new Random();
41          String num = random.nextInt(99999999) + "";
42          StringBuffer sb = new StringBuffer();
43          for (int i = 0; i < 7 - num.length(); i++) {
44              sb.append("0");//不断刷新,不足7位的话用0补充
45          }
46          String s = sb.toString() + num;
47          return num;//保证都是7位
48      }
49 50      @Override
51      protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
52          super.doPost(req, resp);
53      }
54  }

 

 <servlet>
     <servlet-name>ImageServlet</servlet-name>
     <servlet-class>ImageServlet</servlet-class>
 </servlet>
 <servlet-mapping>
     <servlet-name>ImageServlet</servlet-name>
     <url-pattern>/image</url-pattern>
 </servlet-mapping>

 

 

 

 

4.实现重定向

一个 web资源受到客户端A请求后,B会通知A客户端去访问另外一个web资源C,这个过程叫做重定向。

常见场景:

用户登录

 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 ​
 public class RedirectServlet extends HttpServlet {
     @Override
     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         resp.sendRedirect("/Response_war/image");//需要回退到上一级目录
         /*
         原理:上述语句等效于
         resp.setHeader("Location","/Response_war/image");
         resp.setStatus(302);
          */
     }
 ​
     @Override
     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         super.doPost(req, resp);
     }
 }
 
 <servlet>
     <servlet-name>RedirectServlet</servlet-name>
     <servlet-class>RedirectServlet</servlet-class>
 </servlet>
 <servlet-mapping>
     <servlet-name>RedirectServlet</servlet-name>
     <url-pattern>/redirect</url-pattern>
 </servlet-mapping>

 

地址栏访问/redirect后切换到/image

 

 

面试题:重定向和转发的区别

相同点:

页面都会实现跳转

不同点:

  • 请求转发的时候,url不会发生变化;307

  • 重定向的时候,url地址栏会发生变化;302

5.登录界面

用户的登录需要在JSP文件中加入表单

 <html>
 <body>
 <h2>Hello World!</h2><%--这里提交的路径,需要寻找到项目的路径--%>
 <%--${pageContext.request.contextPath}代表当前的项目--%>
 <form action="${pageContext.request.contextPath}/login" method="get">
 <%--    br换行,get接收,post发送--%>
     用户名:<input type="text" name="username"><br>
     密码:<input type="password" name="password"><br>
     <input type="submit">
 </form>
 <%--中文编码防止乱码--%>
 <%@page contentType="text/html; charset=UTF-8" %>
 </body>
 </html>

 

需要下载maven相应的jsp包

 

 

 

 

在左侧栏中出现jsp的包即表示下载成功

后台只需要表示要进入这个请求

 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 ​
 public class RequestTest extends HttpServlet {
     @Override
     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         System.out.println("进入这个请求了");
     }
 ​
     @Override
     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         super.doPost(req, resp);
     }
 }

 

 <servlet>
     <servlet-name>request</servlet-name>
     <servlet-class>RequestTest</servlet-class>
 </servlet>
 <servlet-mapping>
     <servlet-name>request</servlet-name>
     <url-pattern>/login</url-pattern>
 </servlet-mapping>

 

运行Tomcat进入登录页面,输入用户名和密码提交后可在地址栏找到自己传递的明码账户信息,且后台程序显示已经进入请求程序。

 

 

 

 

接下来对请求进行处理

新建登录成功的JSP文件Success.jsp

 <%@ page contentType="text/html;charset=UTF-8" language="java" %>
 <html>
 <head>
     <title>Title</title>
 </head>
 <body>
 <h1>Success!</h1>
 </body>
 </html>

 

对doGet方法进行添加

 @Override
 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     System.out.println("进入这个请求了");
     //处理请求
     String username = req.getParameter("username");
     String password = req.getParameter("password");
     System.out.println(username+":"+password);
     //重定向时一定要注意路径的正确,要切回到原来的Artifact路径下,否则会404
     resp.sendRedirect("/Response_war/Success.jsp");//重定向到登录成功界面
 }

 

登录成功后完成跳转!

 

 

6.7 HttpServletRequest

HttpServletRequest代表客户端的请求,用户通过Http协议访问服务器,HTTP请求中的所有信息会被封装到HttpServletRequest,通过这个方法获得客户端的所有信息。

req.get一列方法

 

 

1. 获取前端传递的参数

req.getParameter

req.getParamterValues

2. 请求转发

req.getRequestDispatcher(跳转路径).forword(req,resp)

 
 <%@ page contentType="text/html;charset=UTF-8" language="java" %>
 <html>
 <head>
     <title>Title</title>
 </head>
 <body>
 <h1>登录</h1>
 <div>
 <%--    以get接收的方式提交表单,提交我们的login请求--%>
     <form action="${pageContext.request.contextPath}/login" method="get">
         用户名:<input type="text" name="username"><br>
         密码:<input type="password" name="password"><br>
         爱好:
         <input type="checkbox" name="hobbies" value="唱歌">唱歌
         <input type="checkbox" name="hobbies" value="跳舞">跳舞
         <input type="checkbox" name="hobbies" value="rap">rap
         <input type="checkbox" name="hobbies" value="篮球">篮球
         <input type="submit">
     </form>
 </div>
 </body>
 </html>

 

import javax.servlet.ServletException;
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 import java.util.Arrays;
 ​
 public class LoginServlet extends HttpServlet {
     @Override
     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         req.setCharacterEncoding("utf-8");
         resp.setCharacterEncoding("utf-8");
         String username = req.getParameter("username");
         String password = req.getParameter("password");
         String[] hobbies = req.getParameterValues("hobbies");
         System.out.println("============");
         System.out.println(username);
         System.out.println(password);
         System.out.println(Arrays.toString(hobbies));
         System.out.println("============");
         //通过请求转发,不用加根路径/Request_war
         req.getRequestDispatcher("/Success.jsp").forward(req,resp);
     }
 ​
     @Override
     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         super.doPost(req, resp);
     }
 }

 

 <servlet>
     <servlet-name>Login</servlet-name>
     <servlet-class>LoginServlet</servlet-class>
 </servlet>
 <servlet-mapping>
     <servlet-name>Login</servlet-name>
     <url-pattern>/login</url-pattern>
 </servlet-mapping>

index.jsp默认界面,点击submit提交后才会进入/login


 <%@ page contentType="text/html;charset=UTF-8" language="java" %>
 <html>
 <head>
     <title>Title</title>
 </head>
 <body>
 <h1>登录成功!</h1>
 </body>
 </html>

 

 

 

 

 

7. Cookie、Session

7.1 会话

会话:用户打开了浏览器,点击了很多超链接,访问多个web资源,关闭浏览器,这个过程可以称之为会话

有状态会话:一个同学来过教室,下次再来教室,就会知道这个同学曾经来过

一个网站证明自己来过

客户端 服务端

  1. 服务端给客户端一个信件,客户端下次访问服务端带上信件就可以开始了:cookie

  2. 服务器等级你来过了,下次你来的时候来匹配你:session

 

7.2 保存会话的两种技术

cookie

  • 客户端技术(响应、请求)

session

  • 服务器技术,利用这个技术,可以保存用户的会话信息

  • 把信息或数据放在session中

 

常见:网站登陆之后,下次不用再登陆了,第二次访问直接就上去了

7.3 Cookie

  1. 从请求中拿到cookie消息

  2. 服务器响应给用户端cookie

 1  package com.zhou.servlet;
 2  3  import javax.servlet.ServletException;
 4  import javax.servlet.http.Cookie;
 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.io.PrintWriter;
10  import java.util.Date;
11 12  //保存用户上一次访问的时间
13  public class CookieDemo01 extends HttpServlet {
14      @Override
15      protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
16          //服务器告诉你你来的时间,把这个时间封装成为一个信件,下次带来,就知道你来了
17 18          //解决中文乱码
19          req.setCharacterEncoding("utf-8");
20          resp.setCharacterEncoding("utf-8");
21          resp.setContentType("text/html");
22 23          PrintWriter out = resp.getWriter();
24 25          //Cookie,服务器端从客户端获取
26          Cookie[] cookies = req.getCookies();//这里返回数组,说明cookie可能存在多个
27 28          //判断Cookie是否存在
29          if (cookies!=null){
30              //如果存在怎么办
31              out.write("你上一次访问的时间是:");
32              for (int i = 0; i < cookies.length; i++) {
33                  Cookie cookie = cookies[i];
34                  //获取Cookie的名字
35                  if (cookie.getName().equals("lastLoginTime")){
36                      //获取cookie的值
37                      long lastLogintime = Long.parseLong(cookie.getValue());
38                      Date date = new Date(lastLogintime);
39                      out.write(date.toLocaleString());
40                  }
41              }
42          }else {
43              out.write("这是您第一次访问网站");
44          }
45 46          //服务器给客户端响应一个cookie,新建
47          Cookie cookie = new Cookie("lastLoginTime",System.currentTimeMillis() + "");//转为String
48          cookie.setMaxAge(24*60*60);//有效期一天,单位,秒
49          resp.addCookie(cookie);//响应给客户端一个cookie
50      }
51 52      @Override
53      protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
54          super.doPost(req, resp);
55      }
56  }

cookie:一般会保存在本地的用户目录下appdata

一个网站cookie是否存在上限?

  • 一个cookie只能保存一个信息

  • 一个web站点可以给浏览器发送多个cookie,最多存放20个cookie

  • cookie大小有限制4kb

  • 300个cookie浏览器上限

删除cookie

  • 不设置有效期,关闭浏览器,自动失效

  • 设置有效期,时间为0

 package com.zhou.servlet;
 ​
 import javax.servlet.ServletException;
 import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 ​
 public class CookieDemo02 extends HttpServlet {
     @Override
     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         //创建一个cookie,名字必须要和要删除的名字一致,覆盖原有cookie
         Cookie cookie = new Cookie("lastLoginTime",System.currentTimeMillis()+"");
         //将cookie有效期设置为0,删除cookie
         cookie.setMaxAge(0);
         resp.addCookie(cookie);
     }
 ​
     @Override
     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         super.doPost(req, resp);
     }
 }

 

中文数据传递,需要编码解码

 package com.zhou.servlet;
 ​
 import javax.servlet.ServletException;
 import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.net.URLDecoder;
 import java.net.URLEncoder;
 import java.util.Date;
 ​
 public class CookieDemo03 extends HttpServlet {
     //中文数据传递
     @Override
     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         req.setCharacterEncoding("utf-8");
         resp.setCharacterEncoding("utf-8");
         resp.setContentType("text/html");
 ​
         PrintWriter out = resp.getWriter();
 ​
         //Cookie,服务器端从客户端获取
         Cookie[] cookies = req.getCookies();//这里返回数组,说明cookie可能存在多个
//判断Cookie是否存在
         if (cookies!=null){
             //如果存在怎么办
             out.write("你上一次访问的时间是:");
             for (int i = 0; i < cookies.length; i++) {
                 Cookie cookie = cookies[i];
                 //获取Cookie的名字
                 if (cookie.getName().equals("name")){
                     //获取cookie的值
                     //System.out.println(cookie.getValue());出现乱码
                     //解码
                     out.write(URLDecoder.decode(cookie.getValue(),"UTF-8"));
                 }
             }
         }else {
             out.write("这是您第一次访问网站");
         }
 ​
         //编码
         Cookie cookie = new Cookie("name", URLEncoder.encode("Java语言","UTF-8"));
         resp.addCookie(cookie);
 ​
     }
 ​
     @Override
     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         super.doPost(req, resp);
     }
 }

 

 
<servlet>
     <servlet-name>CookieDemo03</servlet-name>
     <servlet-class>com.zhou.servlet.CookieDemo03</servlet-class>
 </servlet>
 <servlet-mapping>
     <servlet-name>CookieDemo03</servlet-name>
     <url-pattern>/c3</url-pattern>
 </servlet-mapping>

 

输入/c3可看到输出:你上一次访问的时间是:Java语言

输出了中文字符

7.4 Session(重点)

  • 服务器会给每一个用户(浏览器)创建一个session对象

  • 一个Session独占一个浏览器,只要浏览器没有关闭,这个Session就存在

  • 用户登陆之后,整个网站都可以访问—>保存用户的信息,保存购物车的信息等等……

1. 创建并访问

 1  package com.zhou.servlet;
 2  3  import javax.servlet.ServletException;
 4  import javax.servlet.http.*;
 5  import java.io.IOException;
 6  import java.io.PrintWriter;
 7  8  public class SessionDemo01 extends HttpServlet {
 9      @Override
10      protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
11          //解决中文乱码,后续学习这个可以由简单方法代替
12          req.setCharacterEncoding("utf-8");
13          resp.setCharacterEncoding("utf-8");
14          resp.setContentType("text/html;charset=utf-8");
15 16          //得到Session
17          HttpSession session = req.getSession();
18 19          //给Session存东西
20          session.setAttribute("name","Java语言");
21 22          //获取Session的ID
23          String id = session.getId();
24 25          //判断Session是不是新创建
26          if (session.isNew()){
27              resp.getWriter().write("session创建成功,ID:"+id);
28          }else {
29              resp.getWriter().write("session已经在服务器中存在了,ID:"+id);
30          }
31 32          //Session创建的时候做了什么事情
33  //        Cookie cookie = new Cookie("JESSIONID",id);
34  //        resp.addCookie(cookie);
35      }
36 37      @Override
38      protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
39          super.doPost(req, resp);
40      }
41  }

 

 <servlet>
     <servlet-name>SessionDemo01</servlet-name>
     <servlet-class>com.zhou.servlet.SessionDemo01</servlet-class>
 </servlet>
 <servlet-mapping>
     <servlet-name>SessionDemo01</servlet-name>
     <url-pattern>/s1</url-pattern>
 </servlet-mapping>

 

输入网址:http://localhost:8080/s1

输出:session已经在服务器中存在了,ID:7228E652C4832920BCAFE9327383E793

2. 得到Session

 
 1 package com.zhou.servlet;
 2  3  import javax.servlet.ServletException;
 4  import javax.servlet.http.HttpServlet;
 5  import javax.servlet.http.HttpServletRequest;
 6  import javax.servlet.http.HttpServletResponse;
 7  import javax.servlet.http.HttpSession;
 8  import java.io.IOException;
 9 10  public class SessionDemo02 extends HttpServlet {
11      @Override
12      protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
13          //解决中文乱码,后续学习这个可以由简单方法代替
14          req.setCharacterEncoding("utf-8");
15          resp.setCharacterEncoding("utf-8");
16          resp.setContentType("text/html;charset=utf-8");
17 18          //得到Session
19          HttpSession session = req.getSession();
20 21          String name = (String) session.getAttribute("name");
22          System.out.println(name);
23      }
24 25      @Override
26      protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
27          super.doPost(req, resp);
28      }
29  }

 

 <servlet>
     <servlet-name>SessionDemo02</servlet-name>
     <servlet-class>com.zhou.servlet.SessionDemo02</servlet-class>
 </servlet>
 <servlet-mapping>
     <servlet-name>SessionDemo02</servlet-name>
     <url-pattern>/s2</url-pattern>
 </servlet-mapping>

 

输入:http://localhost:8080/s2

输出:后台控制台打印“Java语言”

3. 删除Session

 package com.zhou.servlet;
 ​
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpSession;
 import java.io.IOException;
 ​
 public class SessionDemo03 extends HttpServlet {
     @Override
     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         //删除Session
         HttpSession session = req.getSession();
         session.removeAttribute("name");
         session.invalidate();//手动注销
     }
 ​
     @Override
     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         super.doPost(req, resp);
     }
 }

 

 
<servlet>
     <servlet-name>SessionDemo03</servlet-name>
     <servlet-class>com.zhou.servlet.SessionDemo03</servlet-class>
 </servlet>
 <servlet-mapping>
     <servlet-name>SessionDemo03</servlet-name>
     <url-pattern>/s3</url-pattern>

 

输入:http://localhost:8080/s3

删除session,再通过s2无法访问500粗偶(清空后调用toString空指针异常),s1创建了一个新的session和原来的id不一样

4. 会话自动过期xml设置

 
<!--    设置session默认的失效时间-->
     <session-config>
 <!--        1分钟后Session自动失效,以分钟为单位-->
         <session-timeout>1</session-timeout>
     </session-config>

 

5. Session和Cookie的区别

  • Cookie是把用户的数据写给用户的浏览器,浏览器保存

  • Session是把用户的数据写到用户独占Session中,服务器端保存(保存重要的信息,减小服务器资源的浪费)

  • Session对象由服务器创建

  • Cookie存放字符串(数据小),Session可以存放对象(数据大)

适用场景:

  • 保存一个登录用户的信息

  • 购物车信息

  • 在整个网站中经常会使用的数据,保存在Session中

posted on 2021-06-05 00:01  zrm0612  阅读(34)  评论(0)    收藏  举报