【JavaWeb】Maven、Servlet、cookie/session

[复制链接]
发表于 2025-7-8 15:40:58 | 显示全部楼层 |阅读模式
5. Maven

Maven是一个强盛的项目管理和理解工具,主要用于Java项目的构建、依赖管理和文档生成。以下是Maven的简明概述:


  • 核心概念:POM(Project Object Model),它是一个XML文件,包含了项目的设置信息,如依赖、构建目的等。
  • 依赖管理:主动处理项目依赖的库,通过中心堆栈或自界说堆栈下载所需的JAR包,并办理版本辩论。
  • 构建生命周期:界说了构建过程的标准阶段,包括验证、编译、测试、打包、集成测试、验证、部署等。
  • 插件支持:提供了多种插件来扩展其功能,好比编译代码、创建Javadoc以及运行单元测试等。
  • 多模块项目:支持复杂项目的分模块构建,方便大型项目的维护和管理。
Maven通过提供同一的构建体系、**约定优于设置 **的原则以及强盛的依赖管理本领,极大地简化了Java项目的开发流程。


  • Maven项目的标准结构:
  1. myproject/
  2. ├── src/
  3. │   ├── main/
  4. │   │   ├── java/         ← Java 源代码
  5. │   │   └── resources/    ← 资源文件(如 .properties, XML 等)
  6. │   └── test/
  7. └── pom.xml
复制代码
6. Servlet

6.1 Servlet 简介



  • Servlet就是sun公司开发动态web的一门技术。
  • Sun在这些API中提供一个接口叫做:Servlet,如果你想开发一个 Servlet 步伐,只必要完成两个小步调:

    • 编写一个类,实现 Servlet 接口;
    • 把开发好的Java类部署到web服务器中。
      把实现了Servlet接口Java步伐叫做 Servlet

6.2 HelloServlet

Serlvet接口Sun公司有两个默认的实现类: HttpServlet, GenericServlet,如图所示, HttpServlet 继承自 GenericServlet ,我们手写一个servlet就必要继承自 HttpServlet 。


  • 构建一个平凡的Maven项目,删掉里面的src目录,在这个项目里面建立Moudel;
这个空的工程就是Maven主工程;

  • 关于Maven父子工程的理解:
    父工程中会有:
  1. <modules>
  2.   <module>servlet-01</module>
  3. </modules>
复制代码
子项目中会有:
  1. <parent>
  2.   <groupId>org.example</groupId>
  3.   <artifactId>javaweb-servlet</artifactId>
  4.   <version>1.0-SNAPSHOT</version>
  5. </parent>
复制代码
父项目中的jar包依赖,子项目可以直接使用,反过来则不可以,这就是 继承 。

  • Maven环境优化
  • 编写一个Servlet步伐

    • 编写一个平凡的类 HelloServlet
    • 我们实现Servlet接口,这里我们直接继承 HttpServlet 类

  1. public class HelloServlet extends HttpServlet {
  2.     @Override
  3.     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  4.         System.out.println("hello servlet");
  5.         PrintWriter writer = resp.getWriter();
  6.         writer.println("Hello Servlet");
  7.     }
  8.     @Override
  9.     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  10.         this.doGet(req,resp);
  11.     }
  12. }
复制代码

  • 编写Servlet的映射
    为什么必要映射 :我们写的是Java步伐,但是要通过浏览器访问,而浏览器必要连接web服务器,所以我们必要在web服务中注册我们写的Servlet,还需给他一个浏览器能够访问的路径。
  1. <!--注册servlet-->
  2. <servlet>
  3. <servlet-name>helloservlet</servlet-name>
  4. <servlet-class>com.sunyiwenlong.servlet.HelloServlet</servlet-class>
  5. </servlet>
  6. <!--servlet请求路径-->
  7. <servlet-mapping>
  8. <servlet-name>helloservlet</servlet-name>
  9. <url-pattern>/hello</url-pattern>
  10. </servlet-mapping>
复制代码

  • 设置tomcat
    注意:设置项目发布路径就可以了
  • 启动测试
6.3 Servlet原理


