JavaWeb学习的第十七天(Filter过滤器_Listener监听器_全站中文乱码_自动登陆_权限控制)

一、Filter过滤器

1.web开发三大组件

Servlet   Filter  Listener

2.Filter功能简述

Filter 不是一个servlet,它不能产生一个response,它能够在一个request到达servlet之前预处理request,也可以在response离开servlet时处理response

3.Filter原理

4.Filter的使用步骤

4.1 创建类实现Filter接口,并且重写所有得方法

4.2 配置Filter方式一,通过web.xml进行配置

4.2 配置Filter方式二,通过注解进行配置

4.3 在Filter中的doFilter方法中拦截请求


5.Filter的生命周期

创建:       服务器启动的时候会创建Filter   执行init方法
拦截请求:   每一次请求拦截的时候执行doFilter方法(在新的线程中)
销毁:       服务器关闭的时候销毁Filter     执行destory方法

注意:Filter是单例对象
一次请求  -----   request对象 -----  一个线程

6.Filter的执行流程

客户端发送请求到服务器的时候,如果请求路径能够被Filter拦截,先执行Filter的doFilter方法
在filter的doFilter方法中,我们需要执行filterChain.doFilter(servletRequest,servletResponse);
在这个方法执行前的代码我们可以针对request做增强
在这个方法执行后的代码我们可以针对response做增强

7.多个Filter执行过程

多个Filter如果是web.xml配置,谁先配置(Filter-mapping),谁先执行

如果是注解配置,按照类名的字典顺序去依次执行(这种方法不靠谱,不建议使用)

8.Filter拦截方式

二、全站中文乱码解决

1.在Filter中的doFilter方法中添加对请求和响应的字符编码,这样可以避免每次都需要在Servlet处理请求时处理字符编码问题了
在这里插入图片描述

package com.bianyiit.anli02;

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

public class FilterDemo1 implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //在filterChain.doFilter()这个方法执行前的代码我们可以针对request做增强,这里用来解决获取请求时的乱码问题
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        request.setCharacterEncoding("utf-8");
        //放行请求
        filterChain.doFilter(servletRequest,servletResponse);
        //在filterChain.doFilter()这个方法执行后的代码我们可以针对response做增强,这里用来解决浏览器响应数据的乱码问题
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        response.setContentType("text/html;charset=utf-8");
    }

    @Override
    public void destroy() {

    }
}

三、自动登陆案例的实现

1.新建一个login.jsp页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>登陆页面</title>
</head>
<body>
    <form method="post" action="${pageContext.request.contextPath}/loginServlet">
        <input type="text" name="username" placeholder="请输入用户名"><br>
        <input type="password" name="password" placeholder="请输入密码"><br>
        <input type="checkbox" name="autologin" value="true">七天内免登陆<br>
        <input type="submit" value="提交">
    </form>
</body>
</html>


2.新建一个index.jsp页面,用来完成用户登陆成功之后的跳转操作

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
    欢迎您${sessionScope.username}登陆成功
  </body>
</html>

2.新建一个LoginServlet,登陆成功之后重定向至index.jsp页面,登陆失败之后打印登陆失败

package com.bianyiit.an01;

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

@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        String autologin = request.getParameter("autologin");
        if(username.equals("flyhigh")&&password.equals("123")){
            //判断用户是否勾选了自动登陆
            if(autologin.equals("true")){
                //把用户名,密码保存到cookie中
                Cookie cookie=new Cookie("autologin",username+"="+password);
                cookie.setMaxAge(7*24*60*60);
                response.addCookie(cookie);
            }
            /*登陆成功之后将用户信息保存到Session中*/
            request.getSession().setAttribute("username",username);
            request.getRequestDispatcher("/index.jsp").forward(request,response);
        }else{
            response.getWriter().println("登陆失败!!");
        }
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
}

注意:

这里使用到了cookie和session
用户第一次登陆成功之后会将用户信息通过cookie保存在浏览器中,下次用户访问资源的时候会自动携带这个cookie进行自动登陆
通过Session将用户信息保存在服务器,这样无论在全站的哪个位置都可以拿到用户信息了

3.新建一个Filter,用来完成用户第二次登陆时能够进行自动登陆

package com.bianyiit.web;

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

@WebFilter("/*")
/*1.创建类实现filter的接口,然后重写filter所有的方法
* 2.配置Filter
* 3.在Filter中的doFilter方法中拦截请求*/
public class Filter01 implements Filter {
    public void destroy() {
        //Filter销毁的时候执行的方法
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        //拦截请求的时候会执行的方法
        HttpServletRequest request = (HttpServletRequest) req;
        request.setCharacterEncoding("utf-8");
        //自动登陆(判断是否有自动登陆的cookie,如果有,自动登陆)
        Object username1 = request.getSession().getAttribute("username");
        if(username1==null){
            Cookie[] cookies = request.getCookies();
            for (Cookie cookie : cookies) {
                if(cookie.getName().equals("autologin")){
                    String value = cookie.getValue();
                    String[] split = value.split("=");
                    String username = split[0];
                    String password = split[1];
                    if(username.equals("flyhigh")&&(password.equals("123"))){
                        request.getSession().setAttribute("username",username);
                    }
                }
            }
        }
        chain.doFilter(req, resp);/*放行请求*/
        HttpServletResponse response = (HttpServletResponse) resp;
        response.setContentType("text/html;charset=utf-8");
    }

