Servlet过滤器简介
- 格式:doc
- 大小:134.50 KB
- 文档页数:22
onceperrequestfilter的用法在Java Web开发中,Filter是一种常用的技术,用于在请求处理过程中执行特定的操作,例如验证用户身份、清理输出流等。
Filter按照它们的作用方式可以分为两种:过滤所有请求的过滤器和仅过滤特定请求的过滤器。
其中,OncePerRequestFilter是一种仅过滤特定请求的过滤器,它的用法对于一些特定的场景非常重要。
OncePerRequestFilter是一种特殊的过滤器,它只对每个请求执行一次。
这意味着,无论请求被多次调用,OncePerRequestFilter只执行一次。
这对于一些需要在请求处理过程中保持状态的场景非常有用,例如缓存某些结果或跟踪用户行为。
要使用OncePerRequestFilter,需要实现javax.servlet.Filter接口,并重写其doFilter方法。
在doFilter方法中,可以实现只执行一次请求的处理逻辑。
以下是一个简单的示例,展示了如何使用OncePerRequestFilter:```javaimport javax.servlet.*;import javax.servlet.http.HttpServletRequest;import java.io.IOException;public class OncePerRequestFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {// 初始化方法,可以在这里进行一些配置}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {// 获取HttpServletRequest对象HttpServletRequest httpRequest = (HttpServletRequest) request;// 检查是否是第一次访问该请求if (!isFirstTime(httpRequest)) {// 如果不是第一次访问,直接将请求传递给下一个过滤器或Servlet处理chain.doFilter(request, response);return;}// 第一次访问时执行的处理逻辑,例如记录用户行为或缓存数据// ...// 将请求传递给下一个过滤器或Servlet处理chain.doFilter(request, response);}private boolean isFirstTime(HttpServletRequest request) { // 实现判断是否是第一次访问的逻辑,这里可以根据实际情况进行定制// 例如,可以记录请求的唯一标识符,并与之前访问的标识符进行比较String uniqueId = request.getHeader("UniqueId");return uniqueId == null|| !uniqueId.equals(getLastAccessedUniqueId(request));}private StringgetLastAccessedUniqueId(HttpServletRequest request) { // 实现获取上次访问的唯一标识符的逻辑,这里可以根据实际情况进行定制// 可以从数据库、缓存或其他数据源中获取该标识符return "123456"; // 示例值,实际应用中需要根据实际情况获取标识符}@Overridepublic void destroy() {// 销毁方法,可以在这里进行一些清理操作}}```上述示例中,OncePerRequestFilter实现了对特定请求的处理逻辑只执行一次。
java-过滤器Filter_多个Filter的执⾏顺序【Filter链】*在⼀个web应⽤中,可以开发编写多个Filter,这些Filter组合起来称为⼀个Filter链。
*web服务器根据Filter在web.xml中的注册顺序,决定先调⽤哪个Filter,当第⼀个Filter的doFilter⽅法被调⽤时,web服务器会创建⼀个代表Filter链的FilterChain对象传递给该⽅法,在doFilter⽅法中,开发⼈员如果调⽤了FilterChain对象的doFilter⽅法,则web服务器会检查FilterChain对象中是否还有filter,如果有,则调⽤第⼆个filter,如果没有,则调⽤⽬标资源。
【⼯程截图】设计了两个Filter和⼀个Servlet,访问Servlet时,查看Filter的执⾏顺序。
【web.xml】<?xml version="1.0" encoding="UTF-8"?><web-app xmlns:xsi="/2001/XMLSchema-instance" xmlns="/xml/ns/javaee" xsi:schemaLocation="/xml/ns/javaee /xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" <display-name>FilterDemo01</display-name><welcome-file-list><welcome-file>index.jsp</welcome-file></welcome-file-list><!-- 过滤顺序:谁的写在上⾯,谁先被过滤 --><filter><filter-name>FilterTest01</filter-name><filter-class>com.Higgin.web.filter.FilterTest01</filter-class></filter><filter-mapping><filter-name>FilterTest01</filter-name><url-pattern>/*</url-pattern> <!-- 过滤所有 --></filter-mapping><filter><filter-name>FilterTest02</filter-name><filter-class>com.Higgin.web.filter.FilterTest02</filter-class></filter><filter-mapping><filter-name>FilterTest02</filter-name><url-pattern>/*</url-pattern> <!-- 过滤所有 --></filter-mapping></web-app>【FilterTest01.java】package com.Higgin.web.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 FilterTest01 implements Filter{@Overridepublic void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException {System.out.println("FilterTest01 执⾏前---");chain.doFilter(request, response);//让⽬标资源执⾏,即:放⾏System.out.println("FilterTest01 执⾏后---");}@Overridepublic void init(FilterConfig arg0) throws ServletException {}@Overridepublic void destroy() {}}【FilterTest02.java】package com.Higgin.web.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 FilterTest02 implements Filter{@Overridepublic void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException {System.out.println("FilterTest02 执⾏前---");chain.doFilter(request, response); //放⾏System.out.println("FilterTest02 执⾏后---");}@Overridepublic void init(FilterConfig arg0) throws ServletException {}@Overridepublic void destroy() {}}【ServletTest01.java】package com.Higgin.web.servlet;import java.io.IOException;import javax.servlet.ServletException;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;/*** Servlet implementation class ServletTest01*/@WebServlet("/ServletTest01")public class ServletTest01 extends HttpServlet {private static final long serialVersionUID = 1L;public ServletTest01() {super();}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //response.getWriter().write("中国加油!China Come on!");System.out.println("执⾏ServletTest01---");}protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request,response);}}【运⾏结果】在浏览器中输⼊:http://localhost:8080/FilterDemo01/ServletTest01查看控制台输出结果⾃⼰可以尝试分别注释FilterTest01和FilterTest02中的chain.doFilter⽅法,⽤Junit查看具体的执⾏过程。
springboot过滤器FilterRegistrationBean有2种⽅式可以实现过滤器1:通过FilterRegistrationBean实例注册2:通过@WebFilter注解⽣效这⾥选择第⼀种,因为第⼆种不能设置过滤器之间的优先级为了演⽰优先级,这⾥创建2个测试过滤器类:Test1Filter、Test2Filter通过实现javax.servlet.Filter接⼝,覆盖其doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)⽅法,决定拦截或放⾏public class Test1Filter implements Filter {@Overridepublic void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)throws IOException, ServletException {// TODO Auto-generated method stubHttpServletRequest request=(HttpServletRequest)arg0;System.out.println("⾃定义过滤器filter1触发,拦截url:"+request.getRequestURI());arg2.doFilter(arg0,arg1);}}public class Test2Filter implements Filter {@Overridepublic void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)throws IOException, ServletException {// TODO Auto-generated method stubHttpServletRequest request=(HttpServletRequest)arg0;System.out.println("⾃定义过滤器filter2触发,拦截url:"+request.getRequestURI());arg2.doFilter(arg0,arg1);}}通过在springboot的configuration中配置不同的FilterRegistrationBean实例,来注册⾃定义过滤器这⾥创建⼀个configuration类import org.springframework.boot.web.servlet.FilterRegistrationBean;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import com.example.demo.filter.Test1Filter;import com.example.demo.filter.Test2Filter;@Configurationpublic class DemoConfiguration {@Beanpublic FilterRegistrationBean<Test1Filter> RegistTest1(){//通过FilterRegistrationBean实例设置优先级可以⽣效//通过@WebFilter⽆效FilterRegistrationBean<Test1Filter> bean = new FilterRegistrationBean<Test1Filter>();bean.setFilter(new Test1Filter());//注册⾃定义过滤器bean.setName("flilter1");//过滤器名称bean.addUrlPatterns("/*");//过滤所有路径bean.setOrder(1);//优先级,最顶级return bean;}@Beanpublic FilterRegistrationBean<Test2Filter> RegistTest2(){//通过FilterRegistrationBean实例设置优先级可以⽣效//通过@WebFilter⽆效FilterRegistrationBean<Test2Filter> bean = new FilterRegistrationBean<Test2Filter>();bean.setFilter(new Test2Filter());//注册⾃定义过滤器bean.setName("flilter2");//过滤器名称bean.addUrlPatterns("/test/*");//过滤所有路径bean.setOrder(6);//优先级,越低越优先return bean;}}其中1第⼀个bean拦截所有路径,⽽第⼆个只拦截/test/*路径2第⼀个bean优先级设置了1,⽽第⼆个设置了6,越低越优先,所以过滤器1应该在过滤器2前⾯拦截运⾏springboot,访问/test/*请求如下图,再访问/v请求如下图只拦截了过滤器1,⽽过滤器2路径不匹配如果把.addUrlPatterns();中拦截路径改成⼀样/test/*,则所有请求,都会触发2个过滤器,⽽且过滤器1永远在最先拦截。
Web过滤器的处理流程通常包括以下几个关键步骤:
1.初始化阶段:当Web容器启动时,过滤器会被创建并初始化。
在
这个阶段,过滤器可以读取配置参数,获取`FilterConfig`对象,并进行一些初始化操作。
2.请求预处理阶段:在请求到达Servlet之前,过滤器可以对请求进
行预处理。
这个环节常用于执行如日志记录、权限验证、字符编码设置等操作。
3.Servlet执行阶段:经过过滤器预处理后,请求会被传递给目标
Servlet进行处理。
如果存在多个过滤器,那么这些过滤器会按照它们在配置文件中的顺序依次执行。
4.响应后处理阶段:在Servlet生成响应之后,过滤器还可以对服务
器的响应进行后处理。
例如,可以对输出的内容进行压缩或者添加额外的头部信息。
5.销毁阶段:在Web容器关闭时,过滤器会被销毁。
在这个阶段,
可以进行资源的清理工作。
需要注意的是,在编写过滤器时,需要实现`javax.servlet.Filter`接口,并重写其中的`doFilter`方法。
该方法接收`ServletRequest`、`ServletResponse`和`FilterChain`三个参数,分别代表请求、响应和过滤器链。
在`doFilter`方法中,可以编写预处理和后处理的逻辑代码。
此外,还需要通过注解`@WebFilter`或者在`web.xml`文件中配置过滤器的映射信息,以指定过滤器应用于哪些URL模式。
tomcat 过滤规则Tomcat的过滤规则可以通过配置web.xml文件来实现。
过滤器是Web应用程序中一种特殊的组件,用于对Web请求进行预处理或后处理。
以下是配置Tomcat过滤器的一般步骤:1. 在项目的WEB-INF目录下创建一个名为web.xml的文件(如果已存在,则直接打开)。
2. 在web.xml文件中的<web-app>标签中添加过滤器的配置。
示例如下:xml<filter><filter-name>MyFilter</filter-name><filter-class>com.example.MyFilter</filter-class></filter>3. 在web.xml文件中的<web-app>标签中添加过滤器映射的配置。
示例如下:xml<filter-mapping><filter-name>MyFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping>上述示例中,过滤器名称为"MyFilter",过滤器类为com.example.MyFilter。
url-pattern指定了过滤器要处理的URL模式,"*"表示所有的URL。
4. 编写过滤器类com.example.MyFilter。
该类需要继承javax.servlet.Filter 接口,并实现doFilter方法。
在doFilter方法中可以编写具体的过滤逻辑。
示例如下:javaimport javax.servlet.*;import javax.servlet.http.HttpServletRequest;import java.io.IOException;public class MyFilter implements Filter {@Overridepublic void init(FilterConfig config) throws ServletException { 过滤器初始化时执行的代码}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { 过滤逻辑代码HttpServletRequest httpRequest = (HttpServletRequest) request;对请求进行处理...将请求转发给下一个过滤器或Servletchain.doFilter(request, response);}@Overridepublic void destroy() {过滤器销毁时执行的代码}}在doFilter方法中,可以对请求进行处理,并通过调用chain.doFilter方法将请求转发给下一个过滤器或Servlet。
get request filter参数关于GET请求中的Filter参数在Web开发中,我们经常会遇到需要从服务器获取数据的场景。
而GET请求是最常用的一种请求方式,使用GET请求可以从服务器获取特定资源的数据。
而为了更精确地获取所需的数据,我们常常会使用Filter参数来进行筛选和过滤。
本文将详细介绍GET请求中的Filter参数,并一步一步回答您关于此参数的疑问。
1. 什么是Filter参数?Filter参数是GET请求中的一种参数,用于对请求的资源数据进行筛选和过滤。
通常,我们可以通过Filter参数指定特定的条件,以限制服务器返回的数据结果。
例如,在一个商品列表接口中,我们可以使用Filter参数来筛选出价格大于某个值且库存大于某个数量的商品。
2. 如何使用Filter参数?使用Filter参数需要注意以下几个方面:- 首先,需要了解服务器接口支持的Filter参数及其语法规则。
通常,服务器接口文档会提供详细的说明,告诉我们可以使用哪些Filter参数以及如何使用。
- 其次,可以在GET请求的URL中添加Filter参数。
一般情况下,Filter参数会以问号(?)作为分隔符,紧跟在资源路径后面。
例如,假设我们的商品列表接口为:`/api/products`,我们可以使用Filter参数来筛选价格在100到200之间的商品,URL可以写为:`/api/products?price_gt=100&price_lt=200`。
- 最后,需要根据服务器接口的要求,将Filter参数的值进行编码。
特殊字符(如空格、符号等)在URL中必须进行编码,以确保数据能正确传递到服务器端。
3. 常见的Filter参数语法有哪些?常见的Filter参数语法包括:- 等于(eq):筛选出指定属性值等于某个值的数据。
例如,`/api/products?category_eq=electronics` 可以筛选出分类为"electronics"的商品。
过滤器,拦截器,aop区别与使⽤场景1. 什么是过滤器过滤器,顾名思义就是起到过滤筛选作⽤的⼀种事物,只不过相较于现实⽣活中的过滤器,这⾥的过滤器过滤的对象是客户端访问的web资源,也可以理解为⼀种预处理⼿段,对资源进⾏拦截后,将其中我们认为的杂质(⽤户⾃⼰定义的)过滤,符合条件的放⾏,不符合的则拦截下来。
1.1 过滤器常见使⽤场景统⼀设置编码过滤敏感字符登录校验URL级别的访问权限控制数据压缩1.2 springboot整合过滤器bean注⼊⽅式a) 编写Filterpublic class HeFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {System.out.println("您已进⼊filter过滤器,您的请求正常,请继续遵规则...");chain.doFilter(request, response);}@Overridepublic void destroy() {}}b) 编写Filter配置类@Configurationpublic class ServletConfig {@Beanpublic FilterRegistrationBean heFilterRegistration() {FilterRegistrationBean registration = new FilterRegistrationBean(new HeFilter());registration.addUrlPatterns("/*");return registration;}}注解⽅式@Slf4j@Component// filterName就是当前类名称,还有⼀个urlPattens的参数,这个参数表⽰要过滤的URL上的后缀名,是多参数,可以⽤数组表⽰。
Interceptor的基本介绍和使⽤简介java⾥的拦截器是动态拦截Action调⽤的对象,它提供了⼀种机制可以使开发者在⼀个Action执⾏的前后执⾏⼀段代码,也可以在⼀个Action执⾏前阻⽌其执⾏,同时也提供了⼀种可以提取Action中可重⽤部分代码的⽅式。
在AOP中,拦截器⽤于在某个⽅法或者字段被访问之前,进⾏拦截然后再之前或者之后加⼊某些操作。
⽬前,我们需要掌握的主要是Spring的拦截器,Struts2的拦截器不⽤深究,知道即可。
原理⼤部分时候,拦截器⽅法都是通过代理的⽅式来调⽤的。
Struts2的拦截器实现相对简单。
当请求到达Struts2的ServletDispatcher时,Struts2会查找配置⽂件,并根据配置实例化相对的拦截器对象,然后串成⼀个列表(List),最后⼀个⼀个的调⽤列表中的拦截器。
Struts2的拦截器是可插拔的,拦截器是AOP的⼀个实现。
Struts2拦截器栈就是将拦截器按⼀定的顺序连接成⼀条链。
在访问被拦截的⽅法或者字段时,Struts2拦截器链中的拦截器就会按照之前定义的顺序进⾏调⽤。
⾃定义拦截器的步骤第⼀步:⾃定义⼀个实现了Interceptor接⼝的类,或者继承抽象类AbstractInterceptor。
第⼆步:在配置⽂件中注册定义的拦截器。
第三步:在需要使⽤Action中引⽤上述定义的拦截器,为了⽅便也可以将拦截器定义为默认的拦截器,这样在不加特殊说明的情况下,所有的Action都被这个拦截器拦截。
Spring拦截器5.1,抽象类HandlerInterceptorAdapter我们如果在项⽬中使⽤了Spring框架,那么,我们可以直接继承HandlerInterceptorAdapter.java这个抽象类,来实现我们⾃⼰的拦截器。
框架,对java的拦截器概念进⾏了包装,这⼀点和Struts2很类似。
HandlerInterceptorAdapter继承了抽象接⼝HandlerInterceptor。
过滤器filter的配置推荐:多个filter拦截的同⼀个请求,按web.xml配置顺序进⾏过滤返回的响应的从最后配置的filter开始过滤具体配置步骤:编写Filter实现类1package cn.kihyou.b2c.filter;23import java.io.IOException;45import javax.servlet.Filter;6import javax.servlet.FilterChain;7import javax.servlet.FilterConfig;8import javax.servlet.ServletException;9import javax.servlet.ServletRequest;10import javax.servlet.ServletResponse;1112//实现接⼝:javax.servlet.Filter;13public class AdminFilter implements Filter {1415// 三个重要⽅法:初始化:init();拦截到要执⾏的⽅法:doFilter();销毁:destroy();1617 @Override18public void init(FilterConfig filterConfig) throws ServletException {19// TODO Auto-generated method stub20// Filter.super.init(filterConfig);21 }2223 @Override24public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)25throws IOException, ServletException {26// TODO Auto-generated method stub27// 1.拦截客户端/上⼀个filter发来的请求,是否放⾏到Servlet/下⼀个Filter28 System.out.println("AdminFilter拦截到请求");29// 放⾏(放不放⾏您可以⾃⼰看着办)30 chain.doFilter(request, response);31// 2.拦截servlet/filter发回的响应,是否放⾏到客户端/上⼀个filter32 System.out.println("AdminFilter拦截到响应");3334 }3536 @Override37public void destroy() {38// TODO Auto-generated method stub39// Filter.super.destroy();40 }4142 }配置web.xml1<!-- Filter,过滤器 -->2<filter>3<!-- filter名,随便起 -->4<filter-name>AdminFilter</filter-name>5<!-- 实现类所在⽬录 -->6<filter-class>cn.kihyou.b2c.filter.AdminFilter</filter-class>7<!-- 初始化参数 -->8<!-- 设置字符集,charset:UTF-8 -->9<init-param>10<!-- 参数名 -->11<param-name>charset</param-name>12<!-- 参数值 -->13<param-value>UTF-8</param-value>14</init-param>1516<!-- 设置内容类型及其字符集,contentType:text/html;charset=UTF-8 -->17<init-param>18<param-name>contentType</param-name>19<param-value>text/html;charset=UTF-8</param-value>20</init-param>21</filter>2223<!-- filter的映射 -->24<filter-mapping>25<!-- 对应的filter名 -->26<filter-name>AdminFilter</filter-name> 27<!-- 要进⾏拦截过滤的⽬录 -->28<url-pattern>/web/admin/*</url-pattern> 29</filter-mapping>3031<session-config>32<!-- 超时时间,单位:分钟 -->33<session-timeout>30</session-timeout> 34</session-config>。
《JavaWeb开发》课程教学⼤纲(移动互联⽹-姬孟洛)《Java Web开发》课程教学⼤纲课程代码:21134050课程名称:Java Web开发课程性质:专业拓展(选修)学分:3 学时:72讲课学时:36实践/实验学时:36适⽤专业:软件⼯程(移动互联⽹⽅向)先修课程:Java 程序设计、数据库系统、HTML基础⼀、课程⽬标本课程主要介绍动态⽹页⽣成技术的基本原理,了解开发基于JAVA的动态⽹页的基本知识,掌握Web编程技术的基本思想,能够较熟练地掌握使⽤Servlet 和JSP技术进⾏动态⽹站程序设计,能够完成配置JAVA Web的开发环境配置,从⽽培养学⽣B/S架构下的程序设计能⼒,掌握构建⼤型、分布式的电⼦商务应⽤的动态Web⽹站的程序设计技术,为学⽣今后从事软件开发⼯作打下坚实的基础。
⼆、教学内容1.JAVA Web开发⼊门教学要求:了解HTML基础和JavaScript基础,理解JAVA Web的开发⽬标和作⽤,掌握JAVA Web的开发环境JDK、Tomcat、Eclipse、MySQL的配置与使⽤。
教学内容:软件编程体系简介;企业应⽤开发架构;Z J2EE应⽤开发体系;J2EE体系结构的优点;ZN J2EE应⽤开发环境的配置与使⽤。
教学内容:Z JAVA Web的开发环境配置;HTML基础;JavaScript基础;Tomcat的安装与配置;N IDE-- Eclipse的安装与配置;ZN创建第⼀个动态Web项⽬;实验内容:实验⼀JAVA Web开发环境的安装和配置JDK1.6的安装和配置。
Tomcat服务器的安装、运⾏和测试。
Eclipse4.4的安装和测试。
MYSQL的安装和测试。
在Tomcat服务器中部署简单的应⽤程序。
实验⼆ HTML和JavaScript基础练习HTML⽂档基本结构HTML常⽤标签的使⽤表格、链接和图⽚表单标签框架JavaScript语法JavaScript内置对象2.JSP编程教学要求:了解JSP的体系内容,理解JSP的运⾏机制,掌握JSP编程的主要⽅法。
struts核心过滤器FilterDispatcher介绍FilterDispatcher功能介绍FilterDispatcher是struts2的核心控制类负责处理最初的请求分发.四大责任1.执行action2.清空ActionContext上下文3.服务静态的内容(初始化环境等)4.中断请求生命周期中的XWORKS拦截器.FilterDispatcher必须映射所有的请求,除非你只想在某一部分支持struts2的功能.配置filter的url-pattern的时候请使用"/*";1.执行action过滤器根据请求的url判断是否需要调用action(判断的依据是根据actionMapper)如果需要执行action那么处于过滤器链中的其他过滤器将终止,并且调用action.这意味着其他一些一定要执行的过滤器必须放在FilterDispatcher前面.以保证他们的执行.2.清空ActionContext上下文FilterDispatcher讲自动的清除上下文,确保没有内存泄露.但是有时候将导致在集成其他产品时出现某些问题.详情,请看ActionContextUp类3.服务静态的内容FilterDispatcher同时会加载常用的静态内容,例如javascript文件,css文件. FilterDispatcher会查找/struts/*这个目录,并且映射"/struts/"后面的的所有常用的包.以下是默认搜索的包org.apache.struts2.statictemplate例如用户可以通过请求/struts/xhtml/styles.css得到struts2的内置的XHTML UI 主题包下面的默认样式表用户还可以通过为filterDispatcher添加packages参数来添加用户自己的包. FilterDispatcher支持以下初始化参数参数名config 参数值以逗号隔开的配置文件名的列表参数名actionPackages 参数值以逗号隔开的java包名,主要用来扫描检测action参数名configProviders 参数值以逗号隔开的配置提供程序的类名.其他的参数名将被当作是框架的常量.public class FilterDispatcher implementsorg.apache.struts2.StrutsStatics,javax.servlet.Filterorg.apache.struts2.StrutsStatics定义了以下常量这些常量用来获取或者设置请求上下文的对象例如通过ActionContext对象和HTTP_REQUEST我们可以获取或者设置HttpServletRequest对象ActionContext.getContext().put(HTTP_REQUEST,request);HttpServletRequest request=(HttpServletRequest)ActionContext.getContext().get(HTTP_REQUEST);public interface StrutsStatics{public static final String HTTP_REQUEST ="com.opensymphony.xwork2.dispatcher.HttpServletRequest";public static final String HTTP_RESPONSE ="com.opensymphony.xwork2.dispatcher.HttpServletResponse";public static final String SERVLET_DISPATCHER ="com.opensymphony.xwork2.dispatcher.ServletDispatcher";public static final String SERVLET_CONTEXT ="com.opensymphony.xwork2.dispatcher.ServletContext";public static final String PAGE_CONTEXT ="com.opensymphony.xwork2.dispatcher.PageContext";public static final String STRUTS_PORTLET_CONTEXT = "struts.portlet.context"; }import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import .URLDecoder;import java.util.ArrayList;import java.util.Calendar;import java.util.Enumeration;import java.util.HashMap;import java.util.List;import java.util.Map;import java.util.StringT okenizer;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.HttpServletResponse;import mons.logging.Log;import mons.logging.LogFactory;import org.apache.struts2.RequestUtils;import org.apache.struts2.StrutsConstants;import org.apache.struts2.StrutsStatics;import org.apache.struts2.dispatcher.mapper.ActionMapper;import org.apache.struts2.dispatcher.mapper.ActionMapping;import com.opensymphony.xwork2.inject.Inject;import com.opensymphony.xwork2.util.ClassLoaderUtil;import com.opensymphony.xwork2.util.profiling.UtilTimerStack;import com.opensymphony.xwork2.ActionContext;public class FilterDispatcher implementsorg.apache.struts2.StrutsStatics,javax.servlet.Filter{//日志类private static final Log LOG = LogFactory.getLog(FilterDispatcher.class);//路径前缀private String[] pathPrefixes;//为缓存静态内容时设置响应头信息提供日期格式化.private final Calendar lastModifiedCal = Calendar.getInstance();//存储StrutConstants.STRUTS_SERVE_STATIC_CONTENT 的设置,该设置可以通过配置文件设置private static boolean serveStatic;//存储StrutConstants.STRUTS_SERVE_STATIC_BROWSER_CACHE的设置,该设置可以通过配置文件设置.private static boolean serveStaticBrowserCache;//存储字符编码的字符串,该设置可以通过配置文件设置private static String encoding;//通过注入方式提供,ActionMapper的实例private static ActionMapper actionMapper;//FilterConfig过滤器配置类的实例,在init方法中初始化private FilterConfig filterConfig;//为子类暴露Dispatcher对象protected Dispatcher dispatcher;/**初始化过滤器的方法,该方法中创建了一个默认的dispatcher,并且在此方法中设置了静态资源的默认包*/public void init(FilterConfig filterConfig)throws ServletException{this.filterConfig = filterConfig;dispatcher = createDispatcher(filterConfig);dispatcher.init();String param = fitlerConfig.getInitParamter("pagckages");String packages = "org.apache.struts2.static templateorg.apache.struts2.interceptor.debugging";if(param != null){packages = param + " "+packages;}this.pathPrefixes = parse(packages);}/**当应用被终止时调用destroy方法,该方法用来用来释放本地线程和任何的DispatcherListeners**/public void destroy(){if(dispatcher==null){LOG.warn("something is seriously wrong,Dispatcher is not initialized(null)");}else{dispatcher.cleanup();}}/**创建默认的Dispatcher对象.可以通过重写此方法提供用户自定义的Dispatcher */protected Dispatcher createDispatcher(FilterConfig filterConfig){Map<String,String> params = new HashMap<String,String>();for(Enumeration e = fitlerConfig.getIntParameterNames();e.hasMoreElements();) {String e.nextElement();String value = filterConfig.getInitParameter(name);params.put(name,value);}return new Dispatcher(filterConfig.getServletContext(),params);}@Inject(StrutsConstants.STRUTS_SERVE_STATIC_CONTENT)public static void setServeStaticContent(String val){serveStatic = "true".equals(val);}@Inject(StrutsConstants.STRUTS_SERVE_STATIC_BROWSER_CACHE) public static void setServeStaticBrowserCache(String val) {serveStaticBrowserCache = "true".equals(val);}@Inject(StrutsConstants.STRUTS_I18N_ENCODING)public static void setEncoding(String val) {encoding = val;}@Injectpublic static void setActionMapper(ActionMapper mapper) {actionMapper = mapper;}/**某些版本的webLogic只能通过fitler config 返回servlet context对象,该方法解决了这个问题.**/protected ServletContext getServletContext() {return filterConfig.getServletContext();}protected FilterConfig getFilterConfig() {return filterConfig;}/**包装request对象,如果需要的话也可以根据给定的RQUEST用来处理多媒体类型*/protected HttpServletRequest prepareDispatcherAndWrapRequest(HttpServletRequest request,HttpServletResponse response)throws ServletException{Dispatcher du = Dispatcher.getInstance();//如果cleanUp filter 还没有准备好,程序将准备并且包装请求对象.//cleanup 过滤器必须配置在dispatcher filter对象的前面,因此当cleanup filter对象运行的时候,静态的dispatcher对象必须是nullif(du == null){Dispatcher.setInstance(dispatcher);dispatcher.prepare(request,response);}else{dispatcher = du;}try{request = dispatcher.wrapRequest(request,getServletContext());}catch(IOException e){String message = "Could not wrap servlet request with MultipartRequestWrapper!";LOG.error(message,e);throw new ServletException(message,e);}return request;}protected String[] parse(String packages){if(packages == null){return null;}List<String> pathPrefixes = new ArrayList<String>();StringT okenizer st = new StringT okenizer(packeages,", \n\t");while(st.hasMoreT okens()){String pathPrefix = st.nextToken.replace('.','/');if(!pathPrefix.endsWith("/")){pathPrefix+="/";}pathPrefixes.add(pathPrefix);}return pathPrefixes.toArray(new String[pathPrefixes.size()]);}public void doFilter(ServletRequest req,ServletResponse res,FilterChain chain)throws IOException,ServletException{HttpServletRequest request = (HttpServletRequest)req;HttpServletResponse response = (HttpServletResponse)res;ServletContext servletContext = getServletContext();String timerKey = "FilterDispatcher_doFilter:";try{UtilTimerStack.push(timerKey);request = prepareDispatcherAndWrapRequest(request,response);ActionMapping mapping;try{mapping = actionMapper.getMapping(request,dispatcher.getConfigurationManager());}catch(Exception ex){LOG.error("error getting ActionMapping",ex);dispatcher.sendError(request,response,servletContext,HttpServletResponse.SC_INTER NAL_SERVER_ERROR,ex);return;}if(mapping==null){//没有action被请求,是否查找静态资源String resourcePath = RequestUtils.getServletPath(request);if("".equals(resourcePath) && null != request.getPathInfo()){resourcePath = request.getPathInfo();}if(serveStatic && resourcePath.startsWith("/struts")){String /struts".length());findStaticResource(name,request,response);}else{chain.doFilter(request,response);}return;}dispatcher.serviceAction(request,response,servletContext,mapping);}finally{try{ActionContextCleanUp.cleanUp(req);}finally{UtilTimerStack.pop(timerKey);}}}protected void findStaticResource(String name,HttpServletRequest request,HttpServletResponse response)throws IOException{if(!name.endWith(".class")){for(String pathPrefix : pathPrefixes){InputStream is = findInputStream(name,pathPrefix);if(is !=null){Calendar cal = Calendar.getInstance();long ifModifiedSince = 0 ;try{ifModifiedSince = request.getDateHeader("If-Modified-Since");}catch(Exception e){LOG.warn("invalid If-Modified-Since header value:'"+request.getHeader("If-Modified-Since")+"', ignoring");}long lastModifiedMillis = lastModifiedCal.getTimeInMillis();long now = cal.getTimeMillis();cal.add(Calendar.DAY_OF_MONTH,1);long expires = cal.getTimeInMillis();if(ifModifiedSince >0 && ifModiifedSince <= lastModifiedMillis){response.setDateHeader("Expires",expires);response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);is.close();return;}//设置content-typeString contentType = getContentType(name);if(contentType != null){response.setContentType(contentType);}if(serveStaticBrowserCache){response.setDateHeader("Date",now);response.setDateHeader("Expires",expires);response.setDateHeader("Retry-After",expires);response.setHeader("Cache-Control","public");response.setDateHeader("Last-Modified",lastModifiedMillis);}else{response.setHeader("Cache-Control","no-cache");response.setHeader("Pragma","no-cache");response.setHeader("Expires","-1");}try{copy(is,response.getOutputStream());}finally{is.close();}return;}}}response.sendError(HttpServletResponse.SC_NOT_FOUND); }protected String getContentType(String name){if (name.endsWith(".js")){return "text/javascript";}else if (name.endsWith(".css")){return "text/css";}else if (name.endsWith(".html")){return "text/html";}else if (name.endsWith(".txt")){return "text/plain";}else if (name.endsWith(".gif")){return "image/gif";}else if (name.endsWith(".jpg") || name.endsWith(".jpeg")){return "image/jpeg";} else if (name.endsWith(".png")){return "image/png";} else{return null;}}protected void copy(InputStream input, OutputStream output) throws IOException {final byte[] buffer = new byte[4096];int n;while (-1 != (n = input.read(buffer))) {output.write(buffer, 0, n);}output.flush(); // WW-1526}protected InputStream findInputStream(String name, String packagePrefix) throws IOException{String resourcePath;if (packagePrefix.endsWith("/") && name.startsWith("/")){resourcePath = packagePrefix + name.substring(1);} else{resourcePath = packagePrefix + name;}resourcePath = URLDecoder.decode(resourcePath, encoding);return ClassLoaderUtil.getResourceAsStream(resourcePath, getClass());}}。
Filter过滤器的使⽤详解⼀.Filter 什么是过滤器1、Filter 过滤器它是 JavaWeb 的三⼤组件之⼀。
三⼤组件分别是:Servlet 程序、Listener 监听器、Filter 过滤器2、Filter 过滤器它是 JavaEE 的规范。
也就是接⼝3、Filter 过滤器它的作⽤是:拦截请求,过滤响应。
拦截请求常见的应⽤场景有:权限检查、⽇记操作、事务管理……等等⼆.Filter 的初体验要求:在你的 web ⼯程下,有⼀个 admin ⽬录。
这个 admin ⽬录下的所有资源(html 页⾯、jpg 图⽚、jsp ⽂件、等等)都必须是⽤户登录之后才允许访问。
思考:根据之前我们学过内容。
我们知道,⽤户登录之后都会把⽤户登录的信息保存到 Session 域中。
所以要检查⽤户是否登录,可以判断 Session 中是否包含有⽤户登录的信息即可Object user = session.getAttribute("user");// 如果等于 null,说明还没有登录if (user == null) {request.getRequestDispatcher("/login.jsp").forward(request,response);return;}Filter 的⼯作流程图:Filter 的代码:package com.atguigu.filter;import javax.servlet.*;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpSession;import java.io.IOException;public class AdminFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}/*** 专门⽤于拦截请求,过滤响应。
14.1 Servlet过滤器简介 很早之前,Servlet API就已成为企业应用开发的重要工具。现在,Servlet中的过滤器和监听器功能则是对J2EE体系的一个补充。过滤器使得Servlet开发者能够在请求到达Servlet之前截取请求,在Servlet处理请求之后修改应答;而Servlet监听器可以监听客户端的请求、服务端的操作,通过监听器,可以自动激发一些操作,如监听应用的启动和停止等。本章将接着介绍Servlet过滤器和监听器的相关知识以及在实际开发中如何使用这些技术。 本章重点: ● Servlet过滤器简介 ● Servlet过滤器的实现 ● Servlet过滤文本信息 ● Servlet监听器简介 14.1 Servlet过滤器简介
Servlet过滤器是小型的Web组件,能拦截请求和响应,以便查看、提取或以某种方式操作正在客户机和服务器之间交换的数据。过滤器是封装了一些功能的Web组件,这些功能虽然很重要,但是对于处理客户机请求或发送响应来说不是决定性的。典型的例子包括记录关于请求和响应的数据、处理安全协议、管理会话属性等。 一个过滤器可以被关联到任意多个资源,一个资源也可以关联到任意多个过滤器。例如,在图14.1中就有如下的关联关系。 ● F1同时被关联到S1、S2、S3。 ● F1、F2、F3都和S2关联。 图14.1 Web资源与过滤器相关联 关联到同一个资源的过滤器形成一个过滤器链。例如,对S2进行访问时,F1、F2、F3就形成了一个过滤器链,客户要访问资源S2,就要经过F1过滤器,然后是F2、F3,最后才是要访问的资源。如果在经过上面这3个过滤器时出现了错误或者被禁止访问,客户的请求就无法到达资源S2。在Servlet过滤器中,这个过滤器传递的过程是通过FilterChain.dofilter()方法实现的,当过滤器链到达末尾时,这个方法调用请求的资源。建立一个过滤器,一般需要下面4个步骤: (1)建立一个实现Filter接口的类。这个类需要3个方法,即doFilter、init和destroy。doFilter方法包含主要的过滤代码(见第(2)步),在init方法中进行一些初始化的设置,而destroy方法进行清除过滤器占用的资源。 (2)在doFilter方法中放入过滤行为。doFilter方法的第一个参数为ServletRequest对象,为过滤器提供了对进入的信息(包括表单数据、cookie和HTTP请求头)的完全访问。第二个参数为ServletResponse,通常在简单的过滤器中忽略此参数。最后一个参数为FilterChain,用来调用过滤器链中下一个过滤器或者在到达过滤器末尾时调用Servlet或JSP页。 (3)调用FilterChain对象的doFilter方法。Filter接口的doFilter方法将一个FilterChain对象作为它的一个参数。在调用此对象的doFilter方法时,激活下一个相关的过滤器。如果没有另一个过滤器与Servlet或JSP页面关联,则Servlet或JSP页面被激活。 (4)对相应的Servlet和JSP页面注册过滤器。在部署描述符文件(web.xml)中使用filter和filter-mapping元素对需要进行过滤的资源进行配置。 14.2 实现一个Servlet过滤器 Servlet过滤器API包含3个简单的接口,即Filter、FilterChain和FilterConfig,它们位于javax.servlet包中。从编程的角度看,过滤器类将实现Filter接口,然后使用这个过滤器类中的FilterChain和FilterConfig接口。该过滤器类的一个引用将传递给FilterChain对象,以允许过滤器将控制权传递给过滤器链中的下一个过滤器或者资源。FilterConfig对象将由容器提供给过滤器,以允许访问该过滤器的初始化数据。 14.2.1 编写实现类的程序
下面是一个简单的Servlet过滤器的例子,其中将获取一个Web服务器给客户提供服务需要的时间,也就是响应时间。 【本节示例参考:资料光盘\源代码\第14章\14-2\Servlet.java】 【实例14-1】这是一个实现类的程序,主要是使用过滤器处理请求,在处理时可能要耗费很多 时间。 程序14-1 Servlet.java 01 package cn.ac.ict.Filter; 02 import java.io.IOException; 03 import java.io.PrintWriter; 04 import java.io.StringWriter; 05 import java.util.Date; 06 import javax.servlet.*; 07 public class ResponseTimeFilter implements Filter { 08 private FilterConfig filterConfig = null; 09 public void init(FilterConfig config) throws ServletException {//初始化函数 10 this.filterConfig = config; 11 } 12 public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException { 13 Date startTime, endTime; 14 double totalTime; 15 startTime = new Date(); 16 StringWriter sw = new StringWriter(); 17 PrintWriter writer = new PrintWriter(sw); 18 writer.println(); 19 writer.println("ResponseTimeFilter Before call chain.doFilter"); 20 chain.doFilter(request, response); //将请求转发给过滤器链中下一个资源 21 //下面是资源的响应时间 22 //下面计算开始时间和结束时间的差,也就是响应时间 23 endTime = new Date(); 24 totalTime = endTime.getTime() - startTime.getTime(); 25 totalTime = totalTime / 1000; //将毫秒时间转换为以秒为单位 26 writer.println("ResponseTimeFilter Before call chain.doFilter"); 27 writer.println("==============="); 28 writer.println("Total elapsed time is: " + totalTime + " seconds." ); 29 writer.println("==============="); 30 filterConfig.getServletContext().log(sw.getBuffer().toString()); //将信息输出到日志中 31 writer.flush(); 32 } 33 public void destroy() { 34 this.filterConfig = null; 35 } 36 public FilterConfig getFilterConfig() { 37 return null; 38 } 39 public void setFilterConfig(FilterConfig config) { 40 } 41 } 【深入学习】当容器第一次加载该过滤器时,init()方法将被调用。该类在这个方法中包含了一个指向FilterConfig对象的引用。过滤器的大多数时间都消耗在执行过滤操作上,第20行中的doFilter()方法被容器调用,同时传入分别指向这个请求/响应链中的ServletRequest、ServletResponse和FilterChain对象的引用。然后过滤器就有机会处理请求,将处理任务传递给链中的下一个资源(通过调用FilterChain对象引用上的doFilter()方法),之后在处理控制权返回该过滤器时处理响应。 14.2.2 配置发布Servlet过滤器
发布Servlet过滤器时,必须在web.xml文件中加入和ng>元素,其中,元素用来定义一个过滤器,在本例中使用了如下代码: Request Response Time cn.ac.ict.Filter.ResponseTimeFilter 以上代码中,指定过滤器的名字,指定过滤器的完整类名,也可以在元素中内嵌元素来为过滤器提供初始化参数。 元素用于将过滤器和URL关联,本例中的代码如下: Request Response Time /ShowCounter.jsp 当客户请求的URL和指定的URL相匹配时,就会触发ResponseTimeFilter过滤器,这里的元素的值和元素中的name>值应该相同。 说明:如果希望Servlet过滤器能过滤所有的客户请求,可以将的值设置为/*。