6.4 Mapping( **映射 ** )问题

  1. <project>
  2.   <modelVersion>4.0.0</modelVersion>
  3.   <groupId>com.example</groupId>
  4.   <artifactId>my-web-app</artifactId>
  5.   <version>1.0-SNAPSHOT</version>
  6.   <packaging>war</packaging>
  7.   <dependencies>
  8.     <!-- Servlet API -->
  9.     <dependency>
  10.         <groupId>javax.servlet</groupId>
  11.         <artifactId>javax.servlet-api</artifactId>
  12.         <version>4.0.1</version>
  13.         <scope>provided</scope>
  14.     </dependency>
  15.     <!-- JSP API -->
  16.     <dependency>
  17.         <groupId>javax.servlet.jsp</groupId>
  18.         <artifactId>jsp-api</artifactId>
  19.         <version>2.3.3</version>
  20.         <scope>provided</scope>
  21.     </dependency>
  22.     <!-- Spring MVC 示例 -->
  23.     <dependency>
  24.         <groupId>org.springframework</groupId>
  25.         <artifactId>spring-webmvc</artifactId>
  26.         <version>5.3.20</version>
  27.     </dependency>
  28. </dependencies>
  29. <build>
  30.     <finalName>mywebapp</finalName>
  31.     <plugins>
  32.         <!-- 编译插件 -->
  33.         <plugin>
  34.             <groupId>org.apache.maven.plugins</groupId>
  35.             <artifactId>maven-compiler-plugin</artifactId>
  36.             <version>3.8.1</version>
  37.             <configuration>
  38.                 <source>1.8</source>
  39.                 <target>1.8</target>
  40.             </configuration>
  41.         </plugin>
  42.         <!-- WAR 插件 -->
  43.         <plugin>
  44.             <groupId>org.apache.maven.plugins</groupId>
  45.             <artifactId>maven-war-plugin</artifactId>
  46.             <version>3.2.3</version>
  47.             <configuration>
  48.                 <failOnMissingWebXml>false</failOnMissingWebXml>
  49.             </configuration>
  50.         </plugin>
  51.     </plugins>
  52. </build>
  53.   
  54. </project>
复制代码

  • 一个Servlet可以指定一个映射路径 "/hello"
  1. @WebServlet("/hello")
  2. public class HelloServlet extends HttpServlet {
  3.     protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
  4.         // 处理逻辑
  5.     }
  6. }
复制代码

  • 一个Servlet可以指定多个映射路径 {"/hello", "/hi", "/greeting"}
  1. @WebServlet({"/hello", "/hi", "/greeting"})
  2. public class HelloServlet extends HttpServlet {
  3.     protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
  4.         // 多个路径都能访问到这个 Servlet
  5.     }
  6. }
复制代码

  • 一个Servlet可以指定通用映射路径 "/user/*"
  1. @WebServlet("/user/*")
  2. public class UserServlet extends HttpServlet {
  3.     protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
  4.         // 所有以 /user/ 开头的请求都会进入该 Servlet
  5.     }
  6. }
复制代码

  • 指定一些后缀或者前缀等等…
  1. @WebServlet("*.do")
  2. public class ActionServlet extends HttpServlet {
  3.     protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
  4.         // 所有以 .do 结尾的请求都进入此 Servlet
  5.     }
  6. }
复制代码
  1. @WebServlet("/api/*")
  2. public class ApiServlet extends HttpServlet {
  3.     protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
  4.         // 所有 /api/ 开头的请求进入此 Servlet
  5.     }
  6. }
复制代码
6.5 ServletContext

ServletContext 是 Java Web 开发中一个非常核心的接口,属于 Servlet API 的一部分。每个 Web 应用在服务器启动时都会创建一个唯一的 ServletContext 实例。
Q:可以本技艺动 new 一个 ServletContext 对象?
A:不能直接 new 创建 ServletContext
Q:why?
A:ServletContext 是 由 Web 容器(如 Tomcat、Jetty)在启动 Web 应用时主动创建的,它是整个 Web 应用的运行环境对象。
Q:那我们怎么获取它?
A:在 Servlet 、Listener、JSP中获取;
web容器在启动的时候,它会为每个web步伐都创建一个对应的 ServletContext 对象,它代表了当前的web应用。

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

  1. 1. 在 Servlet 中获取 `ServletContext`,将一个数据保存在了`ServletContext`中
