Restful API的拦截:

  1,过滤器(Filter)

  2,拦截器(Interceptor)

  3,切片(Aspect)

1,过滤器

和传统javaweb一鸟样,例,记录controller执行时间过滤器,会过滤所有url:

/**
* 记录执行时间过滤器
* ClassName: TimeFilter
* @Description: TODO
* @author lihaoyang
* @date 2018年2月26日
*/
@Component //声明为spring组件,springboot项目没有web.xml直接声明为组件
public class TimeFilter implements Filter { @Override
public void destroy() {
System.err.println("time filter destory...");
} @Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.err.println("time filter start");
long startTime = new Date().getTime();
chain.doFilter(request, response); //执行其他过滤器链
System.err.println("time filter 耗时:"+(new Date().getTime()-startTime));
System.err.println("time filter end");
} @Override
public void init(FilterConfig arg0) throws ServletException {
System.err.println("time filter init...");
} }

在传统javaweb我们需要在web.xml配置过滤器,springboot没有web.xml,只需要在类上加上@Component注解告诉spring这是一个组件即可。如果我们需要引入第三方的一些过滤器,是没办法加注解的,此时就需要使用java来代替配置文件了:

假设自定义的TimeFilter即为第三方Filter,注释掉@Component注解

只需加上一个配置类,相当于xml配置即可:

package com.imooc.web.config;

import java.util.ArrayList;
import java.util.List; import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import com.imooc.web.filter.TimeFilter; @Configuration
public class WebConfig { @Bean
public FilterRegistrationBean timeFilter(){
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(); TimeFilter timeFilter = new TimeFilter();
filterRegistrationBean.setFilter(timeFilter);
//指定要过滤的url
List<String> urls = new ArrayList<>();
urls.add("/*");
filterRegistrationBean.setUrlPatterns(urls);
return filterRegistrationBean;
}
}

filter只能对request和response进行操作,因为他是J2EE的规范,所以这个请求最终是哪一个controller的哪个方法来处理的是不知道的。因为controller是spring的概念。如果需要知道这些信息,就需要用拦截器。

2,拦截器

自定义拦截器,加上@Component 声明为spring组件,记录调用耗时:

package com.imooc.web.interceptor;

import java.util.Date;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView; /**
* 记录调用耗时的拦截器
* ClassName: TimeInterceptor
* @Description: TODO
* @author lihaoyang
* @date 2018年2月26日
*/
@Component //声明为spring组件
public class TimeInterceptor implements HandlerInterceptor{ //进入controller之前执行
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.err.println("preHandle..."); System.err.println(((HandlerMethod)handler).getBean().getClass().getName());//哪个类
System.err.println(((HandlerMethod)handler).getMethod()); //哪个方法
request.setAttribute("startTime", new Date().getTime());//调用开始计时
return true;
} //进入controller之中执行
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
throws Exception {
System.err.println("postHandle...");
Long start = (Long) request.getAttribute("startTime");
System.err.println("time interceptor 耗时:"+(new Date().getTime()-start));
} //controller执行完之后执行
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception { System.err.println("afterCompletion...");
Long start = (Long) request.getAttribute("startTime");
System.err.println("time interceptor 耗时:"+(new Date().getTime()-start));
//如果调用有异常,这个Exception会有信息
System.err.println("exception:"+ex);
} }

java配置,继承WebMvcConfigurerAdapter类重写addInterceptors方法,定义自己的拦截器

package com.imooc.web.config;

