Java学习笔记:SpringMVC

SpringMVC

Java学习笔记:SpringMVC_第1张图片

ApplicationContext应用上下文获取方式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lLdlemnX-1594791930190)(C:\Users\l\AppData\Roaming\Typora\typora-user-images\image-20200629135527220.png)]

在没有配置spring监听器时,要手动将将spring的应用上下文对象存储到ServletContext域中

1.初始化
 //上下文初始化方法
    public void contextInitialized(ServletContextEvent sce) {
        //将spring的应用上下文对象存储到ServletContext域中
        ServletContext servletContext = sce.getServletContext();
        ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        servletContext.setAttribute("app",app);
        System.out.println("Spring容器创建完毕");
    }
2.配置web.xml
  <!--配置之监听器,当服务器一启动(这个ContextLoaderListener是我们手写的假的)-->
    <listener>
        <listener-class>com.ry.listener.ContextLoaderListener</listener-class>
    </listener>
3.调用
@Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ApplicationContext app = (ApplicationContext) req.getServletContext().getAttribute("app");
        UserService userService = app.getBean(UserService.class);
        uservice.save();
    }

提取配置文件

Java学习笔记:SpringMVC_第2张图片

在web.xml中

Java学习笔记:SpringMVC_第3张图片

Spring提供获取应用上下文的工具

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-i4yW9O5i-1594791930200)(C:\Users\l\AppData\Roaming\Typora\typora-user-images\image-20200629144825245.png)]

Java学习笔记:SpringMVC_第4张图片

而当配置了spring自带的监听器之后,只要使用WebApplicationontextUtils获得应用上下文对象ApplicationContext就能获取到域对象

① 在web.xml里面配置ContextLoaderListener监听器(导入spring-web坐标)


  <context-param>
    <param-name>contextConfigLocationparam-name>
    <param-value>classpath:applicationContext.xmlparam-value>
  context-param>

  
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class>
  listener>

② 使用WebApplicationontextUtils获得应用上下文对象ApplicationContext

 @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext servletContext = req.getServletContext();
        
        //使用webApplicationContextUils获取应用上下文对象Application
        ApplicationContext app = WebApplicationContextUtils.getWebApplicationContext(servletContext);
        
        UserService userService = app.getBean(UserService.class);
        
        userService.save();

    }

SpringMVC简介

SpringMVC是一种基于java的实现mvc设计模型的请求驱动类型的轻量级Web框架,属于SpringFrameWork的后续产品,已经融合在SpringWeb Flow中.
在这里插入图片描述

SpringMVC的开发步骤

  1. 导入SpringMVC的包

    Java学习笔记:SpringMVC_第5张图片

  2. 配置Servlet

    Java学习笔记:SpringMVC_第6张图片

  3. 编写Controller

    Java学习笔记:SpringMVC_第7张图片

  4. 将Controller使用在注解配置到Spring容器当中(在web层上用@Controller)

Java学习笔记:SpringMVC_第8张图片
5. 配置组件扫描,具体到扫那个包
在这里插入图片描述
6. 配置spring-mvc.xml文件(配置组件扫描)

Java学习笔记:SpringMVC_第9张图片
7. 执行访问测试
Java学习笔记:SpringMVC_第10张图片

SpringMVC流程图示

Java学习笔记:SpringMVC_第11张图片

Java学习笔记:SpringMVC_第12张图片

知识要点

Java学习笔记:SpringMVC_第13张图片

SpringMVC组件解析

SpringMVC的执行流程

Java学习笔记:SpringMVC_第14张图片

  1. 用户发送请求到前端控制器DispatcherServlet
  2. DispatcherServlet 收到请求调用HandlerMapping处理映射器
  3. 处理器映射器找到具体的处理器(可以根据xml配置,注解进行查找),生产处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet
  4. DispatcherServlet 调用HandlerAdapter处理器适配器
  5. HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)
  6. Conyroller执行完成返回ModelAndView。
  7. DispatcherServletConyroller执行结果ModelAndView返回给DispatcherServlet
  8. DispatcherServlet将ModelAndView传给ViewReslover视图解析器
  9. ModelAndView解析后返回给具体View
  10. DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。DispatcherServlet响应用户

SpringMVC注解解析

@RequestMapping
作用:用于URL和处理请求方法之间的对应关系

位置:

  • 类上,请求URL的第一级访问目录。此处不写的话,就相当于应用的根目录
  • 方法上,请求URL的第二级访问目录,与类上的使用@RequestMapping标注的一级目录组成访问虚拟路径

