JavaWeb--Filter(过滤器)学习(附加)
Posted jinner
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaWeb--Filter(过滤器)学习(附加)相关的知识,希望对你有一定的参考价值。
一、Filter运行原理解析多个Filter执行顺序
1.一个数组:存放与请求相匹配的所有Filter
2.一个Map:Map的key为<url-pattern>的值,value为Filter实例对象的引用
3.执行原理:当请求到达Web服务器时,会先对该请求进行解析,使用解析出的URI作为比较对象,从Map中查找是否存在匹配的key。若存在匹配的key,那么读取其value,即Filter对象的引用,将该引用存入到数组中。然后继续向后查找(这里与servlet的运行原理不同,servlet查找到对应的key,则停止向后查找),直到将该Map查找完毕。这样在数组中就存在按照查找顺序排好序的Filter引用。最后数组初始化完毕,开始按照数组元素顺序进行执行。所有数组中的Filter全部执行完毕,再跳转到请求的目标资源。
(建议:1.查看源码 2.addFilter(ApplicationFilterConfig)--数组的扩容)
二、装饰者设计模式
(1)装饰模式指的是在不必改变原类文件和使用继承的情况下,动态地加强一个对象的功能。
(2)装饰者基类:1:装饰者基类要实现与目标类相同的接口 2:带参构造器(通过带参构造器传入目标对象)3 :重写不对其做任何性的增强(调用目标类的目标方法,但不对其做任何修改)
继承装饰者基类 2:要有带参构造器 3:具体装饰者只对装饰者基类业务方法进行单一的增强(主要通过“装饰者链”不断加强)
package com.jinner.service; //业务逻辑接口 public interface SomeService { String doSome(); }
package com.jinner.service; //目标类 public class ServiceExc implements SomeService { @Override public String doSome() { return " jinner"; } }
package com.jinner.decorator; import com.jinner.service.SomeService; //装饰者基类 //要求1:装饰者要实现与目标类相同的接口 //要求2:无参构造器 //要求3:不对其做任何性的增强 public class SomeServiceDecorator implements SomeService { private SomeService target; //目标对象 public SomeServiceDecorator() { super(); // TODO Auto-generated constructor stub } //通过带参构造器传入目标对象 public SomeServiceDecorator(SomeService target) { super(); this.target = target; } @Override public String doSome() { // 调用目标类的目标方法,但不对其做任何修改 return target.doSome(); } }
package com.jinner.decorator; import com.jinner.service.SomeService; public class ToupperCaseDecoration extends SomeServiceDecorator { public ToupperCaseDecoration() { super(); } public ToupperCaseDecoration(SomeService target) { super(target); } @Override public String doSome() { // TODO Auto-generated method stub return super.doSome().toUpperCase(); } }
package com.jinner.text; import com.jinner.decorator.SomeServiceDecorator; import com.jinner.service.ServiceExc; import com.jinner.service.SomeService; public class Mytext2 { public static void main(String[] args) { //创建目标对象 SomeService target = new ServiceExc(); //使用目标对象作为参数,创建装饰者 SomeService service = new SomeServiceDecorator(target); String result = service.doSome(); System.out.println("result = "+result); } }
三、静态代理设计模式
(1)静态代理类与装饰者间的共同点:
1.都要实现与目标类相同的接口
2.这两个类中都要声明目标对象
3.都可以在不修改目标类的前提下增加目标性能
(2)静态代理类与装饰者间的区别:
1.使用目的不同:
装饰者的使用目的:就是增强目标对象
静态代理的使用目的是:为了保护和隐藏目标对象
2.对于目标对象的获取方式不同:
装饰者获取目标对象要通过带参构造器传进去
静态代理中目标对象的获取:在无参构造器中直接获取
public class SomeServiceProxy implements SomeService { private SomeService target; //在无参构造器中创建目标对象 public SomeServiceProxy() { target = new ServiceExc(); } @Override public String doSome() { // TODO Auto-generated method stub return target.doSome().toUpperCase(); } }
3.功能增强的实现者不同:
装饰者设计模式中存在装饰者基类,其并不真正实现增强,所以存在“装饰者链”的概念
静态代理设计模式中一般不存在父子类的关系,具体增强,就是由代理类完成,无需子类完成,所以不存在“链”的概念
四、post与get方法提交的中文乱码问题(这里指低版本的Tomcat)
(1)tomcat7:
1.没有自动解决中文乱码问题
2.Filter的init和destory要手动实现
(2)tomcat9:
1.解决了中文乱码问题
2.Filter的init和destory要自动实现
(3)post方式提交中文乱码问题:
1.使用过滤器实现,filter的chain.doFilter(arg0, arg1)前加上arg0.setCharacterEncoding("utf-8") 优点:1.避免每个servlet重复代码量 2.修改容易
(4)GET方式提交中文乱码问题:
分析:当用户提交了一个包含中文参数的请求时,浏览器首先将这些中文转化为一个字节序列,发送到服务器,服务器接收这个字节序列后,会按照其默认的字符编码ISO8859-1对其进行解码,此时就产生乱码。但接着,服务器会把将解码过的参数存放到parameterMap(关键)中,那么这个Map中的参数已经是乱码了。
2.因parameterMap中存放的参数已经是乱码,故request.parameter()不能使用。那么重新定义HttpServletRequest,但其不能修改,用装饰者设计模式进行增强。
package com.jinner.text; import java.io.UnsupportedEncodingException; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.Vector; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; //定义具体的请求的装饰者类 public class CustomRequest extends HttpServletRequestWrapper { public CustomRequest(HttpServletRequest request) { super(request); // TODO Auto-generated constructor stub } /** * 要将原始的Map替换为自定义的Map * 原始的map中的数据是乱码 * 自定义的Map中的数据来自于原始的Map,但是由原始Map中的数据解决乱码问题后再放入 */ @Override public Map<String, String[]> getParameterMap() { //新建一个map,将来其中的数据是解决过乱码的。将来用户获取到的Map也是这个Map Map<String,String[]> newMap = new HashMap<>(); //获取原始的Map,其中的数据是包含乱码的 Map<String,String[]> originalMap = super.getParameterMap(); /** * 将原始Map中的数据解决乱码问题后,写进新的的Map * 遍历原始Map */ try { for(String key : originalMap.keySet()) { //获取当前遍历key的所有值 String[] values = originalMap.get(key); //遍历values数组,对第一个值进行中文乱码问题解决 for(int i=0;i<values.length;i++) { //按照字符当前的编码进行打散,即进行编码 byte[] bytes = values[i].getBytes("ISO8859-1"); //按照目标编码进行组装,即进行解码 values[i] = new String(bytes,"UTF-8"); //将解决了乱码问题的数据放入到新的Map中 newMap.put(key, values); } } } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } //返回新创建的Map return newMap; } @Override public Enumeration<String> getParameterNames() { Map<String, String[]> parameterMap = this.getParameterMap(); //keySet转为Vector Set<String> keySet = parameterMap.keySet(); Vector keyVector = (Vector) keySet; //将Vector转换为Enumeration return keyVector.elements(); } @Override public String[] getParameterValues(String name) { //获取自定义的parameterMap Map<String, String[]> parameterMap = this.getParameterMap(); return parameterMap.get(name); } @Override public String getParameter(String name) { // TODO Auto-generated method stub return this.getParameterValues(name)[0]; } }
(5)访问权限过滤器
关键:String servletPath = request.getServletPath();
servletPath.startWith("/****")
以上是关于JavaWeb--Filter(过滤器)学习(附加)的主要内容,如果未能解决你的问题,请参考以下文章
学习日记:关于javaweb filter中过滤了css文件的解决方法