1. 首页 >  小程序定制 >  Spring MVC学习随笔-Ajax集成(JSON格式返回数据)、拦截器(MyInterceptor)、全局异常处理(GlobalExceptionResolver)

Spring MVC学习随笔-Ajax集成(JSON格式返回数据)、拦截器(MyInterceptor)、全局异常处理(GlobalExceptionResolver)

学习视频:【编程不良人】继spring之后快速入门springmvc,面对SpringMVC不用慌

第七章、SpringMVC与Ajax集成

  • 引入相关依赖

    <dependency>
    

    com.fasterxml.jackson.core jackson-databind 2.9.8

  • 开发控制器

    @Controller
    

    @RequestMapping(“json”) public class JsonController { /** * 引入jackson库可以使用@ResponseBody自动转换为json格式数据【推荐】 */ @RequestMapping(“showAll”) public @ResponseBody List findAll() { //1.收集数据 //2.调用业务 List users = new ArrayList<>(); users.add(new User(UUID.randomUUID().toString(), “小红”, 23, new Date())); users.add(new User(UUID.randomUUID().toString(), “小名”, 29, new Date())); users.add(new User(UUID.randomUUID().toString(), “小撒”, 25, new Date())); return users; } /** * 传统写法:引入阿里fastjson手动转换为json格式数据 */ @RequestMapping(“findAll”) public void findAll(HttpServletResponse response) throws IOException { //1.收集数据 //2.调用业务 List users = new ArrayList<>(); users.add(new User(UUID.randomUUID().toString(), “小陈”, 23, new Date())); users.add(new User(UUID.randomUUID().toString(), “小名”, 29, new Date())); users.add(new User(UUID.randomUUID().toString(), “小撒”, 25, new Date())); // fastjson String s = JSONObject.toJSONStringWithDateFormat(users, “yyyy-MM-dd”); response.setContentType(“application/json;charset=UTF-8”); response.getWriter().println(s); } }

  • 日期格式修正

    @JsonFormat(pattern = "yyyy-MM-dd")
    

    private Date bir;

可以正常响应

第八章、SpringMVC的拦截器

  1. 拦截器 :Interceptor 拦截 中断

类似于javaweb中的Filter,不过没有Filter那么强大

  1. 作用

Spring MVC的拦截器是一种用于在请求处理过程中进行预处理和后处理的机制。拦截器可以在请求到达控制器之前和之后执行一些操作,例如日志记录、权限验证、数据处理等。

  1. 拦截器特点

    1. 请求到达会经过拦截器,响应回来同样会经过拦截器
    2. 拦截器只能Controller的请求,不能拦截jsp、静态资源相关请求
    3. 拦截器可以中断请求轨迹
  2. 开发拦截器

    1. 类 实现implements HandlerInterceptor 接口中的方法

    2. 配置拦截器

注册拦截器对象 bean id class=””

配置拦截器拦截请求路径

  • 编码和测试结果

拦截器接口的实现

    public class MyInterceptor implements HandlerInterceptor {
    @Override
    //**参数1:当前请求对象  参数2:当前请求响应对象 参数3:当前请求的控制器对应的方法对象**
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("handler = " + ((HandlerMethod)handler).getMethod().getName() );
        System.out.println("MyInterceptor.preHandle");
        //强制用户登录
        Object user = request.getSession().getAttribute("user");
//        if (user == null) {
//            // 重定向到登录页面
//            response.sendRedirect(request.getContextPath() + "/login.jsp");
//            return false;
//        }
        return HandlerInterceptor.super.preHandle(request, response, handler);
    }

    @Override
    // 参数1、2、3同上 **参数4:当前控制器方法的返回值**
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("modelAndView = " + modelAndView);
        System.out.println("MyInterceptor.postHandle");
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    // 参数1、2、3同上 **参数4:请求过程中出现异常时的异常对象**
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("MyInterceptor.afterCompletion");
        if (ex != null) {
            System.out.println("ex.getMessage() = " + ex.getMessage());
        }
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }
}

dispatcher.xml 配置拦截器

    <!--注册拦截器-->
<bean id="myInterceptor" class="com.baizhi.interceptors.MyInterceptor"/>
<!--配置拦截器-->
<mvc:interceptors>
    <!--配置一个拦截器-->
    <mvc:interceptor>
        <!-- mvc:mapping 代表拦截哪个请求路径-->
        <mvc:mapping path="/json/test"/>
        <!--排除具体地拦截请求-->
        <mvc:exclude-mapping path="/json/showAll"/>
        <!--使用拦截器-->
        <ref bean="myInterceptor"/>
    </mvc:interceptor>
</mvc:interceptors>

进行测试

    @RequestMapping("test")
    public String test() {
        System.out.println("JsonController.test");
//        throw new RuntimeException();
        return "index";
    }

按预期执行顺序执行

看到拦截器的执行顺序,我们会联想到Spring中的AOP,两者的底层逻辑都是通过动态代理实现的,虽然拦截器和AOP都可以用于在请求处理过程中添加额外的逻辑,但拦截器更专注于请求处理阶段的任务,而AOP更适用于在不同模块中实现横切关注点的功能。

关于动态代理和AOP底层可以看之前学习的:Spring5学习随笔-AOP底层实现(JDK、CGlib)、实现切面(@Aspect)
Spring5学习随笔-AOP系列Spring动态代理

第九章、SpringMVC中的全局异常处理

  1. SpringMVC作为一个控制主要作用

    1. 处理请求 接收请求数据 调用业务对象
    2. 请求响应 跳转对应视图展示数据

  1. 现有控制器开发存在问题?

    1. 在处理用户请求出现运行时异常直接响应给用户的是一个错误节目,对于用户的使用体验不友好。

没有使用全局异常处理时

  1. 全局异常处理机制

作用:用来解决整合系统中任意一个控制器抛出异常时的统一处理入口

  • 编码

开发控制类

    public class GlobalExceptionResolver implements HandlerExceptionResolver {
    /**
     * 用来处理发生异常时的方法
     *
     * @param request  当前请求对象
     * @param response 当前请求对应的响应对象
     * @param handler  当前请求的方法对象
     * @param ex       当前出现异常时的异常对象
     * @return 出现异常时展示视图和数据
     */
    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        System.out.println("进入全局异常处理器,获取的异常信息为:" + ex.getMessage());
        ModelAndView modelAndView = new ModelAndView();
        // 基于不同业务异常跳转到不同页面
        modelAndView.setViewName("redirect:/error.jsp"); // return "error" -> error.jsp
        // modelAndView中的model默认放到request作用域,如果使用redirect跳转,model中数据会自动拼接到跳转url
        modelAndView.addObject("msg", ex.getMessage());
        return modelAndView;
    }
}

dispatcher.xml 配置全局异常处理类

    <bean class="com.baizhi.handlerexception.GlobalExceptionResolver"/>
  • 基于不同业务异常跳转不同页面

    // 基于不同业务异常跳转到不同页面
    

    if (ex instanceof NotFoundException) { modelAndView.setViewName(“notFound”); } else if (ex instanceof GeneralException) { modelAndView.setViewName(“generalException”); }

异常处理器的工作流程

/xiao-cheng-xu-ding-zhi/spring-mvcxue-xi-sui-bi-ajaxji-cheng-jsonge-shi-fan-hui-shu-ju-lan-jie-qi-myinterceptor-quan-ju-yi-chang-chu-li-globalexceptionresolver-1551.html