Spring Security构建Rest服务-0400-使用切片拦截rest服务
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服务的更多相关文章
- Spring Boot中使用 Spring Security 构建权限系统
Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架.它提供了一组可以在Spring应用上下文中配置的Bean,为应用系统提供声明式的安全 ...
- Spring Security构建Rest服务-1300-Spring Security OAuth开发APP认证框架之JWT实现单点登录
基于JWT实现SSO 在淘宝( https://www.taobao.com )上点击登录,已经跳到了 https://login.taobao.com,这是又一个服务器.只要在淘宝登录了,就能直接访 ...
- Spring Security构建Rest服务-1202-Spring Security OAuth开发APP认证框架之重构3种登录方式
SpringSecurityOAuth核心源码解析 蓝色表示接口,绿色表示类 1,TokenEndpoint 整个入口点,相当于一个controller,不同的授权模式获取token的地址都是 /oa ...
- Spring Security构建Rest服务-1001-spring social开发第三方登录之spring social基本原理
OAuth协议是一个授权协议,目的是让用户在不将服务提供商的用户名密码交给第三方应用的条件下,让第三方应用可以有权限访问用户存在服务提供商上的资源. 接着上一篇说的,在第三方应用获取到用户资源后,如果 ...
- Spring Security构建Rest服务-1201-Spring Security OAuth开发APP认证框架之实现服务提供商
实现服务提供商,就是要实现认证服务器.资源服务器. 现在做的都是app的东西,所以在app项目写代码 认证服务器: 新建 ImoocAuthenticationServerConfig 类,@Ena ...
- Spring Security构建Rest服务-1200-SpringSecurity OAuth开发APP认证框架
基于服务器Session的认证方式: 前边说的用户名密码登录.短信登录.第三方登录,都是普通的登录,是基于服务器Session保存用户信息的登录方式.登录信息都是存在服务器的session(服务器的一 ...
- Spring Security构建Rest服务-0900-rememberMe记住我
Spring security记住我基本原理: 登录的时候,请求发送给过滤器UsernamePasswordAuthenticationFilter,当该过滤器认证成功后,会调用RememberMeS ...
- Spring Security构建Rest服务-1401-权限表达式
Spring Security 的权限表达式 用法,在自定义的BrowserSecurityConfig extends WebSecurityConfigurerAdapter 配置文件里,每一个a ...
- Spring Security构建Rest服务-1205-Spring Security OAuth开发APP认证框架之Token处理
token处理之二使用JWT替换默认的token JWT(Json Web Token) 特点: 1,自包含:jwt token包含有意义的信息 spring security oauth默认生成的t ...
随机推荐
- MySQL性能调优与架构设计——第 16 章 MySQL Cluster
第 16 章 MySQL Cluster 前言: MySQL Cluster 是一个基于 NDB Cluster 存储引擎的完整的分布式数据库系统.不仅仅具有高可用性,而且可以自动切分数据,冗余数据等 ...
- Android Sqlite 增删改查
模拟 查询所有数据,增加一条数据,修改某一条数据,删除某一条数据: SQLiteOpenHelper 帮助类的介绍: import android.content.Context; import an ...
- 自适应XAML布局经验总结 (三) 局部布局设计模式2
本系列对实际项目中的XAML布局场景进行总结,给出了较优化的自适应布局解决方案,希望对大家有所帮助. 下面继续介绍局部布局设计模式. 5. 工具箱模式 绘图,三维模型操作等需要工具的情况,可以使用带分 ...
- Kafka send问题
kafka 在send之后不会立即把消息发送到broker.会把消息发到producer所在电脑内存里,后端的IOThread会扫描内存,并从中取出消息进行消费. 在调用close()或者flush( ...
- Xml 序列化和反序列化
xml序列化帮助类 using System.IO; using System.Xml; using System.Xml.Serialization; public class XmlHelper ...
- vs2017 修改项目名称
由于经常接到各种项目需求, 又不想重新搭建框架. 于是便想到直接修改项目名. 话不多说, 上图~ 1 重命名 解决方案 和 项目名称 2 重命名项目的应用程序名和命名空间 3 Ctrl+F 将旧的工 ...
- C# AutoMapper 了解一下
什么是AutoMapper? 简单来说就是将一个对象映射到另一个对象的代码. 摆脱了繁琐的赋值过程 (最常见也就是Model -——ViewModel) AutoMapper安装 我使用的是VS201 ...
- 【cocos2d-x 手游研发----地图活起来了】
谈到地图不少人都说要做地图编辑器了,但是我暂时绕过这一步,如果不用寻路地图就不能移动?寻路就是会绕过障碍物的算法. 我做了一个简单的地图的思想,就是地图分层3层:背景层.可行区域层.遮罩层,但是地图就 ...
- 高性能mysql学习笔记
此文已由作者朱笑天授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 笔者在工作之余阅读了一下高性能mysql,以下的内容对mysql的介绍以及书中涉及一些概念的总结归纳. 1. ...
- ko内核模块文件以及载入模块命令modprobe insmod
原文链接:https://blog.csdn.net/evenness/article/details/7655921?utm_source=blogxgwz5 modprobe: Load modu ...