复制代码
  1. public class HelloServlet extends HttpServlet {
  2.     @Override
  3.     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  4.         // this.getInitParameter(); 获取初始化参数(web.xml文件中的初始化参数)
  5.         // this.getServletConfig(); 获取servlet的配置(web.xml文件中的配置
  6.         // this.getServletContext(); 获取servlet上下文
  7.         ServletContext context = this.getServletContext();
  8.         String username = "张三";
  9.         context.setAttribute("username",username);// 将一个数据保存在了ServletContext中
  10.     }
  11. }
复制代码
  1. // 在 Listener 中获取getServletContext
  2. public class MyListener implements HttpSessionListener {
  3.     public void sessionCreated(HttpSessionEvent se) {
  4.         ServletContext context = se.getSession().getServletContext();
  5.     }
  6. }
复制代码
  1. 2. 将保存在context的数据响应出来。
复制代码
  1. public class GetServlet extends HttpServlet {
  2.     @Override
  3.     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  4.         ServletContext context = this.getServletContext();
  5.         String username = (String) context.getAttribute("username");
  6.         resp.setContentType("text/html");
  7.         resp.setCharacterEncoding("utf-8");
  8.         resp.getWriter().println("名字"+username);
  9.     }
  10.     @Override
  11.     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  12.         this.doGet(req,resp);
  13.     }
  14. }
复制代码
  1. 3. 配置URL地址映射
复制代码
  1. <!-- // web.xml文件 -->
  2. <?xml version="1.0" encoding="UTF-8"?>
  3. <web-app version="2.4"
  4.   xmlns="http://java.sun.com/xml/ns/j2ee"
  5.   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  6.   xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
  7.   <servlet>
  8.     <servlet-name>helloservlet1</servlet-name>
  9.     <servlet-class>com.sunyiwenlong.servlet.HelloServlet</servlet-class>
  10.   </servlet>
  11.   <servlet-mapping>
  12.     <servlet-name>helloservlet1</servlet-name>
  13.     <url-pattern>/hello</url-pattern>
  14.   </servlet-mapping>
  15.   <servlet>
  16.     <servlet-name>getservlet</servlet-name>
  17.     <servlet-class>com.sunyiwenlong.servlet.GetServlet</servlet-class>
  18.   </servlet>
  19.   <servlet-mapping>
  20.     <servlet-name>getservlet</servlet-name>
  21.     <url-pattern>/getc</url-pattern>
  22.   </servlet-mapping>
  23. </web-app>
复制代码
  1. 1. <font style="color:rgba(0, 0, 0, 0.85);">也可以通过注解配置地址映射 :: Servlet 3.0+ 规范
复制代码
  1. [/code] [list=1]
  2. [*] 获取初始化参数
  3. [*] 设置web应用中的基本参数
  4. [/list] [code]<!-- web.xml文件 -->
  5. <!--配置一些web应用一些初始化参数-->
  6. <context-param>
  7.   <param-name>url</param-name>
  8.   <param-value>jdbc:mysql://localhost:3306/mybatis</param-value>
  9. </context-param>
复制代码

  • 实现ServletDemo03的Post和Get的逻辑
  1. public class ServletDemo03 extends HttpServlet {
  2.     @Override
  3.     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  4.         String url = this.getInitParameter("url");
  5.         resp.getWriter().println(url);
  6.     }
  7.     @Override
  8.     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  9.         this.doGet(req, resp);
  10.     }
  11. }
复制代码

  • 哀求转发
  • 设置相关URL映射的所在
  1. // web.xml文件
  2. // 请求sd4
  3. <servlet>
  4.   <servlet-name>gp</servlet-name>
  5.   <servlet-class>com.sunyiwenlong.servlet.ServletDemo03</servlet-class>
  6. </servlet>
  7. <servlet-mapping>
  8.   <servlet-name>gp</servlet-name>
  9.   <url-pattern>/gp</url-pattern>
  10. </servlet-mapping>
  11. <servlet>
  12.   <servlet-name>sd4</servlet-name>
  13.   <servlet-class>com.sunyiwenlong.servlet.ServletDemo04</servlet-class>
  14. </servlet>
  15. <servlet-mapping>
  16.   <servlet-name>sd4</servlet-name>
  17.   <url-pattern>/sd4</url-pattern>
  18. </servlet-mapping>
