您的位置:首页 > 编程语言 > Java开发

Spring Security开发安全的REST服务-学习笔记(3.7-3.10)

2019-03-20 14:25 676 查看

Spring Security开发安全的REST服务-学习笔记(3.7-3.10)

  • REST API 拦截
  • 3.9 异步处理REST服务
  • 欢迎

    本篇博文仅记录该学习过程。

    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

    异步处理配置

    内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
    标签: