8.ssm之springmvc

SpringMVC

1 SpringMVC初涉

1.1 为什么要使用SpringMVC

​ 背景:很多应用程序的问题在于处理业务数据的对象和显示业务数据的视图之间存在紧密耦合,通常,更新业务对象的命令都是从视图本身发起的,使视图对任何业务对象更改都有高度敏感性。而且,当多个视图依赖于同一个业务对象时是没有灵活性的。

SpringMVC是一种基于Java,实现了Web MVC设计模式,请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将Web层进行职责解耦。基于请求驱动指的就是使用请求-响应模型,框架的目的就是帮助我们简化开发,SpringMVC也是要简化我们日常Web开发。

1.2 SpringMVC的地位

image-20201030093423606

1.3 SpringMVC的架构

image-20201030093500996

具体流程:

(1)首先浏览器发送请求——>DispatcherServlet,前端控制器收到请求后自己不进行处理,而是委托给其他的解析器进行处理,作为统一访问点,进行全局的流程控制;

(2)DispatcherServlet——>HandlerMapping,处理器映射器将会把请求映射为HandlerExecutionChain对象(包含一个Handler处理器对象、多个HandlerInterceptor拦截器)对象;

(3)DispatcherServlet——>HandlerAdapter,处理器适配器将会把处理器包装为适配器,从而支持多种类型的处理器,即适配器设计模式的应用,从而很容易支持很多类型的处理器;

(4)HandlerAdapter——>调用处理器相应功能处理方法,并返回一个ModelAndView对象(包含模型数据、逻辑视图名);

(5)ModelAndView对象(Model部分是业务对象返回的模型数据,View部分为逻辑视图名)——> ViewResolver, 视图解析器将把逻辑视图名解析为具体的View;

(6)View——>渲染,View会根据传进来的Model模型数据进行渲染,此处的Model实际是一个Map数据结构;

(7)返回控制权给DispatcherServlet,由DispatcherServlet返回响应给用户,到此一个流程结束。

2 SpringMVC的搭建

2.1 创建一个maven项目,导入pom文件
<dependencies>
    <!--ioc四个包-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>4.3.7.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>4.3.7.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-expression</artifactId>
        <version>4.3.7.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
        <version>4.3.7.RELEASE</version>
    </dependency>
    <!--aop包-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aop</artifactId>
        <version>4.3.7.RELEASE</version>
    </dependency>
    <!--web两个包-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>4.3.7.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>4.3.7.RELEASE</version>
    </dependency>
    <!--日志包-->
    <dependency>
        <groupId>commons-logging</groupId>
        <artifactId>commons-logging</artifactId>
        <version>1.2</version>
    </dependency>
    <dependency>
        <groupId>org.apache.tomcat.embed</groupId>
        <artifactId>tomcat-embed-core</artifactId>
        <version>9.0.27</version>
    </dependency>
    <dependency>
        <groupId>jstl</groupId>
        <artifactId>jstl</artifactId>
        <version>1.2</version>
    </dependency>
</dependencies>
2.2 配置web.xml

配置一个DispatcherServlet

<!--1.配置中央处理器,也可以成为前端控制器-->
<servlet>
    <servlet-name>DispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!--1.1配置初始化参数:指定springmvc的配置文件位置-->
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:springmvc.xml</param-value>
    </init-param>
    <!--1.2设置优先级:启动加载-->
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>DispatcherServlet</servlet-name>
    <url-pattern>*.action</url-pattern>
</servlet-mapping>
2.3 配置一个controller

方式1:实现Controller接口

package com.zhiyou100.controller;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class HelloController implements Controller {

    @Override
    public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
        //成功来到了这里
        System.out.println("成功来到了处理器!");
        ModelAndView modelAndView = new ModelAndView("/WEB-INF/pages/success.jsp");
        modelAndView.addObject("message","你好啊!");
        return modelAndView;
    }
}
2.4 配置处理器的映射

​ 在springmvc.xml中进行配置处理器的bean

<bean name="/action01/hello.action" class="com.zhiyou100.controller.HelloController" />
2.5 发布项目

​ 配置tomcat信息,发布项目,进行访问。

注:可能会出现DispatcherServlet找不到的错误,需要进入项目结构中对依赖的jar包进行配置,此问题出现在idea的maven项目中。

image-20201030101201643

3 配置形式的SpringMVC细节

3.1 DispatcherServlet

​ 前端控制器:拦截请求,将请求交给HandleMapping来处理。

