SpringMVC异常处理与拦截器实战揭秘

目录

一、SpringMVC异常处理

(一)异常处理思路

(二)SpringMVC异常处理

1.异常处理优先级

2.处理结果

3.核心注解

(三)处理异常

1.手动处理异常

2.异常处理器处理异常

①RoleController

②自定义异常类SysException

③自定义异常处理器SysExceptionResolver

④Springmvc.xml中配置异常处理器

⑤Jsp页面代码

⑥展示处理后的前端结果

二、SpringMVC拦截器

(一)核心概念

1.拦截器和过滤器

2.三个核心方法

(二)入门过滤器

1.写过滤器类

2.配置拦截器

3.Controller

4.运行看结果

(三)配置多个过滤器


一、SpringMVC异常处理

(一)异常处理思路

Controller调用service,service调用dao,异常都是向上抛出的,最终有DispatcherSevlet异常处理器进行异常处理。

(二)SpringMVC异常处理

1.异常处理优先级

局部异常处理器>全局异常处理>原生异常页面

2.处理结果

可以跳转到错误页面,也可以直接返回JSON数据

3.核心注解

@ExceptionHandler、@ControllerAdvice

(三)处理异常

1.手动处理异常

2.异常处理器处理异常

①RoleController
java 复制代码
package com.qcby.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/role")
public class RoleController {
//    /**
//     * 手动处理异常
//     * @return
//     */
//    @RequestMapping("/findAll.do")
//    public String findAll(){
//        try{
//            System.out.println("findAll执行了");
//            //模拟异常
//            int i = 1/0;
//        }catch (Exception e){
//            e.printStackTrace();
//            //跳转到友好提示页面
//        }
//        return "suc";
//    }

    /**
     * 使用异常处理器的方式
     * @return
     */
    @RequestMapping("/findAll1.do")
    public String findAll(){
        System.out.println("findAll执行了");
        //模拟异常
        int i=1/0;
        return "error";
    }
}
②自定义异常类SysException
java 复制代码
package com.qcby.exception;

/**
 * 自定义异常类
 */
public class SysException extends Exception{
    //提示消息
    private String message;

    @Override
    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public SysException(String message) {
        this.message = message;
    }
}
③自定义异常处理器SysExceptionResolver
java 复制代码
package com.qcby.exception;

import com.qcby.exception.SysException;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 自定义异常处理器
 */
public class SysExceptionResolver implements HandlerExceptionResolver {
    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
        //获取异常对象
        e.printStackTrace();
        //强转
        SysException exception=null;
        //判断
        if(e instanceof SysException) {
            exception=(SysException)e;
        }else{
            exception=new SysException("系统正在维护,请联系管理员");
        }
        //存入异常提示信息
        ModelAndView mv=new ModelAndView();
//将错误信息传给前端
        mv.addObject("errorMsg",e.getMessage());
        //跳转到错误页面
mv.setViewName("error");
        return mv;
    }
}
④Springmvc.xml中配置异常处理器
XML 复制代码
<bean id="sysExceptionResolver" class="com.qcby.exception.SysExceptionResolver" />
⑤Jsp页面代码
html 复制代码
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
    <title>错误提示页面</title>
</head>
<body>

<h3>错误的友好提示页面</h3>

${errorMsg}
</body>
</html>
⑥展示处理后的前端结果

二、SpringMVC拦截器

SpringMVC拦截器是请求的"门卫",在请求进入Controller之前/之后/页面渲染完成后,进行统一处理。

常用于:登录校验、权限判断、日志记录、敏感词过滤等。

(一)核心概念

1.拦截器和过滤器

·拦截器(Interceptor) :是SpringMVC自带的,只拦截进入Controller的请求

·过滤器(Filter) :Servlet规范,拦截所有请求

·执行顺序:过滤器->拦截器->Controller

2.三个核心方法

拦截器必须实现HandlerInterceptor接口,重写3个方法:

(1)preHandle:请求进入Controller前执行(常用,可以用于登录校验)

(2)postHandle:Controller执行完,返回页面之前执行

(3)afterCompletion:页面渲染完成后执行(资源清理)

