Servlet

Servlet

1.Servlet 简介

  • Servlet是sun公司开发的一个动态web技术
  • sun公司在API中提供了一个接口叫Servlet,开发web项目
    • 编写一个类,实现Servlet接口
    • 把开发的web项目部署到web服务器中
  • 把实现了Servlet接口的程序叫做Servlet
  • sun公司提供了两个默认的实现类HtppServlet、

2.HelloServlet

搭建一个简单的Servlet环境

  1. 先构建一个普通的Maven项目,删除掉src目录,以便于建立子工程,这个空的Maven工程就是父工程

  2. 关于父子工程理解:
    父工程中

    <!--    这里代表子工程-->    
    <modules>
        <module>servlet-01</module>
    </modules>
    

    子工程中

     <!-- 代表对应的父工程-->
    	<parent>
            <artifactId>javaweb-servlet</artifactId>
            <groupId>com.myl</groupId>
            <version>1.0-SNAPSHOT</version>
        </parent>
    

    父工程中配置的环境子工程可以直接使用,反之则不行。

  3. Maven环境优化

    • 将子工程的web.xml换成最新的(可以去tomcat路径下拿到)

      <?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>
      
    • 搭建maven结构完整

  4. 编写一个Servlet程序

    • 编写一个普通的JAVA类
    • 实现Servlet接口,这里直接继承HttpServlet

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dU161PZR-1615810852633)(C:\Users\10254\AppData\Roaming\Typora\typora-user-images\image-20201118083708896.png)]

    package com.myl;
    
    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.PrintWriter;
    
    /**
     * @ClassName: HelloServlet
     * @Description: TODO
     * @author: meyolo
     * @date: 2020/11/18  8:24
     */
    public class HelloServlet extends HttpServlet {
        // deGet和doPost方法,可以相互调用,逻辑都一样
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            PrintWriter writer = resp.getWriter();   // 响应流
            writer.write("Hello Servlet!");  // 页面输出
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req,resp);
        }
    }
    
    
  5. 编写Servlet的映射

    原因:我们编写的是一个普通的Java程序,但是要通过浏览器访问则需要连接web服务器,所以我们需要在web服务器中注册我们写的Servlet,还要给一个浏览器访问路径。

    <?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>
            <servlet-name>hello</servlet-name>
        </servlet>
    <!--    请求Servlet路径-->
        <servlet-mapping>
            <servlet-name>hello</servlet-name>
            <url-pattern>/hello</url-pattern>
        </servlet-mapping>
    </web-app>
    
  6. 配置Tomcat

  7. 测试启动

3.Servlet原理

在这里插入图片描述

4.Mapping映射

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

        <servlet-mapping>
            <servlet-name>hello</servlet-name>
            <url-pattern>/hello1</url-pattern>
        </servlet-mapping>
    
  2. 一个Servlet可以指定多个映射路径

        <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>
    
  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>*.sad</url-pattern>
        </servlet-mapping>
    
  6. 优先级问题

     <servlet>
            <servlet-name>error</servlet-name>
            <servlet-class>com.myl.ErrorServlet</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>error</servlet-name>
            <url-pattern>/*</url-pattern>
        </servlet-mapping>
    

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

5.ServletContext

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

1.共享数据

在一个servlet中保存的数据,可以在另一个servlet中拿到。

在这里插入图片描述

package com.myl;

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;

/**
 * @ClassName: HelloServlet
 * @Description: TODO
 * @author: meyolo
 * @date: 2020/11/18  15:21
 */
public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //  this.getInitParameterNames();  初始化参数
        //  this.getServletConfig();        Servlet配置
        //  this.getServletContext();     Servlet上下文
        ServletContext servletContext = this.getServletContext();
        String name = "孟哈哈";
        // 将数据保存在 servletContext 中,键值对(key,value)
        servletContext.setAttribute("name",name);
    }
}

package com.myl;

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;

/**
 * @ClassName: GetServlet
 * @Description: TODO
 * @author: meyolo
 * @date: 2020/11/18  15:41
 */
