servlet3中的多个@WebFilter怎么控制servlet 方法执行顺序序

&之前我们控制多个filter的执行顺序是通过web.xml中控制filter的位置来控制的,放在上面的会比放在下面的先执行,如下&用户登录检查过滤器&会比&接口日志过滤器&先执行
&!-- 用户登录检测过滤器 --&&&& &filter&
&filter-name&UserLoginFilter&/filter-name&&&&&&&&& &filter-class&net.tfgzs.demo.filter.UserLoginFilter&/filter-class&&&& &/filter&&&& &filter-mapping&&&&&&&&& &filter-name&UserLoginFilter&/filter-name&&&&&&&&& &url-pattern&/*&/url-pattern&&&& &/filter-mapping&
&!--接口日志过滤器--&
&filter-name&ApiLog&/filter-name&
&filter-class&net.tfgzs.demo.filter.ApiLog&/filter-class&
&filter-mapping&
&filter-name&ApiLog&/filter-name&
&url-pattern&/*&/url-pattern&
&/filter-mapping&
但是当我们使用@WebFilter注解的时候发现注解里面没有提供可以控制执行顺序的参数
&&&&&@WebFilter 的属性
属性名类型描述
filterName
指定过滤器的 name 属性,等价于 &filter-name&
该属性等价于 urlPatterns 属性。但是两者不应该同时使用。
urlPatterns
指定一组过滤器的 URL 匹配模式。等价于 &url-pattern& 标签。
servletNames
指定过滤器将应用于哪些 Servlet。取值是 @WebServlet 中的 name 属性的取值,或者是 web.xml 中 &servlet-name& 的取值。
dispatcherTypes
DispatcherType
指定过滤器的转发模式。具体取值包括: ASYNC、ERROR、FORWARD、INCLUDE、REQUEST。
initParams
WebInitParam[]
指定一组过滤器初始化参数,等价于 &init-param& 标签。
asyncSupported
声明过滤器是否支持异步操作模式,等价于 &async-supported& 标签。
description
该过滤器的描述信息,等价于 &description& 标签。
displayName
该过滤器的显示名,通常配合工具使用,等价于 &display-name& 标签。
通过实践发现如果想要控制filer的执行顺序可以通过控制filter的文件名来控制
&&&&&& UserLoginFilter.java 和 ApiLog.java 这两个文件里面分别是&用户登录检查过滤器&和&接口日志过滤器&,因为这两个文件的首字母A排U之前,导致每次执行的时候都是先执行&接口日志过滤器&再执行&用户登录检查过滤器&,所以我们现在修改两个文件的名称分别为
Filter0_UserLogin.java
Filter1_ApiLog.java
这样就能先执行&用户登录检查过滤器&再执行&接口日志过滤器&
本文出自 &腾飞工作室& 博客,请务必保留此出处 &&&
阅读(...) 评论()web.xml中filter加载顺序问题 -
- ITeye技术网站
昨天遇到了一个问题,项目中需要用到了urlrewrite,发现地址经过rewrite后,接收到表单post过来的中文数据全是乱码,奇怪了,我的Set Character Encoding这个filter为啥没起作用呢,如下示例,找了半天原因,后来网上找到一篇文章,简单说是filter加载是有顺序的,请看第二个xml,将设置编码方式的filter放到了urlrewrite前面,乱码就不见了,我也不知道具体是为什么,但是通过断点发现这个web.xml中确实是按照你写的先后顺序来执行的,估计是urlrewrite中有转过码,导致filter中再设置编码已经无效。
web.xml示例(接收post中文参数乱码)
&!-- Url Rewrite Filter --&
&filter-name&UrlRewriteFilter&/filter-name&
&filter-class&org.tuckey.web.filters.urlrewrite.UrlRewriteFilter&/filter-class&
&init-param&
&param-name&logLevel&/param-name&
&param-value&INFO&/param-value&
&/init-param&
&filter-mapping&
&filter-name&UrlRewriteFilter&/filter-name&
&url-pattern&/*&/url-pattern&
&/filter-mapping&
&!-- Set Character Encoding --&
&filter-name&Set Character Encoding&/filter-name&
&filter-class&
org.springframework.web.filter.CharacterEncodingFilter
&/filter-class&
&init-param&
&param-name&encoding&/param-name&
&param-value&utf-8&/param-value&
&/init-param&
&filter-mapping&
&filter-name&Set Character Encoding&/filter-name&
&url-pattern&/*&/url-pattern&
&/filter-mapping&
web.xml示例(接收post中文参数没有乱码)
&!-- Set Character Encoding --&
&filter-name&Set Character Encoding&/filter-name&
&filter-class&
org.springframework.web.filter.CharacterEncodingFilter
&/filter-class&
&init-param&
&param-name&encoding&/param-name&
&param-value&utf-8&/param-value&
&/init-param&
&filter-mapping&
&filter-name&Set Character Encoding&/filter-name&
&url-pattern&/*&/url-pattern&
&/filter-mapping&
&!-- Url Rewrite Filter --&
&filter-name&UrlRewriteFilter&/filter-name&
&filter-class&org.tuckey.web.filters.urlrewrite.UrlRewriteFilter&/filter-class&
&init-param&
&param-name&logLevel&/param-name&
&param-value&INFO&/param-value&
&/init-param&
&filter-mapping&
&filter-name&UrlRewriteFilter&/filter-name&
&url-pattern&/*&/url-pattern&
&/filter-mapping&
浏览: 38154 次
来自: 北京
这个pid判断 只能在单服务器启动一个tomcat应用 启动2 ...
你的测试是不是有问题,我看别人做的测试,nio确实提高性能,你 ...
黎明lm 写道能否详细的说名下呢 我也遇到了这个问题 多谢 就 ...
能否详细的说名下呢 我也遇到了这个问题 多谢 就是配置了IK后 ...
george_space 写道直接把SQL写在程序中,这样不太 ...  在WEB Api中,引入了面向切面编程(AOP)的思想,在某些特定的位置可以插入特定的Filter进行过程拦截处理。引入了这一机制可以更好地践行DRY(Don&t Repeat Yourself)思想,通过Filter能统一地对一些通用逻辑进行处理,如:权限校验、参数加解密、参数校验等方面我们都可以利用这一特性进行统一处理,今天我们来介绍Filter的开发、使用以及讨论他们的执行顺序。
一、Filter的开发和调用
&&&&&&&& 在默认的WebApi中,框架提供了三种Filter,他们的功能和运行条件如下表所示:
Filter 类型
实现的接口
Authorization
IAuthorizationFilter
最先运行的Filter,被用作请求权限校验
IActionFilter
在Action运行的前、后运行
IExceptionFilter
当异常发生的时候运行
&&&&&& 首先,我们实现一个AuthorizatoinFilter可以用以简单的权限控制:
public class AuthFilterAttribute : AuthorizationFilterAttribute
public override void OnAuthorization(HttpActionContext actionContext)
//如果用户方位的Action带有AllowAnonymousAttribute,则不进行授权验证
if (actionContext.ActionDescriptor.GetCustomAttributes&AllowAnonymousAttribute&().Any())
var verifyResult = actionContext.Request.Headers.Authorization!=null &&
//要求请求中需要带有Authorization头
actionContext.Request.Headers.Authorization.Parameter == "123456"; //并且Authorization参数为123456则验证通过
if (!verifyResult)
//如果验证不通过,则返回401错误,并且Body中写入错误原因
actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.Unauthorized,new HttpError("Token 不正确"));
&&& 一个简单的用于用户验证的Filter就开发完了,这个Filter要求用户的请求中带有Authorization头并且参数为123456,如果通过则放行,不通过则返回401错误,并在Content中提示Token不正确。下面,我们需要注册这个Filter,注册Filter有三种方法:
第一种:在我们希望进行权限控制的Action上打上AuthFilterAttribute这个Attribute:
public class PersonController : ApiController
[AuthFilter]
public CreateResult Post(CreateUser user)
return new CreateResult() {Id = "123"};
这种方式适合单个Action的权限控制。
第二种,找到相应的Controller,并打上这个Attribute:
[AuthFilter]
public class PersonController : ApiController
public CreateResult Post(CreateUser user)
return new CreateResult() {Id = "123"};
这种方式适合于控制整个Controller,打上这个Attribute以后,整个Controller里所有Action都获得了权限控制。
第三种,找到App_Start\WebApiConfig.cs,在Register方法下加入Filter实例:
public static void Register(HttpConfiguration config)
config.MapHttpAttributeRoutes();  
//注册全局Filter
config.Filters.Add(new AuthFilterAttribute());
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
用这种方式适合于控制所有的API,任意Controller和任意Action都接受了这个权限控制。
在大多数场景中,每个API的权限验证逻辑都是一样的,在这样的前提下使用全局注册Filter的方法最为简单便捷,可这样存在一个显而易见的问题:如果某几个API是不需要控制的(例如登录)怎么办?我们可以在这样的API上做这样的处理:
[AllowAnonymous]
public CreateResult PostLogin(LoginEntity entity)
//TODO:添加验证逻辑
return new CreateResult() {Id = "123456"};
我为这个Action打上了AllowAnonymousAttribute,验证逻辑就放过了这个API而不进行权限校验。
&&& 在实际的开发中,我们可以设计一套类似Session的机制,通过用户登录来获取Token,在之后的交互HTTP请求中加上Authorization头并带上这个Token,并在自定义的AuthFilterAttribute中对Token进行验证,一套标准的Token验证流程就可以实现了。
&&& 接下来我们介绍ActionFilter:
  ActionFilterAttrubute提供了两个方法进行拦截:OnActionExecuting和OnActionExecuted,他们都提供了同步和异步的方法。
  OnActionExecuting方法在Action执行之前执行,OnActionExecuted方法在Action执行完成之后执行。
  我们来看一个应用场景:使用过MVC的同学一定不陌生MVC的模型绑定和模型校验,使用起来非常方便,定义好Entity之后,在需要进行校验的地方可以打上相应的Attribute,在Action开始时检查ModelState的IsValid属性,如果校验不通过直接返回View,前端可以解析并显示未通过校验的原因。而Web API中也继承了这一方便的特性,使用起来更加方便:&&&
public class CustomActionFilterAttribute : ActionFilterAttribute
public override void OnActionExecuting(HttpActionContext actionContext)
if (!actionContext.ModelState.IsValid)
actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.BadRequest,
actionContext.ModelState);
&&& 这个Filter就提供了模型校验的功能,如果未通过模型校验则返回400错误,并把相关的错误信息交给调用者。他的使用方法和AuthFilterAttribute一样,可以针对Action、Controller、全局使用。我们可以用下面一个例子来验证:
代码如下:
public class LoginEntity
[Required(ErrorMessage = "缺少用户名")]
public string UserName { get; set; }
[Required(ErrorMessage = "缺少密码")]
public string Password { get; set; }
[AllowAnonymous]
[CustomActionFilter]
public CreateResult PostLogin(LoginEntity entity)
//TODO:添加验证逻辑
return new CreateResult() {Id = "123456"};
当然,你也可以根据自己的需要解析ModelState然后用自己的格式将错误信息通过Request.CreateResponse()返回给用户。
  OnActionExecuted方法我在实际工作中使用得较少,目前仅在一次部分响应数据加密的场景下进行过使用,使用方法一样,读取已有的响应,并加密后再给出加密后的响应赋值给actionContext.Response即可。
我给大家一个Demo:&
public override async Task OnActionExecutedAsync(HttpActionExecutedContext actionExecutedContext, CancellationToken cancellationToken)
var key = 10;
var responseBody = await actionExecutedContext.Response.Content.ReadAsByteArrayAsync(); //以Byte数组方式读取Content中的数据
for (int i = 0; i & responseBody.L i++)
responseBody[i] = (byte)(responseBody[i] ^ key); //对每一个Byte做异或运算
actionExecutedContext.Response.Content = new ByteArrayContent(responseBody); //将结果赋值给Response的Content
actionExecutedContext.Response.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("Encrypt/Bytes"); //并修改Content-Type
  通过这个方法我们将响应的Content每个Byte都做了一个异或运算,对响应内容进行了一次简单的加密,大家可以根据自己的需要进行更可靠的加密,如AES、DES或者RSA&通过这个方法可以灵活地对某个Action的处理后的结果进行处理,通过Filter进行响应内容加密有很强的灵活性和通用性,他能获取当前Action的很多信息,然后根据这些信息选择加密的方式、获取加密所需的参数等等。如果加密所使用参数对当前执行的Action没有依赖,也可以采取HttpMessageHandler来进行处理,在之后的教程中我会进行介绍。
&&& 最后一个Filter:ExceptionFilter
&&& 顾名思义,这个Filter是用来进行异常处理的,当业务发生未处理的异常,我们是不希望用户接收到黄页或者其他用户无法解析的信息的,我们可以使用ExceptionFilter来进行统一处理:
public class ExceptionFilter : ExceptionFilterAttribute
public override void OnException(HttpActionExecutedContext actionExecutedContext)
//如果截获异常为我们自定义,可以处理的异常则通过我们自己的规则处理
if (actionExecutedContext.Exception is DemoException)
//TODO:记录日志
actionExecutedContext.Response = actionExecutedContext.Request.CreateResponse(
HttpStatusCode.BadRequest, new {Message = actionExecutedContext.Exception.Message});
//如果截获异常是我没无法预料的异常,则将通用的返回信息返回给用户,避免泄露过多信息,也便于用户处理
//TODO:记录日志
actionExecutedContext.Response =
actionExecutedContext.Request.CreateResponse(HttpStatusCode.InternalServerError,
new {Message = "服务器被外星人拐跑了!"});
&&& 我们定义了一个ExceptoinFilter用于处理未捕获的异常,我们将异常分为两类:一类是我们可以预料的异常:如业务参数错误,越权等业务异常;还有一类是我们无法预料的异常:如数据库连接断开、内存溢出等异常。我们通过HTTP Code告知调用者以及用相对固定、友好的数据结构将异常信息告诉调用者,以便于调用者记录并处理这样的异常。
[CustomerExceptionFilter]
public class TestController : ApiController
public int Get(int a, int b)
if (a & b)
throw new DemoException("A必须要比B大!");
if (a == b)
throw new NotImplementedException();
return a*b;
&&& 我们定义了一个Action:在不同的情况下会抛出不同的异常,其中一个异常是我们能够预料并认为是调用者传参出错的,一个是不能够处理的,我们看一下结果:
&&& 在这样的RestApi中,我们可以预先定义好异常的表现形式,让调用者可以方便地判断什么情况下是出现异常了,然后通过较为统一的异常信息返回方式让调用者方便地解析异常信息,形成统一方便的异常消息处理机制。
&&& 但是,ExceptionFilter只能在成功完成了Controller的初始化以后才能起到捕获、处理异常的作用,而在Controller初始化完成之前(例如在Controller的构造函数中出现了异常)则ExceptionFilter无能为力。对此WebApi引入了ExceptionLogger和ExceptionHandler处理机制,我们将在之后的文章中进行讲解。
二、Filter的执行顺序
&&& 在使用MVC的时候,ActionFilter提供了一个Order属性,用户可以根据这个属性控制Filter的调用顺序,而Web API却不再支持该属性。Web API的Filter有自己的一套调用顺序规则:
&&& 所有Filter根据注册位置的不同拥有三种作用域:Global、Controller、Action:
通过HttpConfiguration类实例下Filters.Add()方法注册的Filter(一般在App_Start\WebApiConfig.cs文件中的Register方法中设置)就属于Global作用域;
通过Controller上打的Attribute进行注册的Filter就属于Controller作用域;
通过Action上打的Attribute进行注册的Filter就属于Action作用域;
他们遵循了以下规则:
1、在同一作用域下,AuthorizationFilter最先执行,之后执行ActionFilter
2、对于AuthorizationFilter和ActionFilter.OnActionExcuting来说,如果一个请求的生命周期中有多个Filter的话,执行顺序都是Global-&Controller-&Action;
3、对于ActionFilter,OnActionExecuting总是先于OnActionExecuted执行;
4、对于ExceptionFilter和ActionFilter.OnActionExcuted而言执行顺序为Action-&Controller-&Global;
5、对于所有Filter来说,如果阻止了请求:即对Response进行了赋值,则后续的Filter不再执行。
关于默认情况下的Filter相关知识我们就讲这么一些,如果在文章中有任何不正确的地方或者疑问,欢迎大家为我指出。
阅读(...) 评论()资料分享(25)
之前我们控制多个filter的执行顺序是通过web.xml中控制filter的位置来控制的,放在上面的会比放在下面的先执行,如下“用户登录检查过滤器”会比“接口日志过滤器”先执行
UserLoginFilter
net.tfgzs.demo.filter.UserLoginFilter
UserLoginFilter
&&ApiLog&/&
&&net.tfgzs.demo.filter.ApiLog&/&
&&ApiLog&/&
但是当我们使用@WebFilter注解的时候发现注解里面没有提供可以控制执行顺序的参数
@WebFilter 的属性
filterName
指定过滤器的 name 属性,等价于 &filter-name&
该属性等价于 urlPatterns 属性。但是两者不应该同时使用。
urlPatterns
指定一组过滤器的 URL 匹配模式。等价于 &url-pattern& 标签。
servletNames
指定过滤器将应用于哪些 Servlet。取值是 @WebServlet 中的 name 属性的取值,或者是 web.xml 中 &servlet-name& 的取值。
dispatcherTypes
DispatcherType
指定过滤器的转发模式。具体取值包括: ASYNC、ERROR、FORWARD、INCLUDE、REQUEST。
initParams
WebInitParam[]
指定一组过滤器初始化参数,等价于 &init-param& 标签。
asyncSupported
声明过滤器是否支持异步操作模式,等价于 &async-supported& 标签。
description
该过滤器的描述信息,等价于 &description& 标签。
displayName
该过滤器的显示名,通常配合工具使用,等价于 &display-name& 标签。
通过实践发现如果想要控制filer的执行顺序可以&通过控制filter的文件名&来控制
UserLoginFilter.java 和 ApiLog.java 这两个文件里面分别是“用户登录检查过滤器”和“接口日志过滤器”,因为这两个文件的&首字母A排U之前&,导致每次执行的时候都是先执行“接口日志过滤器”再执行“用户登录检查过滤器”,所以我们现在修改两个文件的名称分别为
Filter0_UserLogin.java
Filter1_ApiLog.java
这样就能先执行“用户登录检查过滤器”再执行“接口日志过滤器”
&&相关文章推荐
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:7766次
排名:千里之外
原创:42篇
转载:13篇
(5)(15)(2)(7)(7)(5)(13)Servlet3中使用@WebFilter注解怎么指定Filter的顺序?
Servlet3中使用@WebFilter注解怎么指定Filter的顺序?
那这样的还,如果有多个Filter,它们的顺序只能在XML中配置了吧
写下你的评论...
写下你的评论...
Copyright (C)
All Rights Reserved | 京ICP备 号-2

我要回帖

更多关于 servlet webfilter 的文章

 

随机推荐