import java.util.ArrayList;
import java.util.List; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; import com.imooc.web.filter.TimeFilter;
import com.imooc.web.interceptor.TimeInterceptor; @Configuration
public class WebConfig extends WebMvcConfigurerAdapter{ //由于TimeInterceptor声明为了spring组件,直接注入进来
@Autowired
private TimeInterceptor timeInterceptor;
/**
* 实现WebMvcConfigurerAdapter,重写addInterceptors方法添加拦截器
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(timeInterceptor);
} @Bean
public FilterRegistrationBean timeFilter(){
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(); TimeFilter timeFilter = new TimeFilter();
filterRegistrationBean.setFilter(timeFilter);
//指定要过滤的url
List<String> urls = new ArrayList<>();
urls.add("/*");
filterRegistrationBean.setUrlPatterns(urls);
return filterRegistrationBean;
}
}

调用http://localhost:8080/user/1

可以看到能获取到所调用的Controller以及哪个方法:

time filter start
preHandle...
com.imooc.web.controller.UserController
public com.imooc.dto.User com.imooc.web.controller.UserController.getInfo(java.lang.String)
afterCompletion...
time interceptor 耗时:34
exception:null
time filter 耗时:50
time filter end
time filter start
time filter 耗时:15
time filter end

注意,如果是抛出了自定义异常,做过了处理,afterCompletion里就不会打印异常信息了。

拦截器能获取到所要处理的控制器类和方法,但是没办法获取到具体要处理的参数,查看DispatcherServlet源码的doDispatch方法就可以看到,执行拦截器的时候,还没有组装参数,把请求的参数映射成为contrller里的参数,所以取不到具体的参数值,如果想获取参数值,就需要用到第三个拦截机制spring的AOP,自定义切面

3,切片

TimeAspect切面类:

package com.imooc.web.aspect;

import java.util.Date;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component; /**
* 调用耗时切片
* ClassName: TimeAspect
* @Description: TODO
* @author lihaoyang
* @date 2018年2月26日
*/
@Aspect
@Component
public class TimeAspect { /**
*
*/
@Around("execution(* com.imooc.web.controller.UserController.*(..))")
public Object handleControllerMethod(ProceedingJoinPoint pjp) throws Throwable{
System.err.println(">>>> 进入 TimeAspect start >>>>>"); Object[] args = pjp.getArgs();
if(args.length > 0){
for (Object arg : args) {
System.err.println("arg is "+arg);
}
}
long start = new Date().getTime(); Object object = pjp.proceed();
System.err.println("TimeAspect 调用耗时:"+(new Date().getTime()-start));
System.err.println(">>>> TimeAspect 结束 >>>>>"); return object;
}
}

访问:http://localhost:8080/user/1可以看到能够取到参数1

=======time filter start======
++++++ 进入 preHandle...+++++++
com.imooc.web.controller.UserController$$EnhancerBySpringCGLIB$$533f819c
public com.imooc.dto.User com.imooc.web.controller.UserController.getInfo(java.lang.String)
>>>> 进入 TimeAspect start >>>>>
arg is 1
>>>>>>进入User Controller --> getInfo 方法
1
TimeAspect 调用耗时:0
>>>> TimeAspect 结束 >>>>>
postHandle...
time interceptor 耗时:1
time interceptor 耗时:1
exception:null
+++++ afterCompletion +++++++
time filter 耗时:5
=======time filter end=======
=======time filter start======
time filter 耗时:2
=======time filter end=======

三者调用顺序:

代码github:https://github.com/lhy1234/spring-security

Spring Security构建Rest服务-0400-使用切片拦截rest服务的更多相关文章

  1. Spring Boot中使用 Spring Security 构建权限系统

    Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架.它提供了一组可以在Spring应用上下文中配置的Bean,为应用系统提供声明式的安全 ...

  2. Spring Security构建Rest服务-1300-Spring Security OAuth开发APP认证框架之JWT实现单点登录