复制代码

  • /sd4哀求 找到ServletDemo04,ServletDemo04逻辑块中举行哀求 转发到/gp,到/gp的页面, /gp找到ServletDemo03。
  1. // 请求/sd4找到ServletDemo04,ServletDemo04进行请求转发到/gp,到/gp的页面
  2. // (浏览器路径是sd4的路径,页面拿到的是/gp的数据)
  3. public class ServletDemo04 extends HttpServlet {
  4.     @Override
  5.     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  6.         ServletContext context = this.getServletContext();
  7.         System.out.println("进入了demo04");
  8.         // RequestDispatcher requestDispatcher = context.getRequestDispatcher("/gp");// 转发的路径
  9.         // requestDispatcher.forward(req,resp);// 调用forward请求转发
  10.         context.getRequestDispatcher("/gp").forward(req,resp);
  11.     }
  12.     @Override
  13.     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  14.         this.doGet(req, resp);
  15.     }
  16. }
复制代码

  • 读取资源文件 Properties


  • 在 src/main/java 目录下新建 properties
  • 在 src/main/resources 目录下新建 properties
  • 末了都被打包到了同一个路径下: target/classes ,我们俗称这个路径为classpath。

  • 实现一个文件流,读取properties
  1. public class ServletDemo05 extends HttpServlet {
  2.     @Override
  3.     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  4.         InputStream stream = this.getServletContext().getResourceAsStream("/WEB-INF/CLASSES/db.properties");
  5.         Properties properties = new Properties();
  6.         properties.load(stream);
  7.         String username = properties.getProperty("username");
  8.         String password = properties.getProperty("password");
  9.         resp.getWriter().println(username+":"+password);
  10.     }
  11.     @Override
  12.     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  13.         this.doGet(req, resp);
  14.     }
  15. }
复制代码

  • 用例图解析:

在一个Web应用中,客户端通过哀求与服务器上的多个Servlet交互,ServletContext在其中饰演的角色是提供一个全局的数据共享空间。
   重点理解:ServletContext是所有Servlet都能访问的全局上下文,用于在应用范围内共享数据;而HttpSession则是针对单个用户的会话管理,用于保存用户相关的临时数据。
  6.6 HttpServletResponse

web服务器吸取到客户端的http哀求,针对这个哀求,分别创建一个代表哀求的 HttpServletRequest 对象,代表响应的一个 HttpServletResponse ;


  • 如果要获取客户端哀求过来的参数:找 HttpServletRequest
  • 如果要给客户端响应一些信息:找 HttpServletResponse

  • 负责向浏览器发送数据的方法
  1. public ServletOutputStream getOutputStream() throws IOException;
  2. public PrintWriter getWriter() throws IOException;
复制代码

  • 响应的状态码
  1. public static final int SC_CONTINUE = 100;
  2. /**
  3.   * Status code (200) indicating the request succeeded normally.
  4.   */
  5. public static final int SC_OK = 200;
  6. /**
  7.   * Status code (302) indicating that the resource has temporarily
  8.   * moved to another location, but that future references should
  9.   * still use the original URI to access the resource.
  10.   *
  11.   * This definition is being retained for backwards compatibility.
  12.   * SC_FOUND is now the preferred definition.
  13.   */
  14. public static final int SC_MOVED_TEMPORARILY = 302;
  15. /**
  16. * Status code (302) indicating that the resource reside
  17. * temporarily under a different URI. Since the redirection might
  18. * be altered on occasion, the client should continue to use the
  19. * Request-URI for future requests.(HTTP/1.1) To represent the
  20. * status code (302), it is recommended to use this variable.
  21. */
  22. public static final int SC_FOUND = 302;
  23. /**
  24.   * Status code (304) indicating that a conditional GET operation
  25.   * found that the resource was available and not modified.
  26.   */
  27. public static final int SC_NOT_MODIFIED = 304;
  28. /**
  29.   * Status code (404) indicating that the requested resource is not
  30.   * available.
  31.   */
  32. public static final int SC_NOT_FOUND = 404;
  33. /**
  34.   * Status code (500) indicating an error inside the HTTP server
  35.   * which prevented it from fulfilling the request.
  36.   */
  37. public static final int SC_INTERNAL_SERVER_ERROR = 500;
  38. /**
  39.   * Status code (502) indicating that the HTTP server received an
  40.   * invalid response from a server it consulted when acting as a
  41.   * proxy or gateway.
  42.   */
  43. public static final int SC_BAD_GATEWAY = 502;
  44. // ...