public class GetServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext servletContext = this.getServletContext();
        String name = (String) servletContext.getAttribute("name");


        resp.setContentType("text/html");
        resp.setCharacterEncoding("utf-8");
        resp.getWriter().println("你好!"+name);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req,resp);
    }
}

<servlet>
  <servlet-name>hello2</servlet-name>
  <servlet-class>com.myl.HelloServlet</servlet-class>
</servlet>
  <servlet-mapping>
    <servlet-name>hello2</servlet-name>
    <url-pattern>/hello</url-pattern>
  </servlet-mapping>


  <servlet>
    <servlet-name>getc</servlet-name>
    <servlet-class>com.myl.GetServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>getc</servlet-name>
    <url-pattern>/getc</url-pattern>
  </servlet-mapping>

2.获取初始化参数

<!--  配置初始化参数-->
<context-param>
  <param-name>url</param-name>
  <param-value>jdbc:mysql://localhost:3306/blog</param-value>
</context-param>
package com.myl;

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;

/**
 * @ClassName: ServletDemo3
 * @Description: TODO
 * @author: meyolo
 * @date: 2020/11/18  16:12
 */
public class ServletDemo3 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext servletContext = this.getServletContext();
        String url = servletContext.getInitParameter("url");
        resp.getWriter().println(url);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req,resp);
    }
}

3.请求转发

package com.myl;

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;

/**
 * @ClassName: ServletDemo3
 * @Description: TODO
 * @author: meyolo
 * @date: 2020/11/18  16:09
 */
public class ServletDemo4 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext servletContext = this.getServletContext();
        // 请求转发Servlet
        servletContext.getRequestDispatcher("/gp").forward(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req,resp);
    }
}

在这里插入图片描述

4.读取资源文件

Properties:

  • 在java目录下新建properties
  • 在resources目录下新建properties

都被打包在了一个路径下 classes 我们称这个路径为 classpath

username=myl
userpassword=12345
package com.myl;

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;

/**
 * @ClassName: ServletDemo5
 * @Description: TODO
 * @author: meyolo
 * @date: 2020/11/22  14:10
 */
public class ServletDemo5 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws  IOException {
        InputStream resourceAsStream = this.getServletContext().getResourceAsStream("/WEB-INF/classes/com/myl/java.properties");
        Properties properties = new Properties();
        properties.load(resourceAsStream);

        String username = properties.getProperty("username");
        String userpassword = properties.getProperty("userpassword");

        resp.getWriter().println("user"+username+"password"+userpassword);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doPost(req, resp);
    }
}

<!--build中配置resources,来防止我们资源导出失败的问题-->
    <build>
        <resources>
            <resource>
                <!-- 设定主资源目录  -->
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
            </resource>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
        </resources>
    </build>

6.HttpServletRequest

请求转发获取前端传递的参数,并请求转发

package com.myl.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.util.Arrays;

/**
 * @ClassName: RequestServlet
 * @Description: TODO
 * @author: meyolo
 * @date: 2020/11/25  17:27
 */
public class RequestServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }

    @Override
    protected void doPost(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[] hobbys = req.getParameterValues("hobbys");

        System.out.println(username);
        System.out.println(password);
        System.out.println(Arrays.toString(hobbys));
//        请求转发这里的 / 代表当前web应用的路径
        req.getRequestDispatcher("/success.jsp").forward(req,resp);
    }
}

7.HttpServletResponse

1.向浏览器输出信息

2.下载文件

  1. 要获取下载文件的路径
  2. 下载的文件名
  3. 设置想办法让浏览器支持下载我们需要的东西
  4. 获取下载文件的输入流
  5. 创建缓冲区
  6. 获取OutputStream对象
  7. 将FIleOutputStream流写入buffer缓冲区
package com.myl.servlet;


import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLEncoder;

/**
 * @ClassName: FileDownload
 * @Description: TODO
 * @author: meyolo
 * @date: 2020/11/22  15:12
 */