<!--1.配置前端控制器-->
<servlet>
    <servlet-name>DispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!--1.1配置初始化参数:指定springmvc的配置文件位置
        1.2如果不指定,则配置文件需要写在WEB-INF下,且名字为:当前servlet的名字+"-servlet.xml"。
            例如DispatcherServlet-servlet.xml
    -->
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:springmvc.xml</param-value>
    </init-param>
    <!--1.2设置优先级:启动加载-->
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>DispatcherServlet</servlet-name>
    <url-pattern>*.action</url-pattern>
</servlet-mapping>

细节:

  1. 配置文件的指定,如果不指定配置文件的位置,需要将配置文件写到WEB-INF下,且对名字配置文件的名字有要求。
    1. 本例中应为:“DispatcherServlet-servlet.xml”。
3.2 HandleMapping

​ 主要用于处理bean以及url的映射关系。

1 BeanNameUrlHandlerMapping

​ 默认的处理器映射器,指定action的name属性就是url。配置方式如下所示:

<bean name="/action01/hello.action" id="helloController" class="com.zhiyou100.controller.HelloController" />

因为是默认的行为,此bean可以不显示的声明

<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />

2 SimpleUrlHandlerMapping

​ 指定以bean的id来作为url,来指定bean和url的映射关系。配置如下:

<!--此方式可以配置多个bean-->
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping" >
    <property name="mappings">
        <props>
            <prop key="/hello.action">helloController</prop>
        </props>
    </property>
</bean>
3.3 HandlerAdapter

​ 适配器:指定什么样的类可以作为处理器来处理请求。

1 SimpleControllerHandlerAdapter

​ 默认情况下,适配器是该类,用于指定实现了HttpRequestHandler接口的类是处理器。配置方式如下所示:

<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" />

符合要求的bean:

package com.zhiyou100.controller;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class HelloController implements Controller {

    @Override
    public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
        //成功来到了这里
        String name = httpServletRequest.getParameter("name");
        System.out.println(name+"成功来到了处理器!");
        ModelAndView modelAndView = new ModelAndView("success");
        modelAndView.addObject("message","你好啊!");
        return modelAndView;
    }
    
}

2 HttpRequestHandlerAdapter

​ 指定实现了HttpRequestHandler接口的类是处理器。配置方式如下。

<bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter" />

符合要求的bean如下所示:

package com.zhiyou100.controller;

import org.springframework.web.HttpRequestHandler;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class HelloController2 implements HttpRequestHandler {
    @Override
    public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("执行到了HelloController2的handleRequest");
        request.getRequestDispatcher("/WEB-INF/pages/success.jsp").forward(request,response);
        //注意重定向不能到web-info下
        //response.sendRedirect(request.getContextPath()+"/WEB-INF/pages/success.jsp");
    }
}
3.4 InternalResourceViewResolver

​ 视图解析器:主要用于封装数据到model,获取view对象,存在两个属性,prefix和suffix.

  • 如果没有设置,默认是"/",映射到真实路径。
  • 如果加上前缀了后缀,就会对返回的view的url的路径进行拼串。
  • 注意:不会对转发和重定向的地址进行拼串。
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/pages/" />
    <property name="suffix" value=".jsp" />
</bean>
3.5 转发和视图解析器

​ 如果我们自定义了视图解析器,并且定义了前缀和后缀,那么视图解析器会对我们的返回进行拼串,如果我们想要转发到其他处理器,我们就需要使用到转发标签和重定向标签。

  • return “forward:/hello”;
  • return “redirect:/hello”;

特殊的:转发和重定向的绝对路径都是当前项目下,web中重定向是当前服务器下。

4 注解的形式实现SpringMVC

4.1 配置DispatcherServlet

​ 在web.xml文件中进行配置

<!--1.配置前端控制器-->
<servlet>
    <servlet-name>DispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:springmvc.xml</param-value>
    </init-param>
</servlet>
<servlet-mapping>
    <servlet-name>DispatcherServlet</servlet-name>
    <url-pattern>*.aaa</url-pattern>
</servlet-mapping>
4.2 配置SpringMVC的配置文件

​ 配置包扫描,视图解析器,保险起见配置开启注解模式。

<!--1.配置包扫描-->
<context:component-scan base-package="com.zhiyou100" use-default-filters="false">
    <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

<!--2.配置视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/pages/" />
    <property name="suffix" value=".jsp" />
</bean>
<!--开启注解驱动:内部注册了很多个bean-->
<mvc:annotation-driven />
4.3 后台代码
package com.zhiyou100.controller;