复制代码
常见应用


  • 向浏览器输出消息的
  • 下载文件 实现方式
  1. public class FileServlet extends HttpServlet {
  2.     @Override
  3.     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  4.         // 1.要获取下载文件的路径 :\转义字符
  5.         String realPath = "E:\\dev\\StudyProjects\\javaweb-servlet\\response\\src\\main\\resources\\大乔.jpg";
  6.         // 2.下载的文件名是啥?
  7.         String filename = realPath.substring(realPath.lastIndexOf("\") + 1);
  8.         // 3.设置想办法让浏览器能够支持下载我们需要的东西
  9.         resp.setHeader("Content-disposition","attachment;filename="+ URLEncoder.encode(filename,"utf-8"));
  10.         // 4.获取下载文件的输入流
  11.         FileInputStream in = new FileInputStream(realPath);
  12.         // 5.创建缓冲区
  13.         int len = 0;
  14.         byte[] buffer = new byte[1024]; // 每次读取的长度
  15.         // 6.获取OutputStream对象
  16.         ServletOutputStream out = resp.getOutputStream();
  17.         // 7.将FileOutputStream流写入到bufer缓冲区
  18.         while ((len = in.read(buffer))>0){// 每次读取的长度大于0的情况下,就写出去
  19.             out.write(buffer,0,len);// 写出字节,从0写到len
  20.         }
  21.         // 8.使用OutputStream将缓冲区中的数据输出到客户端!
  22.         in.close();
  23.         out.close();
  24.     }
  25.     @Override
  26.     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  27.         this.doGet(req, resp);
  28.     }
  29. }
复制代码

  • 验证码功能 实现方式
  1. public class ImageServlet extends HttpServlet {
  2.     @Override
  3.     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  4.         // 让浏览器3秒刷新一次
  5.         resp.setHeader("refresh", "3");
  6.         // 在内存中创建一个图片
  7.         BufferedImage image = new BufferedImage(80, 20, BufferedImage.TYPE_INT_RGB);// 宽、高、颜色
  8.         // 得到图片
  9.         Graphics2D g = (Graphics2D) image.getGraphics();// 得到一只2D的笔
  10.         // 设置图片的背景颜色
  11.         g.setColor(Color.white);
  12.         g.fillRect(0, 0, 80, 20);// 填充颜色
  13.         // 换个背景颜色
  14.         g.setColor(Color.BLUE);
  15.         // 设置字体样式:粗体,20
  16.         g.setFont(new Font(null,Font.BOLD,20));
  17.         // 画一个字符串(给图片写数据)
  18.         g.drawString(makeNum(),0,20);
  19.         // 告诉浏览器,这个请求用图片的方式打开
  20.         resp.setContentType("image/jpeg");
  21.         // 网站存在缓存,不让浏览器缓存
  22.         resp.setDateHeader("expires",-1);
  23.         resp.setHeader("Cache-Control","no-cache");
  24.         resp.setHeader("Pragma","no-cache");
  25.         // 把图片写给浏览器
  26.         boolean write = ImageIO.write(image, "jpg",resp.getOutputStream());
  27.     }
  28.     // 生成随机数
  29.     private String makeNum() {
  30.         Random random = new Random();
  31.         String num = random.nextInt(9999999) + "";// 随机数,最大七位,[0,9999999)
  32.         StringBuffer sb = new StringBuffer();
  33.         for (int i = 0; i < 7 - num.length(); i++) {// 不足七位,则添加0
  34.             sb.append("0");
  35.         }
  36.         num = sb.toString()+num;// 不足七位,在随机数前面添加0
  37.         return num;
  38.     }
  39.     @Override
  40.     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  41.         this.doGet(req, resp);
  42.     }
  43. }
复制代码

  • 实现 哀求重定向
  1. public class RedirectServlet extends HttpServlet {
  2. @Override
  3. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  4.      /*resp.setHeader("Location","/response_war/image");
  5.      resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);*/
  6.      resp.sendRedirect("/response_war/image");// 重定向相当于上面两行代码
  7. }
  8. @Override
  9. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  10.      this.doGet(req, resp);
  11. }
  12. }
复制代码
6.7 HttpServletRequest

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

  • 获取前端传递的参数

    • getParameter(String name) | 获取指定名称的哀求参数值(GET 或 POST 表单)

  1. String username = request.getParameter("username");
  2. String password = request.getParameter("password");