public class FileDownload extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        1. 要获取下载文件的路径
        String realPath = "F:\\javaweb-servlet\\response\\target\\classes\\1.png";
        System.out.println("下载文件的路径:"+realPath);
//
//        2. 下载的文件名
        String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1);
//
//        3. 设置想办法让浏览器支持下载我们需要的东西,后面的URLEncoder中文文件名编码
        resp.setHeader("Content-disposition","attachment;filename="+ URLEncoder.encode(fileName,"UTF-8");
//
//        4. 获取下载文件的输入流
        FileInputStream in = new FileInputStream(realPath);
//
//        5. 创建缓冲区
        int len = 0;
        byte[] buffer = new byte[1024];
//
//        6. 获取OutputStream对象
        ServletOutputStream out =resp.getOutputStream();
//
//        7. 将FIleOutputStream流写入buffer缓冲区
        while ((len=in.read(buffer))>0){
            out.write(buffer,0,len);
        }

        in.close();
        out.close();


    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doPost(req, resp);
    }
}

3.验证码实现

package com.myl.servlet;


import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;

/**
 * @ClassName: ImageServlet
 * @Description: TODO
 * @author: meyolo
 * @date: 2020/11/22  16:27
 */
public class ImageServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       // 浏览器3秒刷新一次
        resp.setHeader("refresh","3");
        //在内存中创建一个图片
        BufferedImage image = new BufferedImage(100, 30, BufferedImage.TYPE_INT_RGB);
        //得到图片
        Graphics2D g = (Graphics2D) image.getGraphics();
        //设置图片的背景色
        g.setColor(Color.cyan);
        g.fillRect(0,0,100,30);
        //给图片写入数据
        g.setColor(Color.black);
        g.setFont(new Font(null,Font.BOLD,30));
        g.drawString(makeNum(),0,20);

        //告诉浏览器,这个请求用图片方式打开
        resp.setContentType("image/jpg");
        //网站存在缓存,不让存在缓存
        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(999999)+"";
        StringBuffer sb = new StringBuffer();
        for (int i=0;i<6-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);
    }
}

4.重定向

public void sendRedirect(String location) throws IOException;

在这里插入图片描述

<%--
  Created by IntelliJ IDEA.
  User: 10254
  Date: 2020/11/25
  Time: 16:25
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>登录</title>
</head>
<body>
<%--EL表达式取出 当前项目路径,也可手动输入项目名称--%>
<form action="${pageContext.request.contextPath}/login" method="get">
<%--<form action="/response/login" method="get">--%>
    用户名:<input type="text" name="username">
    密码:<input type="password" name="password">
            <input type="submit" name="submit">
</form>

</body>
</html>

package com.myl.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.PageContext;
import java.io.IOException;

/**
 * @ClassName: RedirectServlet
 * @Description: TODO
 * @author: meyolo
 * @date: 2020/11/25  16:23
 */
public class RedirectServlet extends HttpServlet {
    @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);

        // 注意这里重定向的路径,最好包含项目名
        resp.sendRedirect("/response/success.jsp");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

8.重定向与请求转发的区别

相同点:都是跳转页面

不同点:

  • 重定向页面URL地址变化 状态码302
  • 请求转发URL地址不发生变化 状态码307
  • 请求转发可以传递数据

9.Cookie、Session

9.1.Cookie

Cookie是存储在计算机内部的文本文件,由服务器发送给客户端,用来保存用户的信息。

识别用户三个步骤:

  • 服务器向浏览器发送一组Cookie
  • 浏览器将Cookie保存在计算机文本文件
  • 当下一次浏览器请求页面时,浏览器将会把这些Cookie发送给服务器,服务器通过Cookie识别用户

在这里插入图片描述

关闭浏览器时,会话结束,Cookie也就清除。

Cookie 解析:

Cookie一般设置在HTTP头信息中:

HTTP/1.1 200 OK
Date: Fri, 04 Feb 2000 21:03:38 GMT
Server: Apache/1.3.9 (UNIX) PHP/4.0b3
Set-Cookie: name=xyz; expires=Friday, 04-Feb-07 22:03:38 GMT; 
                 path=/; domain=runoob.com