(二)入门过滤器

1.写过滤器类

java 复制代码
package com.qcby.Interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class MyInterceptor2 implements HandlerInterceptor {

    /**
     * 拦截controller中方法。放行了,执行controller中方法。
     * return true 方向
     * return false 拦截
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("拦截器2的preHandle方法执行了...");
        // 手动跳转页面
        // request.getRequestDispatcher("/index.jsp").forward(request,response);
        // 拦截,不放行
        //return false;
        // 放行
        return true;
    }

    /**
     *
     * @param httpServletRequest
     * @param httpServletResponse
     * @param o
     * @param modelAndView
     * @throws Exception
     */
    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
        System.out.println("拦截器2的postHandle方法执行了...");
        // 也是可以进行页面的跳转
        httpServletRequest.getRequestDispatcher("/index.jsp").forward(httpServletRequest,httpServletResponse);
        return;
    }



    /**
     * controller跳转的jsp页面都执行完成了,最后执行该方法
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @throws Exception
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("拦截器2的afterCompletion方法执行了...");
    }
}

2.配置拦截器

可以配置想拦截的资源,和不想拦截的资源

XML 复制代码
<!--配置拦截器们-->
    <mvc:interceptors>
        <!--配置拦截器-->
        <mvc:interceptor>
            <!--该拦截器拦截哪些资源-->
            <mvc:mapping path="/dept/**"/>
            <!--哪些资源不想拦截
            <mvc:exclude-mapping path="" />
            -->
            <!--拦截器对象-->
            <bean class="com.qcby.Interceptor.MyInterceptor2" />
        </mvc:interceptor>
    </mvc:interceptors>

3.Controller

java 复制代码
package com.qcby.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/dept")
public class DeptController {
    @RequestMapping("/findAll.do")
    public String findAll(){
        System.out.println("Controller方法执行了 ");
        return "suc";
    }
}

4.运行看结果

(三)配置多个过滤器

再编写一个过滤器3

java 复制代码
package com.qcby.Interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 *
 * 老师
 * 拦截器类
 */
public class MyInterceptor3 implements HandlerInterceptor{

    /**
     * 拦截controller中方法。放行了,执行controller中方法。
     * return true 方向
     * return false 拦截
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("拦截器3的preHandle3方法执行了...");
        // 放行
        return true;
    }

    /**
     * controller方法执行后,要拦截的方法
     * @param request
     * @param response
     * @param handler
     * @param modelAndView
     * @throws Exception
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("拦截器3的postHandle3方法执行了...");
    }

    /**
     * controller跳转的jsp页面都执行完成了,最后执行该方法
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @throws Exception
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("拦截器3的afterCompletion3方法执行了...");
    }

}

在springmvc.xml里配置拦截器3

XML 复制代码
<mvc:interceptor>
    <mvc:mapping path="/**"/>
    <bean class="com.qcby.Interceptor.MyInterceptor3" />
</mvc:interceptor>

运行查看结果

看一下执行顺序,执行顺序应该是严格按照在springmvc中的配置顺序严格执行的

比如说这里先配置的拦截器2,再配置的拦截器3,我们就会发现它的执行顺序是这样的:

相关推荐
仟里码1 小时前
九:goroutine(1.什么是协程)
后端
不是万能的豆学长1 小时前
排查Go服务40天后的内存泄漏问题
开发语言·后端·golang·go
阿狗童鞋1 小时前
SpringSecurity权限认证实战指南
java·后端·spring
码匠许师傅1 小时前
【C++三方组件】libpqxx:PostgreSQL 的 C++ 客户端
开发语言·c++·postgresql
韩振方1 小时前
Kubernetes Service 让会更换的 Pod 有稳定访问入口
后端
用户125758524361 小时前
Golang后台管理框架推荐:XYGo Admin与devinggo怎么选?
后端·go·ai编程
Wang's Blog1 小时前
Java 项目部署之 Docker工具快速入门: 学习路径与命令速查导引
java·学习·docker
仟里码1 小时前
十一:goroutine(3. select基本使用)
后端
花间相见1 小时前
【计算基础|网络13】UDP 与可靠传输
后端·面试