复制代码

  • getParameterValues(String name) | 用于获取多个值的参数(如多选框)
  1. String[] hobbies = request.getParameterValues("hobby");
  2. if (hobbies != null) {
  3.     for (String hobby : hobbies) {
  4.         System.out.println("兴趣爱好:" + hobby);
  5.     }
  6. }
复制代码

  • getParameterMap() | 返回所有参数的 Map 形式,键为参数名,值为字符串数组(得当处理复杂表单)
  1. Map<String, String[]> parameterMap = request.getParameterMap();
  2. for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) { //使用foreach语句循环使用
  3.     System.out.println(entry.getKey() + " = " + Arrays.toString(entry.getValue()));
  4. }
复制代码

  • getInputStream() / getReader() | 适用于吸取 JSON、XML 等原始哀求体内容(常用于前后端分离项目)
  1. StringBuilder jsonBody = new StringBuilder();
  2. BufferedReader reader = request.getReader();
  3. String line;
  4. while ((line = reader.readLine()) != null) {
  5.     jsonBody.append(line);
  6. }
  7. System.out.println("接收到的JSON:" + jsonBody.toString());
复制代码
  注意:你必要使用 JSON 解析库(如 Jackson、Gson)来解析这个字符串。
  

  • 获取路径参数(RESTful 风格) :request.getPathInfo()
  1. @WebServlet("/user/*")
  2. public class UserServlet extends HttpServlet {
  3.     protected void doGet(HttpServletRequest request, HttpServletResponse response) {
  4.         String pathInfo = request.getPathInfo(); // 如:/user/123 → 返回 "/123"
  5.         if (pathInfo != null && pathInfo.length() > 1) {
  6.             String userId = pathInfo.substring(1); // 去掉开头斜杠
  7.             System.out.println("用户ID:" + userId);
  8.         }
  9.     }
  10. }
复制代码

  • 完整代码如下:
  1. protected void doPost(HttpServletRequest request, HttpServletResponse response)
  2.         throws ServletException, IOException {
  3.     // 获取普通参数
  4.     String username = request.getParameter("username");
  5.     String password = request.getParameter("password");
  6.     // 获取多选参数
  7.     String[] hobbies = request.getParameterValues("hobby");
  8.     // 获取所有参数(Map)
  9.     Map<String, String[]> parameterMap = request.getParameterMap();
  10.     // 输出参数
  11.     System.out.println("用户名:" + username);
  12.     System.out.println("密码:" + password);
  13.     if (hobbies != null) {
  14.         for (String hobby : hobbies) {
  15.             System.out.println("兴趣:" + hobby);
  16.         }
  17.     }
  18.     // 处理 JSON 数据(如果需要)
  19.     if ("application/json".equals(request.getContentType())) {
  20.         BufferedReader reader = request.getReader();
  21.         StringBuilder json = new StringBuilder();
  22.         String line;
  23.         while ((line = reader.readLine()) != null) {
  24.             json.append(line);
  25.         }
  26.         System.out.println("JSON 内容:" + json);
  27.     }
  28. }
复制代码

  • 哀求 转发
前端:
  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  2.   <html>
  3.     <head>
  4.       <title>首页</title>
  5.     </head>
  6.     <body>
  7.       <form action="${pageContext.request.contextPath}/login" method="post">
  8.         用户名:<input type="text" name="username"><br>
  9.         密码:<input type="password" name="password"><br>
  10.         爱好:
  11.         <input type="checkbox" name="hobbys" value="代码"> 代码
  12.         <input type="checkbox" name="hobbys" value="唱歌"> 唱歌
  13.         <input type="checkbox" name="hobbys" value="女孩"> 女孩
  14.         <input type="checkbox" name="hobbys" value="电影"> 电影
  15.         <br>
  16.         <input type="submit" name="提交">
  17.       </form>
  18.     </body>
  19.   </html>
