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. js正则表达式汇集

    1.只允许中文.字母.数字.中划线.下划线.空格.中文的().英文的()和#,只能以数字.中文.字母.下划线开头,长度为2至40之间 validateTemplateName: function(va ...

  2. HDU 2058 The sum problem (数学+暴力)

    题意:给定一个N和M,N表示从1到N的连续序列,让你求在1到N这个序列中连续子序列的和为M的子序列区间. 析:很明显最直接的方法就是暴力,可是不幸的是,由于N,M太大了,肯定会TLE的.所以我们就想能 ...

  3. qq强制聊天工具

    当你想和别人聊天, 别人有不理你的时候可以用上哦!!!特别是情人吵架的时候, 呵呵 复制下面的代码: @echo off title DIY-QQ强制聊天工具color 0a echo. echo.  ...

  4. Android draw Rect 坐标图示

    前两天在博客发了在例子 android Canvas类介绍 http://byandby.javaeye.com/blog/825330 建议大家 点进去 看一看 不然下边没办法 继续啊. 我还是把这 ...

  5. day4之内置函数、匿名函数,递归函数

    内置函数: https://www.processon.com/view/link/5adc6062e4b04721d63171eb?pw=3218 匿名函数:lambda lambda 语法: la ...

  6. Java设计模式 -- 简单工厂模式(SimpleFactory)

    一.什么是简单工厂模式 简单工厂模式属于类的创建型模式,又叫做静态工厂方法模式.通过专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类. 二.模式中包含的角色及其职责 1.工厂(C ...

  7. Android sdcard文件读写操作

    这次演示以,安卓原生操作系统 Nexus_6手机进行操作: AndroidManifest.xml配置相关权限: <!-- 增加权限 --> <uses-permission and ...

  8. List<T>用法

    所属命名空间:System.Collections.Generic public class List<T> : IList<T>, ICollection<T>, ...

  9. Winform打包安装程序覆盖安装的实现

    1.修改项目程序集版本号. 2.设置Version,使当前版本号大于前一个版本号. 3.RemovePreviousVersions属性设置为true. 以上三步后,生成安装程序即可实现覆盖安装. P ...

  10. Day5 作业(完成)

    1,有如下变量(tu是个元祖),请实现要求的功能# tu = ("alex", [11, 22, {"k1": 'v1', "k2": [& ...