属性:

  • value:用于指定请求的URL。它和path属性的作用是一样的
  • method:用于指定请求的方式
  • params:用于指定请求参数的条件。它支持简单的表达式。要求请求参数的key与value必须和配置的一模一样

例如:

  • parames={“accountNamel”},表示请其参数必须有accountNamel
  • parames={“moeny!100”},表示参数中money不能是100
@Controller
@RequestMapping("/user")
public class UserController {
    @RequestMapping(value = "/quick",method = RequestMethod.GET,params = {"username=100"})
    public String  save(){
        System.out.println("Contrller save running.......");
        return  "success";
    }
}

SpringMVC的XML配置解析(资源解析器)

Java学习笔记:SpringMVC_第15张图片

这个里面配置的都是默认的组件


    <bean id="viewResoler" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/jsp/">property>
        <property name="suffix" value=".jsp">property>
    bean>

Java学习笔记:SpringMVC_第16张图片

知识要点

Java学习笔记:SpringMVC_第17张图片

  • 负责帮我们调用其他一些功能组件
  • 帮我进行地址解析,返回对应的一个执行链
  • 被前端控制器,调用处理器
  • Controller
  • 负责解析出来View
  • 封装视图信息

SpringMVC的注解配置

  • 虚拟地址映射

## SpringMVC的数据响应

SpringMVC的数据响应方式

  1. 页面跳转
    • 直接返回字符串
    • 通过ModelAndView对象返回
  2. 回写数据
    • 直接返回字符串
    • 返回对象或集合
页面跳转
  • 直接返回字符串
  • 通过ModelAndView对象返回
  1. 返回字符串形式

    ​ 直接返回字符串:此种方式会将返回的字符串与视图解析器的前后缀拼接后跳转

    Java学习笔记:SpringMVC_第18张图片

  2. 返回ModelAndView对象

形式一

@RequestMapping("/quick2")
    public ModelAndView save2(){
        ModelAndView modelAndView = new ModelAndView();
        /*
         Model:模型 作用是封装数据

         View:视图  作用是展示数据
        */
        //设置模型数据,这个数据就相当于放在request域当中了
        modelAndView.addObject("username","张三");
        //如果只想展示视图的话,可以为它设置视图数据
        modelAndView.setViewName("index");
        return  modelAndView;
    }

```jsp <%@ page contentType="text/html;charset=UTF-8" language="java" %> Title 这里是jsp文件夹${requestScope.username} ```

形式二

SpringMVC对方法的参数可以进行相应的注入,比如说这里写了一个ModelAndView,那它在解析参数时,发现有个ModelAndView需要SpringMVC框架提供,那SpringMVC框架就会为你提供一个SpringMVC对象,就可以在内部直接用了

@RequestMapping("/quick3")
 public ModelAndView  save3(ModelAndView modelAndView){
        modelAndView.addObject("username","张三");
        //如果只想展示视图的话,可以为它设置视图数据
        modelAndView.setViewName("index");
        return  modelAndView;
    }

<%@ page contentType="text/html;charset=UTF-8" language="java" %>


 Title
   

这里是jsp文件夹${requestScope.username}


衍生:优化

@RequestMapping("/quick4")
 public String  save4(Model model){
        model.addAttribute("username","zhangsan");
        return  "success";
    }
   
<%@ page contentType="text/html;charset=UTF-8" language="java" %>


 Title
   

success!!!

${username}

回写数据
  • 直接返回字符串
  • 返回对象或集合
  1. 直接返回字符串

    ① Web基础阶段,客户端访问服务器端,如果想直接回写字符串作为响应体返回的话,只需要使用response.getWriter().print(“hello world”)即可,那么在Controller中想直接回写字符串该怎样呢?

    ② 将需要回写的字符串直接返回,但此时需要通过@ResponseBody注解告知SprinMVC框架,方法返回的字符串不说跳转是直接在http响应体中返回

     @ResponseBody
        @RequestMapping("/quick6")
        public String   save6() throws IOException {
            return "hello  wangwu";
        }
    

    直接回写json的方式

    @ResponseBody
        @RequestMapping("/quick7")
        public String   save7() throws IOException {
            User user = new User();
            user.setUsername("zhangsan");
            user.setAge(50);
            //使用json的转换工具,将对象转换成json格式字符串再返回
            ObjectMapper objectMapper = new ObjectMapper();
            String  json= objectMapper.writeValueAsString(user);
            return json;
        }
    
  2. 返回对象或集合

    Java学习笔记:SpringMVC_第19张图片

    第一步:配置spring-xml中json的转换器

        
        <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
            <property name="messageConverters">
                <list>
                    <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">bean>
                list>
            property>
        bean>
    

    第二步:直接返回对象,便会自动转化为json字符串格式

    //期望SpringMVC自动将User转化成json格式字符串
        @ResponseBody
        @RequestMapping("/quick8")
        public User   save8() throws IOException {
            User user = new User();
            user.setUsername("lisi");
            user.setAge(3333);
            return  user;
        }
    

    Java学习笔记:SpringMVC_第20张图片

    优化:使用注解驱动

     
        
       <mvc:annotation-driven/>
    

