互联网架构-SpringMVC源码深度解析-028:拦截器&过滤器&视图层&异步源码分析

1 SpringMVC注解方式开启视图层

课程内容:
1.SpringMVC注解形式启动整合视图层
2.SpringMVC拦截器底层源码分析
3.SpringMVC异步处理有那些方式
4.使用Callable实现Http请求异步处理

SpringMVC注解形式启动整合视图层

@Configuration
@ComponentScan("com.mayikt.controller")
@EnableWebMvc
public class SpringMvcConfig {
    // @EnableWebMvc 等同于开启springmvc注解方式
    // @Configuration 替代xml
    // @ComponentScan 替代扫包范围
    // DispatcherServlet

    @Bean
    public InternalResourceViewResolver internalResourceViewResolver() {
        InternalResourceViewResolver internalResourceViewResolver = new InternalResourceViewResolver();
        internalResourceViewResolver.setPrefix("/WEB-INF/view/");
        internalResourceViewResolver.setSuffix(".jsp");
        return internalResourceViewResolver;
    }
}
@Controller
public class IndexController {

    @RequestMapping(value = "/pageIndex")
    public String pageIndex() {
        return "pageIndex";
    }
}

pageIndex.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
完全基于Spring注解方式启动SpringMVC

测试结果:
在这里插入图片描述

2 Java过滤器与拦截器之间的区别

拦截器与过滤器之间有那些异同?
相同点:拦截器与过滤器都是基于Aop技术,对方法实现增强,都可以拦截请求方法。
不同点:

  1. 过滤器属于Servlet研发的,而拦截器技术属于SpringMVC研发的;
  2. 过滤器属于拦截Web请求,而拦截器不仅可以拦截请求还可以拦截普通方法;
  3. 过滤器会比拦截器先执行,拦截器封装的方法比过滤器拦截使用起来更加简单。

实际开发中绝大多数情况下,都会使用拦截器,
应用场景:
拦截器:权限控制、日志打印、参数验证、会话。
过滤器:编码转换、跨域解决、xss攻击

3 SpringMVC注解形式使用拦截器

自定义拦截器拦截请求Token

@Configuration
@ComponentScan("com.mayikt.controller")
// @EnableWebMvc
public class SpringMvcConfig extends WebMvcConfigurationSupport {
// implements WebMvcConfigurer也可生效
// extends WebMvcConfigurerAdapter 错误,已经过时了
// extends WebMvcConfigurationSupport也没有效果,@EnableWebMvc底层会帮助注入WebMvcConfigurationSupport子类,覆盖自定义配置类
// WebMvcConfigurationSupport帮助配置springmvc相关信息 web视图层相关内容
    // 1.手动注入拦截器到spring中
    @Bean
    public TokenInterceptor tokenInterceptor() {
        return new TokenInterceptor();
    }
    // 2.添加拦截器
    @Override
    public void addInterceptors(InterceptorRegistry interceptorRegistry){
        interceptorRegistry.addInterceptor(tokenInterceptor()).addPathPatterns("/**");// 拦截所有的请求
    }
}
public class TokenInterceptor implements HandlerInterceptor {

    /**
     * 请求方法前置拦截,如果返回true,表示会执行到目标方法(请求方法);返回false,不会执行目标方法
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String token = request.getParameter("token");
        System.out.println("token:" + token);
        if (StringUtils.isEmpty(token)) {
            response.setStatus(500);
            response.getWriter().println("token is null");
            return false;
        }
        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");
    }
}

注意:使用拦截器一定要关闭EnableWebMvc 否则拦截器不会生效。

4 SpringMVC拦截器使用的特征

运行结果:
在这里插入图片描述
preHandle在业务处理器处理请求之前被调用;
postHandle在业务处理器处理请求执行完成后,生成视图之前执行;
afterCompletion在DispatcherServlet完全处理完请求后被调用,可用于清理资源等。
afterCompletion()执行完成后开始渲染页面。

5 SpringMVC异步处理基本概念

在Web中为什么要使用异步?
目的:快速响应给客户端,防止客户端请求等待。单独开启一个线程处理。
缺点:线程安全问题、不能及时拿到结果、消耗CPU。

6 SpringMVC注解形式使用异步

@Controller
public class IndexController {
    @Autowired
    private MemberService memberService;

    @ResponseBody
    @RequestMapping(value = "/payToMember", produces = "text/html;charset=UTF-8")
    public String payToMember() {
        String memberResult = "结果为空!";
        System.out.println("1.开始执行payToMember>>> thread name:" + Thread.currentThread().getName());
        memberResult = memberService.member();
        System.out.println("4.结束执行payToMember>>> thread name:" + Thread.currentThread().getName());
        System.out.println("memberResult:" + memberResult);
        return memberResult;
    }
    // 执行顺序 1423 返回结果 null
}
@Component
public class MemberService {
    /**
     * member方法会单独开启线程处理请求
     * @return
     */
    @Async
    public String member() {
        try {
            System.out.println("2.开始调用会员服务接口...thread name:" + Thread.currentThread().getName());
            Thread.sleep(5000);
            System.out.println("3.结束调用会员服务接口...thread name:" + Thread.currentThread().getName());
        } catch (Exception e) {

        }
        return "member";
    }
}
@Configuration
@ComponentScan(basePackages = {"com.mayikt.controller", "com.mayikt.service"})
@EnableAsync
public class SpringMvcConfig extends WebMvcConfigurationSupport {
}

运行结果:
在这里插入图片描述

7 SpringMVC异步形式Callable

Callable接口:能够让耗时时间的代码,交给单独线程处理,也能够拿到异步线程结果。

@Controller
public class IndexController {
    @Autowired
    private MemberService memberService;

    @ResponseBody
    @RequestMapping(value = "/asyncPay", produces = "text/html;charset=UTF-8")
    public Callable<String> asyncPay() {
        System.out.println("1.开始执行payToMember>>> thread name:" + Thread.currentThread().getName());
        Callable<String> callable = new Callable<String>() {
            @Override
            public String call() throws Exception {
                String member = memberService.member2();
                return member;
            }
        };
        System.out.println("4.结束执行payToMember>>> thread name:" + Thread.currentThread().getName());
        return callable;
    }
    // 执行顺序 1423 返回结果 member
}
@Component
public class MemberService {

        public String member2() {
        try {
            System.out.println("2.开始调用会员服务接口...thread name:" + Thread.currentThread().getName());
            Thread.sleep(5000);
            System.out.println("3.结束调用会员服务接口...thread name:" + Thread.currentThread().getName());
        } catch (Exception e) {

        }
        return "member";
    }
}

运行报错:
在这里插入图片描述
xml配置文件中需新增true,转换成注解形式需要在WebInitializer类中增dispatcher.setAsyncSupported(true);
运行结果:
在这里插入图片描述
此时浏览器页面执行耗时代码仍会不断转圈,如果需求是异步返回结果且不想转圈,可以让客户端主动查询。
假设场景:支付调用会员,会员比较耗时间,调用支付接口马上响应给客户端告诉客户端正在等待会员响应,前台页面写一个定时器,服务端写一个接口,每隔1s查询支付调用会员是否成功,如果成功返回结果给客户端。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值