Connection: close
Content-Type: text/html

其中的Set-Cookie 设置了一些Cookie的基本信息,expires是一个指令,告诉浏览器在指定日期后忘记Cookie,现在大多数浏览器都会设置为 存储Cookie,那么到了指定日期后,Cookie将会自动清除,如果用户的浏览器指向任何匹配Cookie的路径和页面,将会重新发送Cookie到服务器。

Servlet 就能够通过请求方法 request.getCookies() 访问 Cookie,该方法将返回一个 Cookie 对象的数组。

实例:

package com.myl.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.util.Date;

/**
 * @ClassName: CookieServlet
 * @Description: TODO
 * @author: meyolo
 * @date: 2020/11/27  9:14
 */
public class CookieServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");

        PrintWriter out = resp.getWriter();
        // 服务器从客户端获取Cookie
        Cookie[] cookies = req.getCookies();

        //判断Cookie是否存在
        if(cookies!=null) {
            out.write("你上一次访问的时间是:");
            for (int i = 0; i < cookies.length; i++) {
                // 遍历Cookie的基本数据信息
                Cookie cookie = cookies[i];
                if (cookie.getName().equals("LastLoginTime")) {
                    // 通过Long包装转化为长整型
                    long LastLoginTime = Long.parseLong(cookie.getValue());
                    Date date = new Date(LastLoginTime);
                    //输出本机时间
                    out.write(date.toLocaleString());
                }
            }
        }else{
            out.write("这是您第一次访问本站");
        }

        Cookie cookie = new Cookie("LastLoginTime",System.currentTimeMillis()+"");
        resp.addCookie(cookie);


    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

在这里插入图片描述

在这里插入图片描述

保存Cookie,设置有效期

package com.myl.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.util.Date;

/**
 * @ClassName: CookieServlet
 * @Description: TODO
 * @author: meyolo
 * @date: 2020/11/27  9:14
 */
public class CookieServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");

        PrintWriter out = resp.getWriter();
        // 服务器从客户端获取Cookie
        Cookie[] cookies = req.getCookies();

        //判断Cookie是否存在
        if(cookies!=null) {
            out.write("你上一次访问的时间是:");
            for (int i = 0; i < cookies.length; i++) {
                // 遍历Cookie的基本数据信息
                Cookie cookie = cookies[i];

                if (cookie.getName().equals("LastLoginTime")) {
                    // 通过Long包装转化为长整型
                    long LastLoginTime = Long.parseLong(cookie.getValue());
                    Date date = new Date(LastLoginTime);
                    //输出本机时间
                    out.write(date.toLocaleString());
                }
            }
        }else{
            out.write("这是您第一次访问本站");
        }
        //  Cookie中的信息是 键值对, 此处  更新时间
        Cookie cookie = new Cookie("LastLoginTime",System.currentTimeMillis()+"");
        // 设置Cookie的有效期为 一天
        cookie.setMaxAge(24*60*60);
        resp.addCookie(cookie);


    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

在这里插入图片描述

关闭浏览器重新请求

1606442781290

9.2 Session

Session:

  • 服务器会给每一个用户(浏览器)创建一个session
  • 一个Session独占一个浏览器,只要浏览器没关闭,Session就存在
  • 用户登录之后,整个链接网站都可以访问,例如保护用户的信息

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6TqoFCY5-1615810852666)(C:\Users\10254\AppData\Roaming\Typora\typora-user-images\image-20201127211137799.png)]

Session中的方法
在这里插入图片描述

测试:

session请求

package com.myl.servlet;

import com.myl.pojo.Python;

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;

/**
 * @ClassName: SessionServlet
 * @Description: TODO
 * @author: meyolo
 * @date: 2020/11/27  19:52
 */
