Spring Security开发安全的REST服务-学习笔记(3.7-3.10)
2019-03-20 14:25
676 查看
Spring Security开发安全的REST服务-学习笔记(3.7-3.10)
欢迎
本篇博文仅记录该学习过程。
3.7使用切片拦截REST服务
Spring的切面拦截方式(Filter,Interceptor,AspectJ)
测试url请求的controller方法
package com.lwj.securitydemo.controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; @RestController public class UserController { @GetMapping("/hello/{id}") public String hello(@PathVariable int id) { return "hello"; } }
1.Filter的方式
(1)在Springboot项目中通过@Component注解的方式添加一个过滤器来拦截URL请求。
package com.lwj.securitydemo.filter; import javax.servlet.*; import java.io.IOException; import java.util.Date; //将TimeFilter添加到Spring容器中 @Component public class TimeFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { System.out.println("TimeFilter init"); } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("TimeFilter doFilter"); System.out.println("start do something..." + new Date()); filterChain.doFilter(servletRequest, servletResponse); System.out.println("something is done" + new Date()); } @Override public void destroy() { System.out.println("TimeFilter destroy"); } }
(2)使用Springboot的config配置的方式
新建WebConfig类,并添加@Configuration注解,将该类配置为一个配置类。
package com.lwj.securitydemo.config; import com.lwj.securitydemo.TimeFilter; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.ArrayList; import java.util.List; @Configuration public class WebConfig { /** * 配置过滤器 * @return */ @Bean public FilterRegistrationBean timeFilter() { FilterRegistrationBean registrationBean = new FilterRegistrationBean(); // new一個自定義的filter出來 TimeFilter timeFilter = new TimeFilter(); // 將自定義的filter放入到registrationBean registrationBean.setFilter(timeFilter); // 設置需要被攔截的親求類型 List<String> filterUrls = new ArrayList<>(); filterUrls.add("/*"); registrationBean.setUrlPatterns(filterUrls); return registrationBean; } }
2.Interceptor的方式
(1)创建TimeInterceptor类
package com.lwj.securitydemo.interceptor; import org.springframework.stereotype.Component; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.Map; @Component public class TimeInterceptor extends HandlerInterceptorAdapter { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("preHandle"); Map map = request.getParameterMap(); System.out.println(handler.getClass().getName()); System.out.println("param "+ map.toString()); return true; } /** * 该方法如果调用的方法抛出异常就不会再被调用了 */ @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("postHandle"); } /** * 该方法最终都会执行 */ @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("afterCompletion"); } }
PS:此处的handler中虽然不能获取到请求中的参数,但是通过request对象中的方法也可以获取到param参数!
(2)将自定义的Interceptor添加到配置中
@Configuration public class WebConfig implements WebMvcConfigurer { /** * 注入自定义的TimeInterceptor */ @Autowired private TimeInterceptor timeInterceptor; /** * 配置自定义的Interceptor * @param registry */ @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(timeInterceptor); } /** * 配置过滤器 * @return */ @Bean public FilterRegistrationBean timeFilter() { FilterRegistrationBean registrationBean = new FilterRegistrationBean(); // new一個自定義的filter出來 TimeFilter timeFilter = new TimeFilter(); // 將自定義的filter放入到registrationBean registrationBean.setFilter(timeFilter); // 設置需要被攔截的親求類型 List<String> filterUrls = new ArrayList<>(); filterUrls.add("/*"); registrationBean.setUrlPatterns(filterUrls); return registrationBean; } }
AspectJ方式
Aspect方式代码
package com.lwj.securitydemo.web.aspect; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.springframework.stereotype.Component; @Aspect @Component public class TimeAspect { @Around("execution(* com.lwj.securitydemo.controller.UserController.*(..))") public Object handleControllerMethod(ProceedingJoinPoint pjp) throws Throwable { System.out.println("time aspect 方法被调用!"); long start = System.currentTimeMillis(); // 获取切片方法的参数 Object[] args = pjp.getArgs(); for (Object arg : args) { System.out.println("args : " + arg); } // 执行切片的方法 Object obj = pjp.proceed(); System.out.println("time aspect 耗时: " + (System.currentTimeMillis() - start)); System.out.println("time aspect 方法结束!"); return obj; } }
REST API 拦截
3.9 异步处理REST服务
使用Runable异步处理Rest服务
package com.lwj.securitydemo.web.async; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.concurrent.Callable; @RestController public class AsyncController { private Logger logger = LoggerFactory.getLogger(getClass()); @RequestMapping("/order") public Callable<String> order() { logger.info("主线程开始!"); Callable<String> result = () -> { logger.info("副线程开始!"); Thread.sleep(1000); logger.info("副线程结束!"); return "success"; }; logger.info("主线程结束!"); return result; } }
param org.apache.catalina.util.ParameterMap@16e52a1 2019-03-20 11:47:36.206 INFO 15556 --- [nio-8080-exec-1] c.l.s.web.async.AsyncController : 主线程开始! 2019-03-20 11:47:36.207 INFO 15556 --- [nio-8080-exec-1] c.l.s.web.async.AsyncController : 主线程结束! 2019-03-20 11:47:36.215 INFO 15556 --- [ task-1] c.l.s.web.async.AsyncController : 副线程开始! 2019-03-20 11:47:37.216 INFO 15556 --- [ task-1] c.l.s.web.async.AsyncController : 副线程结束!
可以看到日志信息中,在主线程结束后副线程立马开始了
使用DeferredResult异步处理Rest服务
1.创建MockQueue
package com.lwj.securitydemo.web.async; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; @Component public class MockQueue { private Logger logger = LoggerFactory.getLogger(getClass()); private String placeOrder; private String completeOrder; public String getPlaceOrder() { return placeOrder; } public void setPlaceOrder(String placeOrder) throws Exception { new Thread(() -> { logger.info("接到下单请求:" + placeOrder); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } this.completeOrder = placeOrder; logger.info("下单请求处理完毕:" + placeOrder); }).start(); } public String getCompleteOrder() { return completeOrder; } public void setCompleteOrder(String completeOrder) { this.completeOrder = completeOrder; } }
2.创建DeferredResultHolder类
package com.lwj.securitydemo.web.async; import org.springframework.stereotype.Component; import org.springframework.web.context.request.async.DeferredResult; import java.util.HashMap; import java.util.Map; @Component public class DeferredResultHolder { private Map<String, DeferredResult<String>> map = new HashMap<>(); public Map<String, DeferredResult<String>> getMap() { return map; } public void setMap(Map<String, DeferredResult<String>> map) { this.map = map; } }
3.创建QueueListener
package com.lwj.securitydemo.web.async; import cn.hutool.core.util.StrUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationListener; import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.stereotype.Component; /** * ContextRefreshedEvent 為spring容器初始化完畢事件 */ @Component public class QueueListener implements ApplicationListener<ContextRefreshedEvent> { private Logger logger = LoggerFactory.getLogger(getClass()); @Autowired private MockQueue mockQueue; @Autowired private DeferredResultHolder deferredResultHolder; @Override public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) { new Thread(()->{ while (true) { if (StrUtil.isNotBlank(mockQueue.getCompleteOrder())) { String orderNumber = mockQueue.getCompleteOrder(); logger.info("返回订单处理结果:" + orderNumber); deferredResultHolder.getMap().get(orderNumber).setResult("place order success"); mockQueue.setCompleteOrder(null); } else { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); } }
4.修改AsyncController中的方法
package com.lwj.securitydemo.web.async; import cn.hutool.core.util.RandomUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.context.request.async.DeferredResult; import java.util.concurrent.Callable; @RestController public class AsyncController { private Logger logger = LoggerFactory.getLogger(getClass()); @Autowired private MockQueue mockQueue; @Autowired private DeferredResultHolder deferredResultHolder; @RequestMapping("/order") public DeferredResult<String> order() throws Exception { logger.info("主线程开始!"); String orderNumber = RandomUtil.randomNumbers(8); mockQueue.setPlaceOrder(orderNumber); DeferredResult<String> result = new DeferredResult<>(); deferredResultHolder.getMap().put(orderNumber, result); // Callable<String> result = () -> { // logger.info("副线程开始!"); // Thread.sleep(1000); // logger.info("副线程结束!"); // return "success"; // }; logger.info("主线程结束!"); return result; } }
console日志
2019-03-20 14:21:12.700 INFO 6508 --- [nio-8080-exec-1] c.l.s.web.async.AsyncController : 主线程开始! 2019-03-20 14:21:12.701 INFO 6508 --- [nio-8080-exec-1] c.l.s.web.async.AsyncController : 主线程结束! 2019-03-20 14:21:12.701 INFO 6508 --- [ Thread-10] c.lwj.securitydemo.web.async.MockQueue : 接到下单请求:89428880 2019-03-20 14:21:13.702 INFO 6508 --- [ Thread-10] c.lwj.securitydemo.web.async.MockQueue : 下单请求处理完毕:89428880 2019-03-20 14:21:13.703 INFO 6508 --- [ Thread-7] c.l.s.web.async.QueueListener : 返回订单处理结果:89428880
异步处理配置
相关文章推荐
- Spring Security开发安全的REST服务-学习笔记(3.11-3.12)
- Spring Security开发安全的REST服务-学习笔记(4)
- Spring Security开发安全的REST服务 大神带你学习后端安全开发实战课程
- Spring Security开发安全的REST服务 大神带你学习后端安全开发实战分享
- 2018Spring Security开发安全的REST服务(全套八章)
- Spring Security开发安全的REST服务
- 求资源 慕课哪位大神有《Spring Security开发安全的REST服务》求分享
- Beginning Spring学习笔记——第11章 使用Spring开发REST风格的Web服务
- Spring Security开发安全的REST服务
- Spring Security开发安全的REST服务之项目搭建
- 最新Spring Security开发安全的REST服务
- Rest API 开发 学习笔记
- Rest API 开发 学习笔记
- 删除自定义服务 寒江孤钓<<windows 内核安全编程>> 学习笔记
- Rest API 开发 学习笔记
- SMP3.0学习笔记之十九 使用REST API在任何操作系统上消费SMP的OData服务
- Rest API 开发 学习笔记
- 【安全牛学习笔记】拒绝服务攻击工具-NMAP、匿名者拒绝服务工具包(匿名者发布的DoS工具)、其他拒绝服务工具-XOIC、HULK、DDOSIM、GoldenEye
- Rest API 开发 学习笔记
- Dynamic CRM 2015学习笔记(4)修改开发人员资源(发现服务、组织服务和组织数据服务)url地址及组织名