SpringMVC获得请求数据

客户端请求参数的格式是:name=value&name=value…

服务器端要获得请求的参数,有时候还需要进行数据的封装,SpringMVC可以接受如下类型的参数:

  • 基本类型参数
  • POJO类型参数(例如:User,Person类等)
  • 数组类型参数
  • 集合类型参数

获得基本类型参数

​ Controller中的业务方法的参数名称要与请求参数的name一致,参数值会自动映射匹配。

Java学习笔记:SpringMVC_第21张图片

 @ResponseBody
    @RequestMapping("/quick9")
    public void save9(String username ,int age) throws IOException {
        System.out.println(username);
        System.out.println(age);
    }

Java学习笔记:SpringMVC_第22张图片

获得POJO类型参数

Java学习笔记:SpringMVC_第23张图片

Java学习笔记:SpringMVC_第24张图片

 @ResponseBody
    @RequestMapping("/quick10")
    public void   save10(User user) throws IOException {
        System.out.println(user);
    }
public class User  {
    private  String  username;
    private int age;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                ", age=" + age +
                '}';
    }
}

获得数组类型参数

Java学习笔记:SpringMVC_第25张图片
Java学习笔记:SpringMVC_第26张图片

  @ResponseBody
    @RequestMapping("/quick11")
    public void   save11(String[] str) throws IOException {
        //数组默认打印的是地址,要想看到具体值,得for循环打印
        //所以在这里转换成list集合
        System.out.println(Arrays.asList(str));
    }

获得集合类型参数

第一种情况

注意:获得集合参数时,要将集合参数包装到一个POJO中才可以

1.jsp页面中

<form action="${pageContext.request.contextPath}/user/quick12" method="post">
<%--表明是第一个User对象的username age--%>
    <input type="text" name="userList[0].username"><br/>
    <input type="text" name="userList[0].age"><br/>
    <input type="text" name="userList[1].username"><br/>
    <input type="text" name="userList[1].age"><br/>
    <input type="text" name="userList[2].username"><br/>
    <input type="text" name="userList[2].age"><br/>
    <input type="submit" value="提交">
form>

2.java代码

 @ResponseBody
    @RequestMapping("/quick12")
    public void   save12(VO vo) throws IOException {
        System.out.println(vo);
    }
第二种情况

Java学习笔记:SpringMVC_第27张图片

1.编写jsp页面,发送ajax请求

<script src="${pageContext.request.contextPath}/js/jquery-3.3.1.js">script>
<script>
    var userList=new Array();
    userList.push({username:"zhangsan",age:18});
    userList.push({username:"lisi",age:28});
        $.ajax({
            type:"POST",
            url:"${pageContext.request.contextPath}/user/quick13",
            data:JSON.stringify(userList),
            contentType:"application/json;charset=utf-8"
        })
script>

2.在方法参数位置使用@RequestBody注解,直接接收集合数据,无需POJO封装

 @ResponseBody
    @RequestMapping("/quick13")
    public void   save13(@RequestBody List<User> userList) throws IOException {
        System.out.println(userList);
    }

3.发现访问jsp页面之后并未获取到数据,js文件夹未被读取,需在spring-mvc.xml中间配置

<mvc:resources mapping="/js/**" location="/js/"/>

或者

  

开启允许静态资源访问

请求数据乱码问题

在web.xml中