public class SessionServlet 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;charset=utf-8");

        HttpSession session = req.getSession();
        //往Session里面存储信息 object
        session.setAttribute("name","孟永龙");
        session.setAttribute("names",new Python("孟永龙",20));
        // 得到Session的ID
        String sessionId = session.getId();

        if(session.isNew()){
            resp.getWriter().write("Session创建成功"+sessionId);
        }else{
            resp.getWriter().write("Session已经在服务器中存在"+sessionId);
        }


    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

session2请求

package com.myl.servlet;

import com.myl.pojo.Python;

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;

/**
 * @ClassName: Session2
 * @Description: TODO
 * @author: meyolo
 * @date: 2020/11/27  20:01
 */
public class Session2 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;charset=utf-8");

        HttpSession session = req.getSession();

        String name = (String) session.getAttribute("name");
        Python names = (Python) session.getAttribute("names");

        System.out.println(names);
        System.out.println(name);


    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

session3

package com.myl.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;

/**
 * @ClassName: Session3
 * @Description: TODO
 * @author: meyolo
 * @date: 2020/11/27  20:07
 */
public class Session3 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;charset=utf-8");

        HttpSession session = req.getSession();
        //移除session中存储的信息
        session.removeAttribute("name");
        //人为消除session,服务器会立即创建一个新的session
        session.invalidate();
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

<session-config>
    <!--        设置session自动消亡时间 分钟为单位-->
    <session-timeout>1</session-timeout>
</session-config>

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

9.3 总结

Cookie : 客户端技术 (请求和响应)

Session: 服务器技术 (保存用户的会话信息,还可以存储一些数据)

Cookie信息一般保存在计算机AppData中

一个网站Cookie是否存在上限:

  • 一个Cookie只能保存一个信息
  • 一个web站点可以给浏览器发送多个Cookie,最多存放20个Cookie
  • Cookie大小有限制40kb
  • 浏览器设置上限为300个Cookie

删除Cookie

  • 不设置有效期,浏览器关闭,则消失
  • 设置有效期为0,关闭

编码解码:

URLEncoder.encode("孟永龙","utf-8");
URLDecoder.decode(cookie.getValue(),"utf-8");

Cookie和Session的区别:

  • Cookie是把用户的数据写给浏览器,浏览器保存(保存多个)
  • Session是把用户的数据写到独占Session中,服务器保存(保存重要信息,减少资源消耗)
  • Session对象由服务器创建

10. JSP

10.1 初识JSP

Java server pages:Java服务器端页面,本质就是Servlet,用于动态页面开发。

特点:

  • 写JSP页面和写HTML差不多
  • HTML写静态页面,Jsp写动态页面,提供动态数据

10.2 JSP原理

JSP执行:

  • 代码和HTML差不多
  • 服务器内部的执行
    • Tomcat中有一个work目录
    • IDEA中使用Tomcat会生成一个work目录

C:\Users\10254.IntelliJIdea2019.3\system\tomcat\Unnamed_Servlet-Cookie-Session\work\Catalina\localhost\Servlet_Session\org\apache\jsp

jsp页面转变成了java类,无论访问jsp资源,都是在访问Servlet

在这里插入图片描述

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lMYIFp2f-1615810852682)(C:\Users\10254\AppData\Roaming\Typora\typora-user-images\image-20201128075122084.png)]

HttpJspBase.java

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package org.apache.jasper.runtime;

import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.HttpJspPage;
import org.apache.jasper.compiler.Localizer;

public abstract class HttpJspBase extends HttpServlet implements HttpJspPage {
    private static final long serialVersionUID = 1L;

    protected HttpJspBase() {
    }

    public final void init(ServletConfig config) throws ServletException {
        super.init(config);
        this.jspInit();
        this._jspInit();
    }

    public String getServletInfo() {
        return Localizer.getMessage("jsp.engine.info", new Object[]{"2.3"});
    }

    public final void destroy() {
        this.jspDestroy();
        this._jspDestroy();
    }

    public final void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this._jspService(request, response);
    }

    public void jspInit() {
    }

    public void _jspInit() {
    }

    public void jspDestroy() {
    }

    protected void _jspDestroy() {
    }

    public abstract void _jspService(HttpServletRequest var1, HttpServletResponse var2) throws ServletException, IOException;
}

