欢迎您访问365答案网,请分享给你的朋友!
生活常识 学习资料

filter&listener

时间:2023-08-05
第一章-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("zs@hello.com"));//设置发件人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 = "ls@hello.com";// 收件人邮箱// String emailMsg = "激活账户";// sendMail(toEmail,emailMsg);String fromName = "ww";// 发件人邮箱的名字String password = "123456";// 发件人邮箱的密码String fromEmail = "ww@hello.com";// 发件人的邮箱String toEmail = "zs@hello.com";// 收件人的邮箱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代码发送邮件使用工具类调用方法,传入参数即可

Copyright © 2016-2020 www.365daan.com All Rights Reserved. 365答案网 版权所有 备案号:

部分内容来自互联网,版权归原作者所有,如有冒犯请联系我们,我们将在三个工作时内妥善处理。