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 2138 How many prime numbers (判素数,米勒拉宾算法)

    题意:给定一个数,判断是不是素数. 析:由于数太多,并且太大了,所以以前的方法都不适合,要用米勒拉宾算法. 代码如下: #include <iostream> #include <c ...

  2. ansible-playbook api 2.0 直接运行

    官方文档见  http://docs.ansible.com/ansible/dev_guide/developing_api.html 拿官方的例子修改如下 import json from col ...

  3. Windows10+Python3+BeautifulSoup4 安装

    用正则表达式来提取网页中的内容是相当麻烦的,这里介绍一个可以从HTML或XML文件中提取数据的Python库:Beautiful Soup.它能够通过你喜欢的转换器实现惯用的文档导航,查找,修改文档的 ...

  4. java学习之路-分享笔记20150327

    ---恢复内容开始--- 2个月间,断断续续学习了一段时间java平台相关知识,慢慢梳理出来一些枝枝叶叶,和大家交流下.3年前用java边看边做写了一个项目,所以对语法不是很关注.需要原文档的留邮箱吧 ...

  5. LINUX中关于SIGNAL的定义

    /* Signals. */ #define SIGHUP 1 /* Hangup (POSIX). */ #define SIGINT 2 /* Interrupt (ANSI). */ #defi ...

  6. delphi执行一个外部程序,当外部程序结束后,delphi程序立即响应

    //需要引用 ShellAPI 单元;procedure TForm1.Button1Click(Sender: TObject); var SEInfo: TShellExecuteInfo; Ex ...

  7. [leetcode] 19. Count and Say

    这个还是一开始没读懂题目,题目如下: The count-and-say sequence is the sequence of integers beginning as follows: 1, 1 ...

  8. Android-Java-IO流概述

    IO:I:Input输入 O:Output输出 IO流: IO:用于处理设备上数据的一种技术,处理设备上数据包括(Input / Output) ,设备指的是:内存,硬盘,U盘,打印机,等等..... ...

  9. Xamarin.Forms第三方XAML预览工具-LiveXAML简单体验

    截至目前,Xamarin官方的Xaml Previewer工具仍然处于测试阶段,使用中也发现了各种不便,例如各种莫名其妙的渲染失败,或者提示需要编译项目才能渲染等等,复杂项目基本不可用, 完全没有体现 ...

  10. Linux(Debian)网卡设置

    debian IP地址配置 vim /etc/network/interface   配置网卡eth0的IP地址 auto eth0 表示网卡随系统自动请 iface eth0 inet static ...