JSP本质上就是一个Servlet

final javax.servlet.jsp.PageContext pageContext;
javax.servlet.http.HttpSession session = null;
final javax.servlet.ServletContext application;
final javax.servlet.ServletConfig config;
javax.servlet.jsp.JspWriter out = null;
final java.lang.Object page = this;
javax.servlet.jsp.JspWriter _jspx_out = null;
javax.servlet.jsp.PageContext _jspx_page_context = null;

内部工作:

  1. 判断请求

  2. 内置对象

    final javax.servlet.jsp.PageContext pageContext;
    javax.servlet.http.HttpSession session = null;
    final javax.servlet.ServletContext application;
    final javax.servlet.ServletConfig config;
    javax.servlet.jsp.JspWriter out = null;
    final java.lang.Object page = this;
    javax.servlet.jsp.JspWriter _jspx_out = null;
    javax.servlet.jsp.PageContext _jspx_page_context = null;
    HttpServletRequest
    HttpServletResponse 
    
  3. 输出页面前的代码

    response.setContentType("text/html;charset=UTF-8");
    pageContext = _jspxFactory.getPageContext(this, request, response,
                                              null, true, 8192, true);
    _jspx_page_context = pageContext;
    application = pageContext.getServletContext();
    config = pageContext.getServletConfig();
    session = pageContext.getSession();
    out = pageContext.getOut();
    _jspx_out = out;
    
  4. 以上这些对象为JSP内置对象,我们可以直接在JSP页面中使用

在JSP页面中

  • 如果是JAVA代码,则生成的Java文件中java代码不变

  • 如果是HTML代码,则会转变为相应的java代码

    out.write("\r\n"); 输出到前端
    在这里插入图片描述

11.MVC模式

在这里插入图片描述

Model:

  • 业务处理:业务逻辑(Service)
  • 数据持久层: CRUD(Dao)

View

  • 显示数据
  • 提供链接发起Servlet请求

Controller (当前阶段 指Servlet)

  • 接收用户请求: (req:请求参数、Session信息)

  • 交给业务层处理对应的代码

  • 控制视图的跳转

    登录—>接收用户请求—>处理用户请求(获取用户账号、密码)–>业务层处理判断 事务–>Dao层查询用户—>连接数据库

12.Filter

12.1 过滤器:用来过率网站的请求数据

  • 处理中文乱码
  • 登录验证

在这里插入图片描述

