昨天我在项目中加入了token验证,我想在所有修改数据库的ajax请求后增加token的更新操作.
开始我想通过SpringMVC的拦截器在controller方法调用结束后统一进行token的更改,但是并不成功.
查阅资料后发现了ControllerAdvice,它是在spring4.0后出现的.
它可以在controller的方法在用@ResponseBody把返回值转换为json对象之前捕捉到返回的对象,以便我们在它内置的方法中去进行统一的更新操作.
但是ControllerAdvice没有办法选择要过滤的对象,也就是说他会过滤项目中所有的controller返回值
使用方法:
加入@ControllerAdvice和@Controller注解(也可以使用配置文件)
实现ResponseBodyAdvice<Object>接口
@Component
@ControllerAdvice
//controller增强器,修改respondbody中的值,更新token
public class tokenControllerAdvice implements ResponseBodyAdvice<Object>{
@Override
public boolean supports(MethodParameter arg0, Class<? extends HttpMessageConverter<?>> arg1) {
// 只有返回true才会进行下面方法
return true;
}
//对返回值进行拦截,更新token
@Override
public Object beforeBodyWrite(Object body, MethodParameter arg1, MediaType arg2,
Class<? extends HttpMessageConverter<?>> arg3, ServerHttpRequest serverRequest, ServerHttpResponse serverResponse) {
responseBean bean = (responseBean) body;
//判断是否需要token更新
if(bean.getToken() != null && bean.getToken().equals("need")) {
//强转为HttpServletRequest
ServletServerHttpRequest ssRequest = (ServletServerHttpRequest)serverRequest;
HttpServletRequest request = ssRequest.getServletRequest();
//更新token
tokenUtils.createToken(request, "token");
bean.setToken(request.getSession().getAttribute("token"));
}
return body;
}
}
首先必须让supports方法返回true值才能进到beforeBodyWrite方法对返回值进行处理,我这里是把需要做token更新的返回值加上了一个标记(通过bean.getToken()获取),如果这个标记存在就做更新token操作.
操作时如果需要使用request和response就需要进行转换,因为这里的serverHttpRequest和serverHttpResponse与我们使用的HttpServletRequest并不一样.然后第一个参数body就是controller的返回值,此时他还没有被处理为json格式的数据,所以我们可以直接进行强转使用.之后把增强后的body返回就ok了.