    public void init(FilterConfig config) throws ServletException {
        //Filter创建的时候执行的方法
    }

}

输出结果截图
1.用户第一次进行登陆的时候,需要输入正确的用户名和密码,并且勾选七天免密登陆

2.登陆成功之后的主界面,这是我们可以在这个页面显示我们的用户名了

3.用户关闭浏览器后,重新打开浏览器直接访问主界面,我们可以看到用户处于自动登陆状态

四、完整的实现一个登录的案例

1.src下面创建下面的一些包

2.web下面copybootstrap的三个包css/font/js,在WEB-INF中创建lib文件夹,导入下面的jar包,并添加依赖,在web目录下创建login.jsp

链接:https://pan.baidu.com/s/13WetXmoPz334m4JRJWMEVg 
提取码:fe0d 
复制这段内容后打开百度网盘手机App,操作更方便哦


3.在web下创建一个order和product两个文件夹

4.在login.jsp中添加下列代码

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
    <title>Bootstrap 101 Template</title>

    <!-- Bootstrap -->
    <link href="css/bootstrap.min.css" rel="stylesheet">
    <!-- jQuery (Bootstrap 的所有 JavaScript 插件都依赖 jQuery,所以必须放在前边) -->
    <script src="js/jquery-3.2.1.min.js"></script>
    <!-- 加载 Bootstrap 的所有 JavaScript 插件。你也可以根据需要只加载单个插件。 -->
    <script src="js/bootstrap.min.js"></script>

    <!-- HTML5 shim 和 Respond.js 是为了让 IE8 支持 HTML5 元素和媒体查询(media queries)功能 -->
    <!-- 警告:通过 file:// 协议(就是直接将 html 页面拖拽到浏览器中)访问页面时 Respond.js 不起作用 -->
    <!--[if lt IE 9]>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/html5shiv.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dest/respond.min.js"></script>
    <![endif]-->
</head>
<body>
<!--留白的-->
<div class="container">
    <br>
    <hr width="50%">
    <div style="color: red;text-align: center">
        ${errorMsg}
    </div>
    <form class="form-horizontal" action="${pageContext.request.contextPath}/loginServlet" method="post">
        <div class="form-group">
            <label for="username" class="col-sm-4 control-label">请输入用户名</label>
            <div class="col-sm-3">
                <input type="text" class="form-control" id="username" name="username">
            </div>
        </div>
        <div class="form-group">
            <label for="password" class="col-sm-4 control-label">请输入密码</label>
            <div class="col-sm-3">
                <input type="password" class="form-control" id="password" name="password">
            </div>
        </div>
        <div class="form-group">
            <div class="col-sm-offset-4 col-sm-10">
                <button type="submit" class="btn btn-default">登录</button>
            </div>
        </div>
    </form>
    <hr width="50%">
    </div>
</body>
</html>


5.使用Mysql创建一个login数据库,并在这个数据库下新建一张表,这张表的字段如下所示


6.在src/com.bianyiit/domian下创建一个User实体类,这个实体类要与数据库的字段匹配

package com.bianyiit.domain;

public class User {
    private int id;
    private String username;
    private String password;

    public User() {
    }