Java学习笔记:SpringMVC_第28张图片

  
  <filter>
    <filter-name>CharacterEncodingFilterfilter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-class>
    <init-param>
      <param-name>encodingparam-name>
      <param-value>UTF-8param-value>
    init-param>
  filter>
  <filter-mapping>
    <filter-name>CharacterEncodingFilterfilter-name>
    <url-pattern>/*url-pattern>
  filter-mapping>

参数绑定注解

Java学习笔记:SpringMVC_第29张图片
Java学习笔记:SpringMVC_第30张图片

 @ResponseBody
    @RequestMapping("/quick9")
    public void   save9(@RequestParam(value = "name" ,required = false,defaultValue = "null") String username) throws IOException {
        System.out.println(username);
    }

获得Restful风格的参数

Java学习笔记:SpringMVC_第31张图片

Java学习笔记:SpringMVC_第32张图片

1.访问的地址
在这里插入图片描述

2.获取的数据

Java学习笔记:SpringMVC_第33张图片

3.java代码

   @ResponseBody
    @RequestMapping("/quick14/{username}")
    public void   save14(@PathVariable("username") String  name) throws IOException {
            System.out.println(name);
    }

自定义类型转换器

Java学习笔记:SpringMVC_第34张图片

第一步:定义转换器实现Converter接口,复写方法


public class conveter implements Converter<String, Date> {
    @Override
    public Date convert(String s) {
        Date date =null;
        //将我们日期的字符串转化成真正的日期对象,返回
        SimpleDateFormat format=new SimpleDateFormat("yyyy-MM-dd");
        try {
            date = format.parse(s);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }
}

第二步:在配置文件中声明


    <bean  id="ConversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
        <property name="converters">
            <list>
                <bean class="com.ry.DateConveter.conveter">bean>
            list>
        property>
    bean>

第三步:在mvc:annotation中引用转换器

获取请求头数据

@RequestHeader

Java学习笔记:SpringMVC_第35张图片

案例:文件上传

文件上传三要素

Java学习笔记:SpringMVC_第36张图片

文件上传原理

Java学习笔记:SpringMVC_第37张图片

创建文件提交的表单

<form action="${pageContext.request.contextPath}/user/quick16" method="post" enctype="multipart/form-data">
 名称<input type="text" name="userame"/><br/>
 文件<input type="file" name="upload"/><br/>
 文件<input type="submit" value="提交"/><br/>
form>

单文件的上传步骤

  1. 导入fileupload和io坐标

       
        <dependency>
          <groupId>commons-iogroupId>
          <artifactId>commons-ioartifactId>
          <version>2.4version>
        dependency>
        <dependency>
          <groupId>commons-fileuploadgroupId>
          <artifactId>commons-fileuploadartifactId>
          <version>1.3.1version>
        dependency>
    
  2. 配置文件上传解析器

     
        <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
            <property name="defaultEncoding" value="UTF-8"/>
            <property name="maxUploadSize" value="500000"/>
        bean>
    

Java学习笔记:SpringMVC_第38张图片

  1. 编写文件上传代码

    @ResponseBody
        @RequestMapping("/quick16")
        public void   save16(String username,MultipartFile uploadFile) throws IOException {
    
            System.out.println(uploadFile);
            System.out.println(username);
               //获得文件名称
            String originalFilename = uploadFile.getOriginalFilename();
            //保存文件
            uploadFile.transferTo(new File("C:\\Users\\l\\Desktop\\"+originalFilename));
        }
    

    Java学习笔记:SpringMVC_第39张图片

    多文件上传

        @ResponseBody
        @RequestMapping("/quick17")
        public void   save17(String username,MultipartFile[] uploadFile) throws IOException {
            //获得文件名称
            for (MultipartFile multipartFile : uploadFile) {
                //获得文件名称
                String originalFilename = multipartFile.getOriginalFilename();
                //保存文件至指定的目录
                multipartFile.transferTo(new File("C:\\Users\\l\\Desktop\\"+originalFilename));
            }
        }
    
    <form action="${pageContext.request.contextPath}/user/quick17" method="post" enctype="multipart/form-data">
        名称<input type="text" name="username"/><br/>
        文件1<input type="file" name="uploadFile"/><br/>
        文件2<input type="file" name="uploadFile"/><br/>
        文件3<input type="file" name="uploadFile"/><br/>
        <input type="submit" value="提交"/><br/>
    form>
    

    Java学习笔记:SpringMVC_第40张图片

Spring拦截器

拦截器(interceptor)的作用

相当于web阶段的过滤器filter

Java学习笔记:SpringMVC_第41张图片

拦截器和过滤器的区别

Java学习笔记:SpringMVC_第42张图片

拦截器的快速入门

Java学习笔记:SpringMVC_第43张图片

1.创建拦截器类实现HandlerInterceptor接口

public class MyInerceptor1  implements HandlerInterceptor {
    //在目标方法执行之前执行
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle....");
        String param = request.getParameter("param");
        //如果获取的参数里面包括yes,则放行,否则就不放行,跳转到error.jsp
        if ("yes".equals(param)){
            //当返回true时,放行
            return true;
        }else{
            //当返回false时,拦截后面的动作,不放行
            request.getRequestDispatcher("/error.jsp").forward(request,response);
            return  false;
        }
    }
    //在目标方法执行之后,视图返回之前执行
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
       modelAndView.addObject("name","李四");
        System.out.println("postHandle....");
    }
    //在整个流程都执行完毕之后执行,做收尾工作
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion...");
    }
}

2.在spring-mvc中配置拦截器

<!--配置拦截器-->
    <mvc:interceptors>
        <mvc:interceptor>
            <!--代表对哪些资源执行拦截操作  /**代表对所有的资源都进行拦截-->
            
            
        
    

3.测试

Java学习笔记:SpringMVC_第44张图片

在有多个拦截器时,拦截的顺序与spring-xml中的配置先后顺序有关,例如:下面的配置的执行顺序就是先执行上面的再执行下面的

Java学习笔记:SpringMVC_第45张图片


    <mvc:interceptors>
        <mvc:interceptor>
            
            <mvc:mapping path="/**"/>
            <bean class="com.ry.interceptor.MyInerceptor1"/>
        mvc:interceptor>
        <mvc:interceptor>
            
            <mvc:mapping path="/**"/>
            <bean class="com.ry.interceptor.MyInerceptor2"/>
        mvc:interceptor>
    mvc:interceptors>

拦截器方法说明

![> [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RdKKqzHh-1594791930303)(C:\Users\l\AppData\Roaming\Typora\typora-user-images\image-20200701171014870.png)]

](https://img-blog.csdnimg.cn/20200715135901723.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1MzU5Mzg2,size_16,color_FFFFFF,t_70)

案例:用户登录权限控制

Java学习笔记:SpringMVC_第46张图片

第一步:创建拦截器类并且实现HandlerInterceptor接口,复写方法

public class PrivilegeInterceptor implements HandlerInterceptor  {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
       //逻辑:判断用户是否登录
        //主要判断session中有没有user
        HttpSession session = request.getSession();
        User user = (User) session.getAttribute("user");
       if (user==null){
           //如果没有登录,跳回登陆页面
           response.sendRedirect(request.getContextPath()+"/login.jsp");

           return false;
       }else {
           //如果登录,放行,访问目标资源
           return true;
       }
    }
}

2.在spring-mvc.xml中配置拦截器

 <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <bean class="com.itheima.interceptor.PrivilegeInterceptor">bean>
        mvc:interceptor>
    mvc:interceptors>

注意

在以上都配完之后,出现了一个问题,即使输对密码和账号也登陆不了
是因为在配置拦截器时,把拦截的路径path设置成了/**,全部拦截,所以需要在这里放行一下

 <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            
            
            <mvc:exclude-mapping path="/usre/login"/>
            
            <bean class="com.itheima.interceptor.PrivilegeInterceptor">bean>
        mvc:interceptor>
    mvc:interceptors>

SpringMVC异常处理机制

异常处理的思路

Java学习笔记:SpringMVC_第47张图片

异常处理的两种方式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WnUHbu0U-1594791930307)(C:\Users\l\AppData\Roaming\Typora\typora-user-images\image-20200701204743383.png)]

简单异常处理器:SimpleMappingExceptionResolver

  
    <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
    
        <property name="exceptionMappings">
            <map>
                
                <entry key="java.lang.ClassCastException" value="error1">entry>
                
                <entry key="com.itheima.exception.MyException" value="error2">entry>
            map>
        property>
    bean>

Java学习笔记:SpringMVC_第48张图片

自定义异常处理步骤:

Java学习笔记:SpringMVC_第49张图片

1.创建异常处理类实现HandlerExceptionResolver接口,复写方法

public class MyExceptionResolver  implements  HandlerExceptionResolver{
    /**
     * @param httpServletRequest
     * @param httpServletResponse
     * @param o
     * @param e 参数Exception:异常对象
     * @return 返回值ModelAndView:跳转到错误视图页面
     */
    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
        ModelAndView modelAndView = new ModelAndView();

        if (e instanceof  MyException){
            modelAndView.addObject("info","自定义异常");
        }else  if (e instanceof  ClassCastException){

            modelAndView.addObject("info","类转换异常");
        }
        modelAndView.setViewName("error");
        return modelAndView;
    }
}

2.配置异常处理器

    
    <bean class="com.itheima.resolver.MyExceptionResolver"/>

3.配置错误页面

4.调试页面

注意:在以后的开发过程中,再遇到异常的时候,就尽管往上抛出异常,直到被我们定义或配置的异常处理器捕获

知识要点

Java学习笔记:SpringMVC_第50张图片

你可能感兴趣的:(spring,java,mvc,web)