复制代码
后端:
  1. public class LoginServlet extends HttpServlet {
  2.         @Override
  3.         protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  4.                 this.doPost(req, resp);
  5.         }
  6.         @Override
  7.         protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  8.                 // 处理请求中文乱码(后期可以使用过滤器来解决)
  9.                 req.setCharacterEncoding("utf-8");
  10.                 resp.setCharacterEncoding("utf-8");
  11.                 String username = req.getParameter("username");         // 用户
  12.                 String password = req.getParameter("password");         // 密码
  13.                 String[] hobbys = req.getParameterValues("hobbys"); // 爱好
  14.                 System.out.println(username);
  15.                 System.out.println(password);
  16.                 System.out.println(Arrays.toString(hobbys));
  17.                 // 这里的 / 代表当前的web应用,所以不需要再加上/request_war这个上下文路径了,否则会出现404错误 转发
  18.                 req.getRequestDispatcher("/success.jsp").forward(req,resp);
  19.         }
  20. }
复制代码
web.xml
  1. <servlet>
  2.         <servlet-name>login</servlet-name>
  3.         <servlet-class>com.sunyiwenlong.request.LoginServlet</servlet-class>
  4. </servlet>
  5. <servlet-mapping>
  6.         <servlet-name>login</servlet-name>
  7.         <url-pattern>/login</url-pattern>
  8. </servlet-mapping>
复制代码
  这个 web.xml 设置界说了一个名为 login 的Servlet及其URL映射,对应的Java代码实现了基本的登录处理逻辑,包括获取哀求参数和返回响应
  面试题:请你聊聊 重定向 转发 的区别?
相同点:页面都会实现跳转
不同点:
   哀求转发的时候,URL所在栏不会产生变化。
  

  • 得当服务器内部跳转 。
  • 状态码: 307 (临时重定向)
  • RequestDispatcher.forward()
  1. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  2.     // 设置属性
  3.     request.setAttribute("message", "这是转发时携带的消息");
  4.     // 获取 RequestDispatcher 并转发
  5.     RequestDispatcher dispatcher = request.getRequestDispatcher("/target.jsp");
  6.     dispatcher.forward(request, response);
  7. }
复制代码
  重定向时候,URL所在栏会发生变化。
  

  • 跳转到外部网站。
  • 状态码:302 ,301(永世重定向)
  • HttpServletResponse.sendRedirect()
  1. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
  2.     // 重定向到另一个路径
  3.     response.sendRedirect("http://example.com");  // 也可以是相对路径:"/myapp/target.jsp"
  4. }
复制代码
7. cookie/session

7.1 会话

无状态的会话:用户打开一个浏览器,点击了很多超链接,访问多个web资源,关闭浏览器,这个过程可以称之为会话。
有状态的会话:一个用户打开一个浏览器,访问某些资源(网站),下次再来访问该资源(网站),我们会知道这个用户曾经来过,称之为有状态会话;
   一个网站,怎么证明你来过?
  

  • 服务端给客户端一个信件,客户端下次访问服务端带上信件就可以了;cookie(客户端)
  • 服务器登记你来过了,下次你来的时候我来匹配你;session(服务端)
  7.2 保存会话的两种技术

cookie:客户端技术,(响应、哀求)
session:服务端技术,利用这个技术,可以保存用户的会话信息?我们可以把信息或者数据放在Session中。
  1. 用户登录
  2.     ↓
  3. 服务器创建 Session 并保存用户信息
  4.     ↓
  5. 服务器生成 JSESSIONID 并写入 Cookie
  6.     ↓
  7. 客户端保存 Cookie
  8.     ↓
  9. 后续请求携带 Cookie 到服务器
  10.     ↓
  11. 服务器根据 JSESSIONID 找到对应的 Session
  12.     ↓
  13. 继续处理用户逻辑
复制代码
7.3 Cookie


  • 从哀求中拿到cookie
  • 服务器响应给客户端cookie
  1. Cookie[] cookies = req.getCookies();// 获得cookie
  2. cookie.getName();// 获得cookie中的key
  3. cookie.getValue();// 获得cookie中的value
  4. new Cookie("lastLoginTime",System.currentTimeMills()+"");// 新建一个cookie
  5. cookie.setMaxAge(24*60*60);// 设置cookie的有效期,单位:秒
  6. resp.addCookie(cookie);// 响应给客户端一个cookie
复制代码
Q: cookie:一样平常会保存在本地的用户目录下appdata,一个网站cookie是否存在上限!聊聊细节问题


  • 一个Cookie只能保存一个信息;
  • 一个web站点可以给浏览器发送多个cookie,最多存放20个cookie;
  • Cookie大小有限定4kb
  • 300个cookie浏览器上限
删除cookie


  • 不设置有用期,关闭浏览器,主动失效
  • 设置有用期时间为 0
