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. HDU 3177 Crixalis's Equipment (贪心,差值)

    题意:判断 n 件物品是否可以搬进洞里,每件物品有实际体积A和移动时的额外体积 B . 析:第一反应就是贪心,一想是不是按B从大到小,然后一想,不对,比如体积是20,第一个 是A=11, B=19.第 ...

  2. python 取整itertools

    #coding:utf-8 import sys import itertools def MaxString(n,nums): list1 = nums list2 = [] for i in ra ...

  3. 15) maven dependency scope

    Dependency Scope Dependency scope is used to limit the transitivity of a dependency, and also to aff ...

  4. Linux常见配置文件

    一./etc 配置文件 /etc/passwd 用户数据库,其中的域给出了用户名.真实姓名.家目录.加密口令和用户的其他信息 /etc/group 类似/etc/passwd ,但说明的不是用户而是组 ...

  5. (线段树)Just a Hook -- hdu -- 1689

    链接: http://acm.hdu.edu.cn/showproblem.php?pid=1698 思路: 我的想法很简单,像上一题一样从后面向前面来算,前面已经覆盖的,后面自然不能再来计算了,具体 ...

  6. oracl中的大数据类型clob

    建表 create table test_name( test_id   number(6) not null, img_data clob ); 在java中该表所对应的po为: class Tes ...

  7. gridview的编辑,更新,取消,自动分页等

    gridview编辑列,把左下角的"自动生成字段"的复选框的勾去掉 添加boundfield(绑定列)将其datafield设置为productname,headertext设置为 ...

  8. TCP/IP模型的一个简单解释

    TCP/IP模型是互联网的基础. 想要理解互联网,就必须理解这个模型.但是,它不好懂,我就从来没有搞懂过. 前几天,BetterExplained上有一篇文章,很通俗地解释了这个模型.我读后有一种恍然 ...

  9. java web前端easyui(layout+tree+双tabs)布局+树+2个选项卡tabs

    1.列出要实现的样式: 2.实现的代码: 分三大部分: 1):页面主体部分:mian.vm <html> <head> <title>Ks UI</title ...

  10. Eclipse 4.2 failed to start after TEE is installed

    ---------------  VM Arguments---------------  jvm_args: -Dosgi.requiredJavaVersion=1.6 -Dhelp.lucene ...