    基于JWT实现SSO 在淘宝( https://www.taobao.com )上点击登录,已经跳到了 https://login.taobao.com,这是又一个服务器.只要在淘宝登录了,就能直接访 ...

  3. Spring Security构建Rest服务-1202-Spring Security OAuth开发APP认证框架之重构3种登录方式

    SpringSecurityOAuth核心源码解析 蓝色表示接口,绿色表示类 1,TokenEndpoint 整个入口点,相当于一个controller,不同的授权模式获取token的地址都是 /oa ...

  4. Spring Security构建Rest服务-1001-spring social开发第三方登录之spring social基本原理

    OAuth协议是一个授权协议,目的是让用户在不将服务提供商的用户名密码交给第三方应用的条件下,让第三方应用可以有权限访问用户存在服务提供商上的资源. 接着上一篇说的,在第三方应用获取到用户资源后,如果 ...

  5. Spring Security构建Rest服务-1201-Spring Security OAuth开发APP认证框架之实现服务提供商

    实现服务提供商,就是要实现认证服务器.资源服务器. 现在做的都是app的东西,所以在app项目写代码  认证服务器: 新建 ImoocAuthenticationServerConfig 类,@Ena ...

  6. Spring Security构建Rest服务-1200-SpringSecurity OAuth开发APP认证框架

    基于服务器Session的认证方式: 前边说的用户名密码登录.短信登录.第三方登录,都是普通的登录,是基于服务器Session保存用户信息的登录方式.登录信息都是存在服务器的session(服务器的一 ...

  7. Spring Security构建Rest服务-0900-rememberMe记住我

    Spring security记住我基本原理: 登录的时候,请求发送给过滤器UsernamePasswordAuthenticationFilter,当该过滤器认证成功后,会调用RememberMeS ...

  8. Spring Security构建Rest服务-1401-权限表达式

    Spring Security 的权限表达式 用法,在自定义的BrowserSecurityConfig extends WebSecurityConfigurerAdapter 配置文件里,每一个a ...

  9. Spring Security构建Rest服务-1205-Spring Security OAuth开发APP认证框架之Token处理

    token处理之二使用JWT替换默认的token JWT(Json Web Token) 特点: 1,自包含:jwt token包含有意义的信息 spring security oauth默认生成的t ...

随机推荐

  1. Swift1.2与Xcode6.3 beta

    Xcode6.3和Swift1.2都已经发布.这次发布增强了Swift编译器也给Swift增加了一些新的特性.详细内容可以看这里.这里主要关注比较重要的内容. 编译器的改进 Swift1.2的编译器更 ...

  2. 解决Error creating bean with name 'huayuanjingguanDaoimp' defined in file [D:\apache-tomcat-7.0.52\webapps\landscapings\WEB-INF\classes\com\itheima\landscaping\dao\imp\huayuanjingguanDaoimp.class]: Invo

    问题描述: 10:23:13,585 ERROR ContextLoader:307 - Context initialization failedorg.springframework.beans. ...

  3. Asp.net mvc验证用户登录之Forms实现

    这里我们采用asp.net mvc 自带的AuthorizeAttribute过滤器验证用户的身份,也可以使用自定义过滤器,步骤都是一样. 第一步:创建asp.net mvc项目, 在项目的App_S ...

  4. nodejs 获取文件的编码方式

    使用nodejs获取文件夹内文件的编码方式:使用jschardet模块. 下面的代码还有问题,没有添加结束的语句,没有判断应该在哪执行res.send(). res.send()不能放在forEach ...

  5. springmvc 开涛 拦截器

    拦截器有三个方法:preHandle, postHandle, afterCompletion ***-servlet.xml <bean name="/test" clas ...

  6. ACL登陆认证

    前篇文章ACL授权实例介绍了授权,授权完成之后,就要进行认证.ACL的认证主要分为登陆认证与即时认证.所谓登录认证就是在用户登陆的时候,进行信息认证.根据用户Id,加载上来该用户所拥有的权限模块:而即 ...

  7. Toad 实现 SQL 优化

    It is very easy for us to implement sql tuning by toad.  We need to do is just give complex sql stat ...

  8. ajax方式上传图片到Django后台

    参考价值最大 https://blog.csdn.net/huangql517/article/details/81259671 https://www.cnblogs.com/chenjianhon ...

  9. ASP.NET Web API 2.0 统一响应格式

    传统实现 在搭建 Web API 服务的时候,针对客户端请求,我们一般都会自定义响应的 JSON 格式,比如: { "Data" : { "Id" : 100, ...

  10. 详解webpack + vue + node 打造单页面(入门篇)

    1.node下载地址:http://nodejs.cn/download/,安装完成检查node和npm版本 2.淘宝镜像 : npm install cnpm -g --registry=https ...