大数据正式21 朱雀 2022-06-04 09:07 263阅读 0赞 # 大数据正式21 # ### 过滤器 ### * 定义 1. Filter--过滤器 2. 是Servlet中最实用的技术--JavaEE核心技术之一【Servlet+Filter+Listener】 3. 可以拦截对资源的访问,拦截下来后可以是否允许通过时,在之前或之后做一些额外单位操作,所谓的拦截,其实是将代表请求的request对象和代表Response对象拦截下来;责任链模式【依次拦截、检查、和控制】 4. 一个资源看可以被多个过滤器拦截 5. 一个拦截器也可以拦截多个资源 * 图解 * ![NOl7gUZ.png][] * 常见使用场景 * 基于URL的访问控制权限 * 全站乱码解决过滤器 * 自动登录 * 过滤敏感词 * 压缩响应 * 。。。 * 实现一个过滤器的步骤 1. 写一个类实现Filter接口 1. public void init(FilterConfig arg0) throws ServletException * 初始化方法 2. public void doFilter(final ServletRequest arg0, ServletResponse arg1,FilterChain arg2) throws IOException, ServletException * 最核心的方法,在存活期间,会造成此方法的执行,在里面写逻辑代码即可 3. public void destroy() * 在过滤器被销毁之前调用,实现善后操作 4. api * ![z3HekXm.png][] 5. 例 # # package com.peng.filter; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; public class FilterDemo implements Filter { public void destroy() { System.out.println("destory"); } public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throws IOException, ServletException { System.out.println("kernel"); } public void init(FilterConfig arg0) throws ServletException { System.out.println("init"); } } 2. 在web.xml中配置过滤器 # # <!-- 过滤器 --> <filter> <filter-name>FilterDemo</filter-name> <filter-class>com.peng.filter.FilterDemo</filter-class> </filter> <filter-mapping> <filter-name>FilterDemo</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> * filter的生命周期 * 在web应用启动的时候,会创建出应用中配置的过滤器对象,init方法进行初始化操作,之后一直存活,直到web应用销毁时,Filter跟着被销毁,再销毁之前执行destory方法的逻辑。在存活期间,进行对资源的拦截处理(doFilter方法),可以增加before和after方法,进行处理,一层一层进,一层一层出。 * 调用过程 * 如果一个资源被多个过滤器拦截,顺序为【mapping】配置的顺序 * ![LHAgTeX.png][] * 和Filter相关的对象 * FilterConfig过滤器配置对象 1. init方法的参数 2. 获取filter初始化参数 3. 获取ServletContext对象 4. 例子 # # <filter> <filter-name>FilterDemo</filter-name> <filter-class>com.peng.filter.FilterDemo</filter-class> <init-param> <param-name>key1</param-name> <param-value>value1</param-value> </init-param> <init-param> <param-name>key2</param-name> <param-value>value2</param-value> </init-param> </filter> # # public void init(FilterConfig arg0) throws ServletException { System.out.println("init"); Enumeration initParameterNames = arg0.getInitParameterNames(); while (initParameterNames.hasMoreElements()) { String name = initParameterNames.nextElement().toString(); System.out.println(name + "~" + arg0.getInitParameter(name)); } } * 执行效果 * ![s6dzpmS.png][] * FilterChain 1. doFilter函数的参数 2. 代表过滤器链 3. 提供doFilter方法,执行之后的过滤器 # # public void doFilter(final ServletRequest arg0, ServletResponse arg1,FilterChain arg2) throws IOException, ServletException { // 过滤具体操作 // 释放资源--责任链模式,进行下一个过滤器执行操作 arg2.doFilter(arg0, arg1); } ### Filter应用 ### * 全站乱码解决过滤器 * 请求乱码 * GET方式 1. 解决方案一:获取参数,解决乱码,再放回去 * 【有问题:Request方法没setParameter方法】 * ![eSROwk3.png][] 2. 解决方案二:request中的数据包无法改变,只能改变其原始方法 1. 继承【这里不能使用】:对已有对象的改造无效--因为对象是已经生成的,不能new出新的子类对象 2. 可以使用装饰模式装饰request方法【这里能使用】: * 【getParameter(String key)】 * 【getParameterValues()】 * 【getParameterMap】 # # package com.easymall.filter; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.Map; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; public class EncodingFilter implements Filter { private String encode = null; // 初始化过滤器 public void init(FilterConfig arg0) throws ServletException { // 获取ServletContext对象 ServletContext sc = arg0.getServletContext(); // 获取全局变量之编码 this.encode = sc.getInitParameter("encode"); } public void doFilter(final ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throws IOException, ServletException { // 请求乱码-get、post一起解决 MyServletRequest msr = new MyServletRequest((HttpServletRequest) arg0); // 响应乱码 arg1.setCharacterEncoding(encode); arg1.setContentType("text/html;charset=" + encode); // 释放资源 arg2.doFilter(msr, arg1); } // 销毁过滤器方法 public void destroy() { } // 内部类装饰 class MyServletRequest extends HttpServletRequestWrapper { private ServletRequest request = null; private boolean hasNoteEncode = true; public MyServletRequest(HttpServletRequest request) { super(request); this.request = request; } // 改造方法 @Override public String getParameter(String name) { return this.getParameterValues(name) == null ? null : this .getParameterValues(name)[0]; } // 改造方法 @Override public Map<String, String[]> getParameterMap() { try { // 注:第一次map之后就对了,得处理--加一个标记 @SuppressWarnings("unchecked") Map<String, String[]> map = request.getParameterMap(); if (hasNoteEncode) { for (Map.Entry<String, String[]> entry : map.entrySet()) { String[] values = entry.getValue(); for (int i = 0; i < values.length; i++) { values[i] = new String( values[i].getBytes("iso8859-1"), encode); } } hasNoteEncode = false; } return map; } catch (UnsupportedEncodingException e) { e.printStackTrace(); throw new RuntimeException(e); } } // 改造方法 @Override public String[] getParameterValues(String name) { return this.getParameterMap().get(name); } } } 3. 动态代理:通过代理对象来改造,并且通过代理对象访问被代理对象【这里能使用】: # # package com.easymall.filter; import java.io.IOException; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; public class EncodingFilter implements Filter { private String encode = null; public void destroy() { } public void doFilter(final ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throws IOException, ServletException { // 请求乱码-get-- 动态代理 // 将ServletRequest强转为HttpServletRequest final HttpServletRequest hsr = (HttpServletRequest) arg0; // get转码---动态代理方法 // 2、创建代理对象【固定】 // 参数一:被代理对象的类加载器。 实现方式:被代理对象.getClass().getClassLoader() // 参数二:被代理对象的接口数组。 实现方式:被代理对象.getClass().getInterfaces() // 参数三:处理类【用来增强方法的】 // 增强代码需要写在处理类的 invoke方法中即可 HttpServletRequest obj = (HttpServletRequest) Proxy.newProxyInstance( hsr.getClass().getClassLoader(), // 获取被代理类类加载器 hsr.getClass().getInterfaces(), // 获取被代理类实现类的接口 new InvocationHandler() { // 参数一: Object proxy 代理对象。没用 // 参数二: Method method 被代理对象的对应方法 // 参数三: Object[] args 被代理对象对应方法执行时,传递的实参 public Object invoke(Object arg0, Method method, Object[] arg2) throws Throwable { // 针对getParameter方法进行增强 if ("getParameter".equals(method.getName())) { // 获取提交方式 String m = hsr.getMethod(); if ("GET".equalsIgnoreCase(m)) { // 调用原来的方法 String invoke = (String) method.invoke(hsr, arg2); String re = null; try { // 转码 re = new String(invoke .getBytes("iso8859-1"), encode); } catch (Exception e) { } return re; } } return method.invoke(hsr, arg2); } }); // 请求乱码-post arg0.setCharacterEncoding(encode); // 响应乱码 arg1.setCharacterEncoding(encode); arg1.setContentType("text/html;charset=" + encode); // 释放资源 arg2.doFilter(obj, arg1); } public void init(FilterConfig arg0) throws ServletException { ServletContext sc = arg0.getServletContext(); this.encode = sc.getInitParameter("encode"); } } * POST方式 # # arg0.setCharacterEncoding(encode); * 响应乱码 * 解决方案 # # arg1.setCharacterEncoding(encode); arg1.setContentType("text/html;charset=" + encode); ### 自动登录 ### * 不加过滤器的登录 * ![pcyopzj.png][] * 加入过滤器的登录 * ![hbcJtc9.png][] * 在处理用户登录时 1. 首次登录时:判断是否勾选过自动登录 1. 否--进入登录页面 2. 是--保存到cookie【注意:密码的保密性】 2. 再次访问时: 1. 用户未登录+cookie信息账号密码正确-->>自动登录 2. 已经登录过,判断账号密码是否正确-->>正确则进行登录 * 代码示例 # # package com.easymall.filter; import java.io.IOException; import java.net.URLDecoder; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import com.easymall.domain.User; import com.easymall.factory.BasicFactory; import com.easymall.service.UserService; public class AautologinFilter implements Filter { public void destroy() { } public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) arg0; HttpServletResponse response = (HttpServletResponse) arg1; // 只有未登录的用户 if (request.getSession(false) == null || request.getSession().getAttribute("user") == null) { // 只有携带Cookie才自动登录 Cookie[] cookies = request.getCookies(); Cookie autoCookie = null; for (Cookie cookie : cookies) { if ("autologin".equals(cookie.getName())) { autoCookie = cookie; } } if (autoCookie != null) { // 只有自动登录cookie保存的用户名正确才能自动登录 String username = URLDecoder.decode(autoCookie.getValue() .split("#")[0], "utf-8"); String password = autoCookie.getValue().split("#")[1]; UserService userService = BasicFactory.getFactory().getObj( UserService.class); if (userService.checkUsernameAndPassord(username, password)) { // 获取session HttpSession session = request.getSession(); // 在session中加入相应的标记 session.setAttribute("user", new User(-1, username, null, null, null)); // 回到主页 response.getWriter().write("登录成功!正在跳转。。。"); response.setHeader("refresh", "2;url=" + request.getContextPath() + "/index.jsp"); } } } else {// 已经登录过 // 跳转页面的话,会一直进过滤器哦。。。。 } // 放行资源 arg2.doFilter(arg0, arg1); } public void init(FilterConfig arg0) throws ServletException { } } ### 加密 ### * MD5加密算法 * 特点 1. 任意大小的二进制经过MD5计算得到一个独一无二的128位二进制 2. 相同的数据得到的MD5得到的结果相同 3. 不相同的数据得到的MD5得到的结果不同 4. 通常转化为16进制的32位数据 * 数据摘要,数据指纹----之后对比 * 应用 1. 加密存储数据 2. 文件的完整性 3. 数字签名 4. 。。。 * EasyMall中,应该加密的地方 1. Cookie中自动登录的密码的存储 2. 数据库中存放密码的记录,不应该铭文记录 * 代码示例 # # package com.easymall.utils; import java.math.BigInteger; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public class MD5Utils { /** * 使用md5的算法进行加密 */ public static String md5(String plainText) { byte[] secretBytes = null; try { secretBytes = MessageDigest.getInstance("md5").digest( plainText.getBytes()); } catch (NoSuchAlgorithmException e) { throw new RuntimeException("没有md5这个算法!"); } String md5code = new BigInteger(1, secretBytes).toString(16); // 为了防止不够32位,比如一些短的密码生成的数据可能不够32位,那么为了解决这的问题,在数据的前面进行补0操作 for (int i = 0; i < 32 - md5code.length(); i++) { md5code = "0" + md5code; } return md5code; } } ### 补充 ### * ![zyf2Pzb.jpg][] [NOl7gUZ.png]: https://i.imgur.com/NOl7gUZ.png [z3HekXm.png]: https://i.imgur.com/z3HekXm.png [LHAgTeX.png]: https://i.imgur.com/LHAgTeX.png [s6dzpmS.png]: https://i.imgur.com/s6dzpmS.png [eSROwk3.png]: https://i.imgur.com/eSROwk3.png [pcyopzj.png]: https://i.imgur.com/pcyopzj.png [hbcJtc9.png]: https://i.imgur.com/hbcJtc9.png [zyf2Pzb.jpg]: https://i.imgur.com/zyf2Pzb.jpg
相关 大数据正式5 大数据正式5 常见的shell命令 管道命令 管道符| 将两个命令隔开,左边命令的输出就会作为管道右边命令的输入 连续使 旧城等待,/ 2022年06月06日 10:29/ 0 赞/ 233 阅读
相关 大数据正式2 大数据正式2 用户身份与用户组记录的文件 在Linux系统当中,默认情况下所有的系统上的账号信息都记录在/etc/passwd这个文件内(包括root用户), 快来打我*/ 2022年06月06日 08:38/ 0 赞/ 161 阅读
相关 大数据正式10 大数据正式10 jQuery 定义:jQuery是一个“写的更少”,但“做的更多”的轻量级JavaScript函数库 优势 1. 可 ゞ 浴缸里的玫瑰/ 2022年06月05日 06:24/ 0 赞/ 246 阅读
相关 大数据正式21 大数据正式21 过滤器 定义 1. Filter--过滤器 2. 是Servlet中最实用的技术--JavaEE核心技术之一【S 朱雀/ 2022年06月04日 09:07/ 0 赞/ 264 阅读
相关 大数据正式32 大数据正式32 Spring中的JDBC jar包准备 ![zW1gEQQ.png][] bean+properties普通配置 悠悠/ 2022年06月03日 08:44/ 0 赞/ 165 阅读
相关 大数据正式27 大数据正式27 Spring 先来张图简单看一下 ![oQySJMC.png][] spring框架的特点 1 悠悠/ 2022年06月03日 04:38/ 0 赞/ 143 阅读
相关 大数据正式37 大数据正式37 Maven 传统项目存在的弊端 1. 导入jar包得经验丰富 2. 传统项目打包方式不通用,不能很好的支持聚合项 左手的ㄟ右手/ 2022年06月02日 01:46/ 0 赞/ 156 阅读
相关 大数据正式36 大数据正式36 MyBatis的接口形式 注意两点 1. 接口名---namespace值对应 2. 方法名---id一致 淩亂°似流年/ 2022年06月02日 01:12/ 0 赞/ 260 阅读
相关 大数据正式34 大数据正式34 Spring+SpringMVC 小例子 效果图 ![hsIEQmd.png][] 功能说明 川长思鸟来/ 2022年06月02日 00:16/ 0 赞/ 272 阅读
还没有评论,来说两句吧...