编码解码,怎么办理中文乱码问题
  1. URLEncoder.encode("张三","UTF-8")
  2. URLDecoder.decode("张三","UTF-8")
复制代码
保存上一次登录时间** 实现方式 **
  1. // 保存用户上一次访问的时间
  2. public class CookieDemo01 extends HttpServlet {
  3.     @Override
  4.     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  5.         // 服务器告诉你,你来的时间,把这个时间封装成一个信息,你下次带来,我就知道你上次来的时间
  6.         // 解决中文乱码
  7.         req.setCharacterEncoding("utf-8");
  8.         resp.setCharacterEncoding("utf-8");
  9.         PrintWriter out = resp.getWriter();
  10.         // Cookie,服务器端从客户端获取cookie
  11.         Cookie[] cookies = req.getCookies();// 数组,说明cookie可以有多个
  12.         // 判断cookie是否
  13.         if (cookies != null) {
  14.             out.write("你上一次登录的时间是:");
  15.             for (int i = 0; i < cookies.length; i++) {
  16.                 // 获取cookie的名字
  17.                 if (cookies[i].getName().equals("lastLoginTime")) {
  18.                     // 获取cookie的值
  19.                     long l = Long.parseLong(cookies[i].getValue());
  20.                     Date date = new Date(l);
  21.                     out.write(date.toLocaleString());
  22.                 }
  23.             }
  24.         } else {
  25.             out.write("你是第一次登录!");
  26.         }
  27.         Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis() + "");
  28.         cookie.setMaxAge(24*60*60);// 设置cookie的有效期为一天,单位是:秒
  29.         resp.addCookie(cookie);
  30.     }
  31.     @Override
  32.     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  33.         this.doGet(req, resp);
  34.     }
  35. }
复制代码
7.4 Session (重点)

什么是Session:


  • 服务器会给每一个用户(浏览器)创建一个Seesion对象。
  • 一个session独占一个浏览器,只要浏览器没有关闭,这个session就存在。
  • 用户登录之后,整个网站它都可以访问。(保存用户的信息;也可以保存购物车的信息)
Session和cookie的区别


  • Cookie是把用户的数据写给用户的浏览器,浏览器保存(可以保存多个)保存在 客户端;
  • Session把用户的数据写到用户独占 Session 中,服务器端 保存(保存重要的信息,减少服务器资源的浪费)
  • Session对象由服务( sevice )创建;
使用场景


  • 保存一个登任命户的信息;
  • 购物车信息;
  • 在整个网站中经常会使用的数据,我们将它保存在 Session 中;
会话主动过期
  1. <!--设置session默认的失效时间-->
  2. <session-config>
  3.   <!--15分钟后session自动失效,以分钟为单位-->
  4.   <session-timeout>15</session-timeout>
  5. </session-config>
复制代码
Session的使用
  1. public class SessionDemo01 extends HttpServlet {
  2.     @Override
  3.     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  4.         
  5.         // 解决中文乱码
  6.         req.setCharacterEncoding("UTF-8");
  7.         resp.setCharacterEncoding("UTF-8");
  8.         resp.setContentType("text/html;charset=utf-8");
  9.         // 得到Session
  10.         HttpSession session = req.getSession();
  11.         // 给session中存东西
  12.         session.setAttribute("name", "张三");
  13.         // 获取session的id
  14.         String sessionId = session.getId();
  15.         // 判断session是不是新创建
  16.         if (session.isNew()) {
  17.             resp.getWriter().write("session创建成功,ID:" + sessionId);
  18.         } else {
  19.             resp.getWriter().write("session已经存在了,ID:" + sessionId);
  20.         }
  21.         // session创建的时候做了什么事情
  22.         /*Cookie cookie = new Cookie("JSESSIONID", sessionId);
  23.         resp.addCookie(cookie);*/
  24.         //------------------
  25.         // 从session中获取数据
  26.         String name = (String) session.getAttribute("name");
  27.         //------------------
  28.         // 从session中删除指定name的数据
  29.         session.removeAttribute("name");
  30.         // 手动注销session
  31.         session.invalidate();
  32.     }
  33.     @Override
  34.     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  35.         this.doGet(req, resp);
  36.     }
  37. }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
继续阅读请点击广告

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
回复

使用道具 举报

快速回复 返回顶部 返回列表