filter&listener

filter&listener,第1张

filter&listener 第一章-Filter 1.1 Filter概述 什么是filter

过滤器是一个运行在服务器的程序, 优先于请求资源(Servlet或者jsp,html)之前执行. 过滤器是javaweb技术中最为实用的技术.也就是说在程序中访问服务器资源时,当一个请求到来,服务器首先判断是否有过滤器与请求资源相关联,如果有,过滤器可以将请求拦截下来,完成一些特定的功能,再由过滤器决定是否交给请求资源。如果没有则像之前那样直接请求资源了。响应也是类似的!Filter接口:创建一个类实现Filter接口,该类就是一个过滤器类,如果要让过滤器起到过滤的作用,还需要配置拦截路径 过滤器的作用

​ 对目标资源(Servlet,jsp)进行过滤.

​ 应用场景:登录权限检查,解决网站乱码,过滤敏感字符 ...

1.2 Filter入门

Filter 是一个接口。如果想实现过滤器的功能,必须实现该接口,然后配置过滤的路径! 通过xml配置方式

创建一个类实现Filter接口在web.xml文件中配置过滤路径

public class FilterDemo1 implements Filter {
    public void destroy() {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        // 过滤...
        System.out.println("来到了FilterDemo1过滤器...");

        // 放行
        chain.doFilter(req, resp);
    }

    public void init(FilterConfig config) throws ServletException {

    }

}

在web.xml对过滤器进行配置


    FilterDemo01
    com.geekly.web.filter.FilterDemo01


    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        //1.获取Filter的初始化参数
        String akey = filterConfig.getInitParameter("akey");
        System.out.println("FilterDemo04-akey = " + akey);
        //2.获取ServletContext对象
        ServletContext servletContext = filterConfig.getServletContext();
        System.out.println("FilterDemo04-servletContext = " + servletContext);
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("FilterDemo04...");

        filterChain.doFilter(servletRequest, servletResponse);
    }

    @Override
    public void destroy() {

    }
}
1.4 映射路径

​ 假设有一个管理员权限的过滤器,它应该对用户发出的管理员功能的请求进行条件的过滤。但是当用户发出登录、注册等请求的时候,不应该进行过滤。所以我们过滤器,应该有选择的过滤器请求。这就需要学习配置过滤器不同的映射路径,从而让过滤器过滤希望过滤器的请求。

完全路径匹配

以"/"开始

/demo01 ---> 过滤器只能拦截路径/demo01; 
目录匹配

以"/"开始 以 *结束 .



@WebFilter(value = "/ServletDemo9",dispatcherTypes = {DispatcherType.REQUEST,DispatcherType.FORWARD})
public class FilterDemo9 implements Filter {
    public void destroy() {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        System.out.println("来到了FilterDemo9过滤器,然后不放行....");
        // 放行
        //chain.doFilter(req, resp);
    }

    public void init(FilterConfig config) throws ServletException {

    }
}
1.6 过滤器链

概述: FilterChain 是一个接口,代表过滤器链对象。过滤器可以定义多个,就会组成过滤器链。过滤器链作用:当一个filter收到请求的时候,调用chain.doFilter才可以访问下一个匹配的filter,若当前的filter是最后一个filter,调用chain.doFilter才能访问目标资源

过滤器链执行顺序:

配置文件: 谁先配置filter-mapping 谁先执行注解方式: 按照Filter的首字母顺序 eg: AFilter BFilter A在B的前面, AFilter先执行既有配置文件又有注解方式:先执行配置方式在执行注解方式

@WebFilter("/ServletDemo10")
public class FilterDemo10 implements Filter {
    public void destroy() {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        // 过滤
        System.out.println("来到了FilterDemo10过滤器...");

        // 过滤器链对象放行
        chain.doFilter(req, resp);

        // 放行之后执行
        System.out.println("FilterDemo10过滤器放行之后执行的代码...");
    }

    public void init(FilterConfig config) throws ServletException {

    }

}
@WebFilter("/ServletDemo10")
public class FilterDemo11 implements Filter {
    public void destroy() {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        // 过滤
        System.out.println("来到了FilterDemo11过滤器...");

        // 过滤器链对象放行
        chain.doFilter(req, resp);

        // 放行之后执行
        System.out.println("FilterDemo11过滤器放行之后执行的代码...");
    }

    public void init(FilterConfig config) throws ServletException {

    }
}
@WebServlet("/ServletDemo10")
public class ServletDemo10 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("执行ServletDemo10...");
    }

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