    public User(int id, String username, String password) {
        this.id = id;
        this.username = username;
        this.password = password;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

7.在src/com.bianyiit/web/servlet下创建一个LoginServlet用来接收请求参数

package com.bianyiit.web.servlet;

import com.bianyiit.domain.User;
import com.bianyiit.service.UserService;
import org.apache.commons.beanutils.BeanUtils;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;

@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    	//处理请求时中文乱码问题
    	request.setCharacterEncoding("utf-8");
        //1.获取所有请求参数
        Map<String, String[]> parameterMap = request.getParameterMap();
        User user=new User();
        try {
            BeanUtils.populate(user,parameterMap);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //2.调用Service处理登录的业务逻辑
        UserService userService = new UserService();
        User loginUser=userService.login(user);
        System.out.println(loginUser);
        //3.根据业务处理结果响应数据
        if(loginUser==null){
            request.setAttribute("errorMsg","用户不存在");
            request.getRequestDispatcher("/login.jsp").forward(request,response);
        }else{
            if(user.getPassword().equals(loginUser.getPassword())){
            	//用户登陆成功之后清除掉之前设置的错误信息
             	request.removeAttribute("essorMsg");
                //用户登录成功之后一定要保存用户信息到服务器
                request.getSession().setAttribute("loginUser",loginUser);
                response.sendRedirect(request.getContextPath()+"/index.jsp");
            }else{
                request.setAttribute("errorMsg","密码不正确");
                request.getRequestDispatcher("/login.jsp").forward(request,response);
            }
        }
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
}

8.在src/com.bianyiit/service下创建一个UserService类用来处理业务逻辑

package com.bianyiit.service;

import com.bianyiit.dao.UserDao;
import com.bianyiit.domain.User;

public class UserService {
    public User login(User user) {
        UserDao userDao = new UserDao();
        return userDao.findUserByName(user.getUsername());
    }
}

9.在src下面创建一个druid.properties配置文件

driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/login
username=root
password=123
#初始化时连接池中连接对象的个数
initialSize=5
#最大的连接对象的个数
maxActive=10
#超时时间(延迟三秒报错)
maxWait=3000

10.在src/com.bianyiit/util下新建一个JDBCUtils类

package com.bianyiit.util;

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;

//Druid连接池的工具类
/*
 * 1.获取连接池对象
 * 2.获取连接对象
 * 3.归还连接对象的方法
 * 4.静态代码块(因为在创建连接池对象之前就需要加载好配置文件中的所有信息)
 * */
public class JDBCUtils {
    private static DataSource ds;
    //用来加载配置文件并创建好一个连接池对象
    static {
        Properties ps=new Properties();
        try {
            ps.load(JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties"));
            ds = DruidDataSourceFactory.createDataSource(ps);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //获取连接对象的方法
    public static Connection getConnection() throws SQLException {
        return ds.getConnection();
    }
    //有没有必要提供一个获取连接池对象的方法??---框架中可能只需要连接池对象,不需要连接对象
    public static DataSource getDataSource(){
        return ds;
    }
    //归还连接对象的方法
    //有一种是有结果集的连接(查询),
    public static void close(PreparedStatement psmt, Connection con, ResultSet rs){
        try {
            if(psmt!=null){
                psmt.close();
                psmt=null;
            }
            if(con!=null){
                con.close();
                con=null;
            }
            if(rs!=null){
                rs.close();
                rs=null;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    //有一种没有结果集的连接(增删改)
    public static void close(PreparedStatement psmt, Connection con){
        try {
            if(psmt!=null){
                psmt.close();
                psmt=null;
            }
            if(con!=null){
                con.close();
                con=null;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

11.在src/com.bianyiit/dao下创建一个UserDao类

package com.bianyiit.dao;

import com.bianyiit.domain.User;
import com.bianyiit.util.JDBCUtils;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;

//data Access object
public class UserDao {

    public User findUserByName(String username) {
        JdbcTemplate jdbcTemplate = new JdbcTemplate(JDBCUtils.getDataSource());
        User user = null;
        try {
            String sql="select * from message where username=?";
            user = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<User>(User.class), username);
        } catch (DataAccessException e) {
            e.printStackTrace();
        }
        return user;
    }
}

12.在web目录下新建一个index.jsp,当用户输入正确的用户名和密码时跳转的页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    淘宝后台管理系统首页<br>
    <a href="order/orderDetail.jsp">订单详情管理</a><br>
    <a href="../order/orderlist.jsp.jsp">订单列表管理</a><br>
    <a href="product/productDetail.jsp">产品详情管理</a><br>
    <a href="product/productlist.jsp">产品列表管理</a><br>
</body>
</html>

13.结果演示截图
1.当用户名和密码都正确时点击登陆


2.用户名正确,但是密码错误,点击登陆

3.用户名错误,密码正确,点击登陆

五、Listener监听器

1.监听器的监听对象是什么??

1.JavaWeb中的监听器是用来监听域对象(request  session  ServletContext)
2.这里主要对ServletContext进行学习,监听ServletContext对象的创建和销毁的
3.由于ServletContext在服务器启动时创建,在服务器关闭时销毁,所以我们使用监听器对这个域对象进行监听时,可以监听服务器的启动和关闭

2.Listenter监听器的使用步骤

2.1 编写类实现ServletConextListener接口,重写方法
package com.bianyiit.Listenter;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

public class MyListener implements ServletContextListener {
    /*
    * 监听ServletContext对象的创建
    * 服务器启动的时候
    * 监听服务器的启动
    * 服务器启动的时候可以在这个监听器中去加载资源(加载配置文件)
    * */
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        servletContextEvent.getServletContext().getResourceAsStream("WEB-INF/classes/jdbc.properties");
    }
    /*
    * 监听ServletContext对象的销毁
    * 监听服务器的关闭
    * */
    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {

    }
}
2.2 通过web.xml配置Listener
<?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">
    <!--配置Listener-->
    <listener>
        <listener-class>com.bianyiit.Listenter.MyListener</listener-class>
    </listener>
</web-app>
2.2 通过注解配置Listener


3.Session对象的创建

在一次会话中:第一次调用Request.getSession()
访问Servlet:不一定,只有第一次调用Request.getSession()才会去创建
访问jsp:会,因为jsp有九大内置对象,其中就包括Session对象

4.request对象的创建

在一次请求中,创建request对象
当用户访问Jsp servelet html的时候tomcat在处理之前都会生成request和response对象
只要我们需要用的时候可以直接去拿这两个对象,不需要的时候可以不用,但是只要用户请求了资源就会创建
发布了73 篇原创文章 · 获赞 11 · 访问量 2436

猜你喜欢

转载自blog.csdn.net/weixin_43908333/article/details/103862344
今日推荐