使用:

  1. 导包(不要导错)

    1. 包 (javax.servlet)
  2. 实现Filter接口,重写方法

    package com.myl.filter;
    
    import javax.servlet.*;
    import java.io.IOException;
    
    /**
     * @ClassName: CharacterEncodingFilter
     * @Description: TODO
     * @author: meyolo
     * @date: 2020/11/28  10:27
     */
    public class CharacterEncodingFilter implements Filter {
        @Override
        //web服务器启动调用初始化
        public void init(FilterConfig filterConfig) throws ServletException {
            System.out.println("CharacterEncodingFilter初始化");
        }
    
        /*
        *   Chain  :  链
        *   1、过滤请求中所有代码,在过滤特定请求时都会执行
        *   2、必须要让过滤器继续执行
        *            chain.doFilter(request,response);
        *
        * */
    
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
            request.setCharacterEncoding("utf-8");
            response.setCharacterEncoding("utf-8");
            response.setContentType("text/html;charset=UTF-8");
    
            System.out.println("CharacterEncodingFilter执行前");
            //让我们的请求继续走,如果不写,程序走到这就会被拦截
            chain.doFilter(request,response);
            System.out.println("CharacterEncodingFilter执行后");
        }
    
        @Override
        //web服务器关闭调用销毁
        public void destroy() {
            System.out.println("CharacterEncodingFilter销毁");
        }
    }
    
    
  3. 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">
    
        <servlet>
            <servlet-name>ShowServlet</servlet-name>
            <servlet-class>com.myl.servlet.ShowServlet</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>ShowServlet</servlet-name>
            <url-pattern>/servlet/show</url-pattern>
        </servlet-mapping>
        <servlet-mapping>
            <servlet-name>ShowServlet</servlet-name>
            <url-pattern>/show</url-pattern>
        </servlet-mapping>
    
        <filter>
            <filter-name>ShowFilter</filter-name>
            <filter-class>com.myl.filter.CharacterEncodingFilter</filter-class>
        </filter>
        <filter-mapping>
            <filter-name>ShowFilter</filter-name>
            <!--        过滤、servlet下面的任何请求都会被这个过滤器过滤-->
            <url-pattern>/servlet/*</url-pattern>
        </filter-mapping>
    </web-app>
    

12.2 Filter实现登录拦截

  1. 用户登录成功后,向Session中放入用户的数据

  2. 进入主页的时候判断用户是否登录:用过滤器拦截

    注意:Session中存的数据,重定向是可以接收到的

    HttpServletRequest request = (HttpServletRequest) req;
    HttpServletResponse response = (HttpServletResponse) resp;
    
    Object usersession = request.getSession().getAttribute(Constant.USER_SESSION);
    if(usersession==null){
        response.sendRedirect("/error.jsp");
    }
    chain.doFilter(request,response);
    
package com.myl.servlet;

import com.myl.utile.Constant;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @ClassName: LoginServlet
 * @Description: TODO
 * @author: meyolo
 * @date: 2020/11/28  16:57
 */
public class LoginServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String username = req.getParameter("username");
        //判断用户登录正确
        if(username.equals("admin")){
            //登录成功,给用户Session中添加一个常量
            req.getSession().setAttribute(Constant.USER_SESSION,req.getSession().getId() );
            resp.sendRedirect("/sys/success.jsp");
        }else{
            resp.sendRedirect("/error.jsp");
        }


    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

package com.myl.servlet;


import com.myl.utile.Constant;
import com.mysql.cj.Session;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @ClassName: LogoutServlet
 * @Description: TODO
 * @author: meyolo
 * @date: 2020/11/28  16:57
 */
public class LogoutServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Object user_session = req.getSession().getAttribute(Constant.USER_SESSION);

        //判断用户是否登录,如果登录(不为空),则清除掉Constant.USER_SESSION
        //此处如果用 req.getSession().invalidate(); 删除Session 有点暴力,会造成资源消耗
        if(user_session!=null){

            req.getSession().removeAttribute(Constant.USER_SESSION);
            resp.sendRedirect("/login.jsp");
        }else{
            resp.sendRedirect("/login.jsp");
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

package com.myl.filter;


import com.myl.utile.Constant;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @ClassName: SysFilter
 * @Description: TODO
 * @author: meyolo
 * @date: 2020/11/28  17:20
 */
public class SysFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
        //此处Filter中的req,resp需要先强转成父类HttpServletRequest,HttpServletResponse
        //然后调用Session,进行判断
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;

        Object usersession = request.getSession().getAttribute(Constant.USER_SESSION);
        if(usersession==null){
            response.sendRedirect("/error.jsp");
        }
        chain.doFilter(request,response);


    }

    @Override
    public void destroy() {

    }
}

package com.myl.utile;

/**
 * @ClassName: Constant
 * @Description: TODO
 * @author: meyolo
 * @date: 2020/11/28  16:58
 */
public class Constant {
    //设置常量  多个页面引用,易于维护
    public final static String USER_SESSION ="USER_SESSION" ;
}

登录:

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

        <form action="/servlet/login" method="get">
            用户名:<input type="text" name="username">
            <input type="submit">
        </form>
    </body>
</html>

登录成功进入主页

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>主页</title>
</head>
<body>
<h1>主页</h1>
<a href="/servlet/logout">注销</a>
</body>
</html>

错误

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
    <head>
        <title>错误</title>
    </head>
    <body>
        <h1>错误</h1>
        <h2>没有权限访问或者密码错误</h2>

        <a href="/login.jsp">返回登录页面</a>
    </body>