结果:

来到了FilterDemo10过滤器...
来到了FilterDemo11过滤器...
执行ServletDemo10...
FilterDemo11过滤器放行之后执行的代码...
FilterDemo10过滤器放行之后执行的代码...
1.7:统一全网站中文乱码的处理 需求分析

​ 在整个网站中,可能会有get请求或post请求向服务器提交参数.参数中往往有中文信息.在后台每个Servlet中都需要去处理乱码.

​ 我们想做的是:请求到达Servlet中.就可以直接调用getParameter方法获得请求参数,请求参数已经没有乱码了.

代码实现
package com.geekly.web.filter;

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

@WebFilter("
public class MailUtil {
	private MailUtil(){}
	
	public static void sendMail(String toEmail, String emailMsg) throws Exception {
		//1_创建Java程序与eyou邮件服务器的连接对象
		Properties props = new Properties();
		props.put("mail.smtp.host", "localhost");
		props.put("mail.smtp.auth", "true");
		Authenticator auth = new Authenticator() {
			public PasswordAuthentication getPasswordAuthentication() {
				return new PasswordAuthentication("zs", "123456"); //类似登录
			}
		};
		Session session = Session.getInstance(props, auth);
		//2_创建一封邮件
		Message message = new MimeMessage(session);
		message.setFrom(new InternetAddress("[email protected]"));//设置发件人
		message.setRecipient(RecipientType.TO, new InternetAddress(toEmail));//设置收件人
		message.setSubject("用户激活");
		message.setContent(emailMsg, "text/html;charset=UTF-8");//设置发送的内容
		//3_发送邮件
		Transport.send(message);
	}

	public static void sendMail(String fromName,String password,String fromEmail,String toEmail,String subject, String emailMsg) throws Exception {
		//1_创建Java程序与eyou邮件服务器的连接对象
		Properties props = new Properties();
		props.put("mail.smtp.host", "localhost");
		props.put("mail.smtp.auth", "true");
		Authenticator auth = new Authenticator() {
			public PasswordAuthentication getPasswordAuthentication() {
				return new PasswordAuthentication(fromName, password); //类似登录
			}
		};
		Session session = Session.getInstance(props, auth);
		//2_创建一封邮件
		Message message = new MimeMessage(session);
		message.setFrom(new InternetAddress(fromEmail));//设置发件人
		message.setRecipient(RecipientType.TO, new InternetAddress(toEmail));//设置收件人
		message.setSubject(subject);
		message.setContent(emailMsg, "text/html;charset=UTF-8");//设置发送的内容
		//3_发送邮件
		Transport.send(message);
	}
	
	public static void main(String[] args) throws Exception{
		// String toEmail = "[email protected]";// 收件人邮箱
		// String emailMsg = "激活账户";
		// sendMail(toEmail,emailMsg);
		String fromName = "ww";// 发件人邮箱的名字
		String password = "123456";// 发件人邮箱的密码
		String fromEmail = "[email protected]";// 发件人的邮箱
		String toEmail = "[email protected]";// 收件人的邮箱
		String subject = "5月份会议内容";// 邮件主题
		String emailMsg = "5月份一直加班到月底....";// 邮件内容
		sendMail(fromName,password,fromEmail,toEmail,subject,emailMsg);

		System.out.println("发送邮件成功!");
	}
}
第四章-扩展 1.密码加密

可逆: 加密之后还可以解密不可逆: 加密之后 不可以解密 2.MD5加密算法

不可逆步骤 直接拷贝工具类进行加密 3.保证MD5加密算法安全

    前端控制(避免密码过于简单),加密多次

    加盐

4.修改注册和登录功能(密码的加密)

登陆的时候 按照 注册那种方式加密一下, 再去查询数据库 就OK了

修改注册Servlet的代码

package com.geekly.web;

import com.geekly.bean.User;
import com.geekly.utils.C3P0Utils;
import com.geekly.utils.Md5Util;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.dbutils.QueryRunner;

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("/ServletRegister")
public class ServletRegister extends HttpServlet {


    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        try {
            //1.处理请求和响应乱码
            request.setCharacterEncoding("utf-8");
            response.setContentType("text/html;charset=utf-8");

            //2.获得浏览器提交的数据(请求参数)
            Map map = request.getParameterMap();

            //3.封装请求参数--->User对象
            User user = new User();
            BeanUtils.populate(user, map);
            // 单独设置状态属性
            user.setStatus("0");
            System.out.println("user:" + user);

            // 对密码进行加密
            // 获得用户输入的密码
            String password = user.getPassword();

            // 对密码进行加盐
            password = user.getUsername() + password + "helloworld123";

            // 使用md5加密
            String md5Password = Md5Util.encodeByMd5(password);

            // 把加密之后的密码存储到user对象中
            user.setPassword(md5Password);

            //4.创建QueryRunner对象
            QueryRunner qr = new QueryRunner(C3P0Utils.getDataSource());

            //5.调用update方法把数据插入到数据库,返回受影响的行数
            String sql = "insert into user values(null,?,?,?,?,?,?,?)";
            Object[] args = {
                    user.getUsername(),
                    user.getPassword(),
                    user.getAddress(),
                    user.getNickname(),
                    user.getGender(),
                    user.getEmail(),
                    user.getStatus()
            };
            int rows = qr.update(sql, args);

            //6.判断受影响的行数:
            if (rows > 0) {
                //6.1 如果大于0,重定向到成功页面(success.html)
                response.sendRedirect(request.getContextPath()+"/login.html");
            } else {
                //6.2 如果不大于0,重定向到失败页面(failed.html)
                response.sendRedirect(request.getContextPath()+"/failed.html");
            }
        } catch (Exception e) {
            e.printStackTrace();
            // 失败了
            response.sendRedirect(request.getContextPath()+"/failed.html");
        }
    }

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

登录Servlet的代码修改

package com.geekly.web;

import com.geekly.bean.User;
import com.geekly.utils.C3P0Utils;
import com.geekly.utils.Md5Util;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;

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;
import java.sql.SQLException;

@WebServlet("/ServletLogin")
public class ServletLogin extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        try {
            // 1.处理乱码
            request.setCharacterEncoding("utf-8");
            response.setContentType("text/html;charset=utf-8");

            // *********************校验验证码*******************************
            // 1.获得用户输入的验证码
            String checkCode = request.getParameter("checkCode");

            // 2.获得事先生成的验证码
            String code = (String) request.getSession().getAttribute("checkCode");

            // 3.校验
            if (!checkCode.equalsIgnoreCase(code)) {
                System.out.println("验证码失败...");
                // 不相等,响应失败页面
                response.sendRedirect(request.getContextPath() + "/failed.html");
                // 提前结束程序
                return;
            }


            // *********************校验用户名和密码*******************************
            // 2.获得请求参数(用户输入的用户名和密码)
            String username = request.getParameter("username");
            String password = request.getParameter("password");

            // 对密码进行加密,使用加密之后的密码进行查询
            // 对密码进行加盐
            password = username + password + "helloworld123";

            // 使用md5加密
            String md5Password = Md5Util.encodeByMd5(password);



            // 3.创建QueryRunner对象
            QueryRunner qr = new QueryRunner(C3P0Utils.getDataSource());

            // 4.调用query方法查询数据库,把结果封装成User对象
            String sql = "select * from user where username = ? and password = ?";
            User user = qr.query(sql, new BeanHandler(User.class), username, md5Password);

            // 5.判断是否登录成功(判断user对象是否为null)
            if (user == null) {
                System.out.println("用户名或者密码错误...");
                // 5.1 如果为null,表示登录失败,重定向到失败页面
                response.sendRedirect(request.getContextPath() + "/failed.html");

            } else {
                // ***************实现记住用户名的功能(登录成功才去记住用户名)*************************
                //1.获得记住用户名复选框的值
                String remember = request.getParameter("remember");

                //2.判断复选框是否勾选(值是否为ok或者null)
                if (remember != null && "ok".equals(remember)) {
                    //3.如果值不为null,为ok,那么就勾选了记住用户名复选框
                    //3.1 创建cookie对象,保存用户名
                    cookie cookie = new cookie("username", username);
                    //3.2 设置cookie对象的有效时长
                    cookie.setMaxAge(60*60*24*7);
                    //3.3 设置cookie对象的有效路径
                    cookie.setPath(request.getContextPath());
                    //3.4 响应cookie对象给浏览器
                    response.addcookie(cookie);
                }else {
                    //4. 如果复选框没有勾选,
                    //3.1 创建cookie对象,保存空值,键还是和之前的cookie的键一样
                    cookie cookie = new cookie("username", "");
                    //3.2 设置cookie对象的有效时长为0
                    cookie.setMaxAge(0);
                    //3.3 设置cookie对象的有效路径,还是和之前的cookie的有效路径一样
                    cookie.setPath(request.getContextPath());
                    //3.4 响应cookie对象给浏览器
                    response.addcookie(cookie);
                }


                // 5.2 如果不为null,表示登录成功,重定向到成功页面
                response.sendRedirect(request.getContextPath() + "/success.html");
            }
        } catch (Exception e) {
            // 异常(失败)
            response.sendRedirect(request.getContextPath() + "/failed.html");
        }


    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
}
5.权限校验(session)