import com.zhiyou100.pojo.Student;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/hello")
public class HelloController {
    @RequestMapping("/hello")
    public String hello(Integer id, Student student, Model model) {
        System.out.println(id+"经过努力走向人生巅峰!!!");
        System.out.println(student);
        System.out.println(model.getClass());
        return "success";
    }
}
4.4 前台测试代码
id: sid: sname: sage:
4.5 常见问题:

1 出现乱码问题

​ 配置filter进行编码的配置,此处不同的版本可能代码有所不同。

<!--设置编码集,优先于doDispatcher执行-->
<filter>
    <filter-name>CharacterEncodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
        <param-name>encoding</param-name>
        <param-value>utf-8</param-value>
    </init-param>
    <init-param>
        <param-name>forceResponseEncoding</param-name>
        <param-value>true</param-value>
    </init-param>
    <init-param>
        <param-name>forceRequestEncoding</param-name>
        <param-value>true</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>CharacterEncodingFilter</filter-name>
    <!--拦截所有请求,包含jsp,-->
    <url-pattern>/*</url-pattern>
</filter-mapping>

注:/和/*的区别

  1. 当配置<url-pattern>/</url-pattern>的时候,它会匹配到路径型的url,就不会匹配到模式为.jsp型的url

  2. 当配置<url-pattern><url-pattern>/*<url-pattern>的时候,它就会匹配到所有类型的url,包括路径型的,有各种后缀的等等。

5 Ajax和JSON

5.1 从后端获取json数据

后台代码:

@ResponseBody
@RequestMapping("/getOne")
public Student getOne(){
    Student student = new Student(1, "张三", 23);
    student.setBirth(new Date());
    System.out.println(student);
    return student;
}

前台代码:

$.ajax({
  url:"<c:url value='/hello/getOne'/>",
  type:"get",
  async:false,
  dataType:"json",
  success:function (data) {
    var s = JSON.stringify(data);
    $("#div_show").text(s);
      student=s;
  }
})

注:需要接受的类型是json,返回的是json对象。

5.2 json的前后端互传

前端代码:

$.ajax({
  url:"<c:url value='/hello/addOne'/>",
  type:"post",
  async:false,
  contentType:"application/json",
  data:student,
  dataType:"json",
  success:function (data) {
    $("#div_show1").text(JSON.stringify(data));
  }
})

要求:

  1. 写传输的内容类型: contentType:“application/json”。
  2. 传输的内容为:json字符串,而非是json对象,使用JSON.stringify(data),将json对象转化为json类型字符串。

后台代码:

@ResponseBody
@RequestMapping("/addOne")
public Student addOne(@RequestBody()Student student){
    System.out.println(student);
    student.setSname("王八");
    System.out.println(student);
    return student;
}

6 文件上传和下载

6.1 文件上传

1 导入依赖的pom文件

<!--文件上传下载的jar-->
<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.2</version>
</dependency>
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-io</artifactId>
    <version>1.3.2</version>
</dependency>

2 前端页面:

  • post请求
  • enctype
  • 上传输入框的type为file
<form enctype="multipart/form-data" method="post" action="<c:url value='/hello/uploadFile'/>">
  用户名:<input type="text" name="name" />
  照片:<input type="file" name="photo" />
  <input type="submit" value="上传" />
</form>

3 配置多路径解析器

id必须为:multipartResolver

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" />

4 后端代码进行接收

  • 可以在web.xml中参数来指定一个文件夹,专门来存储用户的图片信息。

    • <context-param>
          <param-name>filePath</param-name>
          <param-value>e:/file</param-value>
      </context-param>
      
@RequestMapping("/uploadFile")
public String uploadFile(String name, @RequestParam(value = "photo",required = false) CommonsMultipartFile file,
                         Map<String, String> map, HttpServletRequest request) throws IOException {
    if (!file.isEmpty()){
        System.out.println(name+"上传了文件:"+file.getOriginalFilename());
        String realPath = request.getRealPath("/");
        System.out.println(realPath);
        file.transferTo(new File(realPath+System.currentTimeMillis()
                +"_"+file.getOriginalFilename()));
        map.put("message","上传成功");
    }else {
        map.put("message","上传失败");
    }
    return "success";
}
6.2 文件下载

​ 文件下载:

@RequestMapping("/download")
public ResponseEntity<byte[]> download(String fileName,HttpServletRequest request) throws IOException {
    System.out.println(fileName);
    String realPath = request.getRealPath("/");
    //获取要下载的文件的位置
    File file = new File(realPath, fileName);
    FileInputStream fis = new FileInputStream(file);
    byte[] bytes = new byte[fis.available()];
    fis.read(bytes);
    String mimeType = request.getServletContext().getMimeType(fileName);
    //泛型指的是返回的响应体的内容的类型:可以自己定制我们需要的响应,在响应数据的时候也可以自定义响应头。
    MultiValueMap<String,String> headers=new HttpHeaders();
    //headers.add("Content-Disposition","attchement;filename="+new String(fileName.getBytes("utf-8"),"iso-8859-1"));
    headers.add("Content-Disposition","attchement;filename="+new String(fileName.getBytes("utf-8"),"iso-8859-1"));
    headers.add("Content-Type", mimeType);
    String body="<h1>success</h1>";
    return new ResponseEntity<byte[]>(bytes,headers, HttpStatus.OK);
}

7 拦截器

7.1 拦截器简单介绍

​ SpringMVC提供了拦截器机制,允许运行目标方法之前进行一些拦截工作或者目标方法运行之后进行一些操作。

  • javaweb:filter,过滤器。
  • SpringMVC:HandleInterceptor,拦截器。

接口为:HandlerInterceptor

image-20201030101409091

  • preHandle:在目标方法运行之前调用,返回值是boolean类型
    • return true:放行。
    • return false:不放行。
  • postHandle:目标方法运行之后调用。
  • afterCompletion:请求完成之后,来到目标页面之后。相当于chain.doFilter()放行之后,资源响应之后。
7.2 使用步骤

1 编写一个类实现接口:HandlerInterceptor

package com.zhiyou100.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 MyInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        System.out.println("preHandle");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle");
    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
        System.out.println("afterCompletion");
    }
}

2 在SpringMVC中注册这个组件

方式1:bean的方式

<!-- 配置拦截器 -->
<mvc:interceptors>
    <!-- 配置某个拦截器:默认情况下拦截所有的请求 -->
    <bean class="com.atguigu.interceptor.MyInterceptor"></bean>
</mvc:interceptors>

方式2:mvc的名称空间的方式

<!--配置一个拦截器-->
    <bean id="myInterceptor" class="com.zhiyou100.interceptor.MyInterceptor" />
    <mvc:interceptors>
        <mvc:interceptor>
            <!--表明拦截那些路径:
				/**:包含子集目录的所有内容
				/*:当前目录下的所有内容,不包含子集目录
			-->
            <mvc:mapping path="/hello/**"/>
            <!--引用之前定义的bean-->
            <ref bean="myInterceptor" />
            <!--注意拦截路径要在bean之前进行配置-->
            <!--<bean class="com.zhiyou100.interceptor.MyInterceptor" />-->
        </mvc:interceptor>
    </mvc:interceptors>

3 拦截器的运行流程:单拦截器的流程

preHandle
运行到了这里:test01
postHandle
afterCompletion

流程:拦截器preHandle–>目标方法–>拦截器postHandle–>拦截器afterCompletion。

细节:

  1. 只要preHandle不放行,则不会接着执行下去。
  2. 只要preHandle放行,当前拦截器的afterCompletion总会执行。

3 多拦截器的流程

<!-- 配置拦截器 -->
<mvc:interceptors>
    <!-- 配置某个拦截器:默认情况下拦截所有的请求 -->
    <bean class="com.atguigu.interceptor.MyInterceptor"></bean>
    <mvc:interceptor>
        <!-- 配置拦截哪种请求 -->
        <mvc:mapping path="/test01"/>
        <bean class="com.atguigu.interceptor.MyInterceptor2"></bean>
        <!-- <mvc:exclude-mapping path=""/> -->
    </mvc:interceptor>
</mvc:interceptors>

注:和filter一致,谁配置在前谁优先执行。

preHandle
222preHandle
运行到了这里:test01
222postHandle
postHandle
222afterCompletion
afterCompletion

特殊:

  1. 如果1放行,2不放行,已放行的拦截器的afterCompletion一定会执行。
  2. preHandle是按照顺序执行的。
  3. postHandle和afterCompletion逆序执行。

4 执行流程

FirstInterceptor#preHandle–>HandlerAdapter#handle–>FirstInterceptor#postHandle–>DispatcherServlet#render–>FirstInterceptor#afterCompletion

5 filter和拦截器的区别

  • 如何进行选择:

    • 如果你写的功能相对来说比较复杂,需要其他组件配合完成,我们就需要使用到拦截器。
    • 如果仅仅只是为了配置编码之类的比较简单的功能,使用flter即可。
  • 实现的接口不同:

    • filter实现的是filter接口
    • 过滤器实现的是HandlerInterceptor
  • 规范不同:

    • filter过滤器是Servlet规范中定义的,是servlet容器支持的。
    • 拦截器在spring容器中,是srping框架支持的。
  • 深度不同:

    • filter是回调函数的方式。
    • 拦截器是动态代理和反射。

8 异常

8.1 配置的方式

1 自定义异常类

package com.zhiyou100.exception;

public class MyException extends RuntimeException {
    public MyException(String msg){
        super(msg);
    }
}

2 自定义MyExceptionHandler,实现HandlerExceptionResolver接口

package com.zhiyou100.exceptionResolver;

import com.zhiyou100.exception.MyException;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;

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

public class MyExceptionHandler implements HandlerExceptionResolver {
    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
        System.out.println("==="+o+"===");
        if (e instanceof MyException){
            ModelAndView modelAndView = new ModelAndView("error");
            modelAndView.addObject("errorMsg",e.getMessage());
            modelAndView.addObject("errorCause",e.getCause());
            return modelAndView;
        }
        return null;
    }
}

3 springmvc的xml文件中进行配置

<bean class="com.zhiyou100.exceptionResolver.MyExceptionHandler" />
8.2 注解方式

1 解析异常

默认的几个HandlerExceptionResolver

image-20201030101626866

如果三个异常解析器都无法处理异常,就会抛出异常。

2 @ExceptionHandler

​ 这个注解就是告诉SpringMVC这个方法专门处理这个类出现的指定异常。

@ExceptionHandler(value= {ArithmeticException.class,NullPointerException.class})
public ModelAndView handleException01(Exception exception) {
    ModelAndView modelAndView = new ModelAndView("myerror");
    modelAndView.addObject("excep",exception);
    System.out.println("handleException01---");
    //也会被视图解析器进行拼串
    return modelAndView;
}

使用一个处理器进行测试:

@RequestMapping("/exceptionTest")
public String hello() {
    int i= 10/0;
    return "success";
}

运行结果:代码一旦运行会出现运算异常,会进入到异常处理方法。

image-20201030101643320

要点:

  1. 在方法上随便写一个Exception,用来接收发生的异常,也只能给参数位置上写Exception。
  2. 要携带的异常信息不能给参数位置上写model,参数位置上只认识异常exception,需要返回异常信息的时候,返回ModelAndView就行。
  3. 如果存在多个@ExceptionHandler都能处理这个异常,精确优先。
  4. 我们可以专门写一个类来处理所有的异常。
    1. 需要将该类加入到ioc容器中去。使用@ControllerAdvice,表明是一个专门处理异常的类。
    2. 将异常处理的方法写到这个类中即可。
      1. 如果本类中和全局的都存在异常处理信息,那么优先使用本类的,就算是全局的更加精确,依旧是本类的优先。
@ControllerAdvice
public class MyExceptionController {
    @ExceptionHandler(value= {Exception.class})
    public ModelAndView handleException01(Exception exception) {
        ModelAndView modelAndView = new ModelAndView("myerror");
        modelAndView.addObject("excep",exception);
        System.out.println("全局的:handleException01---");
        //也会被视图解析器进行拼串
        return modelAndView;
    }
}

3 @ResponseStatus

​ 在自定义异常上标注的。不能标注到方法上,否则肯定会进行报错,响应的状态码。

使用步骤

1)自定义异常类

package com.atguigu.controller;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;

@ResponseStatus(reason="用户拒绝访问",value=HttpStatus.NOT_ACCEPTABLE)
    public class MyException extends RuntimeException{
        public MyException() {
    }
}

2)使用

@RequestMapping("/exceptionTest2")
public String hello2(@RequestParam("username")String username) {
    if (!"admin".equals(username)) {
        System.out.println("出现了异常");
        throw new MyException();
    }
    System.out.println("登陆成功");
    return "success";
}

3)结果测试

image-20201030101825919

注意:如果存在我们使用的@ExceptionHandler修饰的异常的方法,或者全局异常处理类,会导致该异常被拦截,会被这些异常解析器被处理。

4 DefaultHandlerExceptionResolver

​ 多个异常解析器轮流进行解析。如果前两个异常解析器都不能解析,那么默认异常解析器就会进行解析。存在很多的if–else if来判断可不可以进行解析。

9 总结–SpringMVC运行流程

image-20201030101852195

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SSrDK7mi-1604024798011)(image/Tim截图20200819203846.png)]

流程图解:

image-20201030101913466

参考文献:

  1. https://blog.csdn.net/litianxiang_kaola/article/details/79169148
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值