</html>



<servlet>
    <servlet-name>LoginServlet</servlet-name>
    <servlet-class>com.myl.servlet.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>LoginServlet</servlet-name>
    <url-pattern>/servlet/login</url-pattern>
</servlet-mapping>

<servlet>
    <servlet-name>LogoutServlet</servlet-name>
    <servlet-class>com.myl.servlet.LogoutServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>LogoutServlet</servlet-name>
    <url-pattern>/servlet/logout</url-pattern>
</servlet-mapping>

<filter>
    <filter-name>SysFilter</filter-name>
    <filter-class>com.myl.filter.SysFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>SysFilter</filter-name>
    <url-pattern>/sys/*</url-pattern>
</filter-mapping>

13.监听器

实现一个监听的方式有N种:

  1. 新建监听器类

    package com.myl.listener;
    
    
    import javax.servlet.ServletContext;
    import javax.servlet.http.HttpSessionEvent;
    import javax.servlet.http.HttpSessionListener;
    
    /**
     * @ClassName: SessionListener
     * @Description: TODO
     * @author: meyolo
     * @date: 2020/11/28  16:06
     */
    public class SessionListener implements HttpSessionListener {
        @Override
        //一旦创建Session,就会触发这个事件
        public void sessionCreated(HttpSessionEvent se) {
            ServletContext servletContext = se.getSession().getServletContext();
            Integer onlineCount = (Integer) servletContext.getAttribute("OnlineCount");
            System.out.println(se.getSession().getId());
            if(onlineCount==null){
                onlineCount = new Integer(1);
            }else{
                int count = onlineCount.intValue();
                onlineCount = new Integer(count+1);
            }
    
            servletContext.setAttribute("OnlineCount",onlineCount);
    
    
        }
    
        @Override
        //一旦销毁Session,触发这个事件
        public void sessionDestroyed(HttpSessionEvent se) {
            ServletContext servletContext = se.getSession().getServletContext();
            Integer onlineCount = (Integer) servletContext.getAttribute("OnlineCount");
    
            if(onlineCount==null){
                onlineCount = new Integer(0);
            }else{
                int count = onlineCount.intValue();
                onlineCount = new Integer(count-1);
            }
    
            servletContext.setAttribute("OnlineCount",onlineCount);
    
    
        }
    }
    
    
  2. xml注册

    <listener>
        <listener-class>com.myl.listener.SessionListener</listener-class>
    </listener>
    
HttpSessionEvent;
   import javax.servlet.http.HttpSessionListener;
   
   /**
    * @ClassName: SessionListener
    * @Description: TODO
    * @author: meyolo
    * @date: 2020/11/28  16:06
    */
   public class SessionListener implements HttpSessionListener {
       @Override
       //一旦创建Session,就会触发这个事件
       public void sessionCreated(HttpSessionEvent se) {
           ServletContext servletContext = se.getSession().getServletContext();
           Integer onlineCount = (Integer) servletContext.getAttribute("OnlineCount");
           System.out.println(se.getSession().getId());
           if(onlineCount==null){
               onlineCount = new Integer(1);
           }else{
               int count = onlineCount.intValue();
               onlineCount = new Integer(count+1);
           }
   
           servletContext.setAttribute("OnlineCount",onlineCount);
   
   
       }
   
       @Override
       //一旦销毁Session,触发这个事件
       public void sessionDestroyed(HttpSessionEvent se) {
           ServletContext servletContext = se.getSession().getServletContext();
           Integer onlineCount = (Integer) servletContext.getAttribute("OnlineCount");
   
           if(onlineCount==null){
               onlineCount = new Integer(0);
           }else{
               int count = onlineCount.intValue();
               onlineCount = new Integer(count-1);
           }
   
           servletContext.setAttribute("OnlineCount",onlineCount);
   
   
       }
   }
   
  1. xml注册
   <listener>
       <listener-class>com.myl.listener.SessionListener</listener-class>
   </listener>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值