只能校验一个页面,如果多个页面需要校验,就需要每个页面加判断----->改进参考7过滤器权限校验

修改ServletLogin

// 使用session域对象存储user对象
request.getSession().setAttribute("user",user);

// 5.2 如果不为null,表示登录成功,重定向到成功页面
response.sendRedirect(request.getContextPath() + "/success.jsp");

把success.html换成success.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>


    Title




    success....
欢迎${user.username}---退出登录
小子,你还没有登录呢,赶紧去登录
6.退出登录 5.1 思路
    修改success.jsp的超链接 请求LogoutServlet在LogoutServlet里面, 移除session里面存的user, 重定向到首页
5.2实现

超链接




    success....
欢迎${user.username}---退出登录
小子,你还没有登录呢,赶紧去登录

LogoutServlet

@WebServlet("/LogoutServlet")
public class LogoutServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //    移除session对象中的user对象
        request.getSession().removeAttribute("user");
        //     重定向登录页面
        response.sendRedirect("login.jsp");
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
}
7.过滤器进行权限校验

思路:

实现:

登录成之后,需要把user对象存储到session域对象中

定义一个过滤器类

@WebFilter("/*")
public class FilterAuth implements Filter {
    public void destroy() {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        //1.创建一个过滤器类实现过滤器接口
        //2.设置过滤器的路径为 /*
        //3.获取请求的urI路径--->浏览器请求的路径(拦截的路径)
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        String requestURI = request.getRequestURI();

        //4.判断路径中是否包含(index,login,register,......)
        if (requestURI.contains("index") || requestURI.contains("login") || requestURI.contains("register")|| requestURI.contains("ServletCode")) {
            //4.1 如果包含,就直接放行
            chain.doFilter(request, response);
        } else {
            //4.2 如果不包含,就继续校验是否登录
            HttpSession session = request.getSession();
            User user = (User) session.getAttribute("user");

            if (user == null) {
                //4.2.1. 如果没有登录(session对象中的user是否空),就不放行.,重定向到登录页面
                response.sendRedirect("login.jsp");
                return;
            } else {
                //4.2.2  如果有登录(session对象中的user是否空),就放行
                chain.doFilter(request, response);
            }
        }
    }

    public void init(FilterConfig config) throws ServletException {

    }

}
总结
	1.统一全网站中文乱码处理
    2.非法字符过滤
    3.扩展登录权限校验 
    4.退出登录
    5.密码加密和解码
    6.ServletContextListener监听ServletContext的创建和销毁
        
- 能够说出过滤器的作用
    对目标资源(Servlet,jsp)进行过滤.  
	应用场景:登录权限检查,解决网站乱码,过滤敏感字符 ...   

- 能够编写过滤器
  方式一:
       * - 创建一个类实现Filter接口
       * - 在web.xml对过滤器进行配置
  方式二:
       * - 创建一个类实现Filter接口
       * - 直接在这个类上面添加注解进行配置
           
- 能够说出过滤器生命周期相关方法
  1. 服务器启动的时候, 会创建过滤器对象,调用init()方法进行初始化【调用一次】
  2. 任何一次请求都会调用doFilter()方法进行过滤【路径相匹配】
  3. 服务器正常关闭或者项目从服务器移除, 调用destory()方法进行销毁【调用一次】

- 能够说出什么是过滤器链
   当一个filter收到请求的时候,调用chain.doFilter才可以访问下一个匹配的filter,若当前的filter是最后一个filter,调用chain.doFilter才能访问目标资源
           
- 能够编写过滤器解决全局乱码案例
     创建过滤器类,在doFilter方法中处理请求和响应乱码,然后过滤器的路径配置为/*即可
           
- 能够编写ServletContextListener
    1. 创建一个类实现ServletContextListener 
	2. 在web.xml配置监听器

- 能够搭建邮箱服务器	
	邮件服务器搭建
	配置邮箱的域名---->创建用户名和密码
	
- 能够通过Java代码发送邮件
	使用工具类调用方法,传入参数即可

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5722408.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-18
下一篇 2022-12-18

发表评论

登录后才能评论

评论列表(0条)

保存