SpringMVC

什么是MVC

MVC是模型(Model)、视图(View)、控制器(Controller)的简写,是一种软件设计规范,是将业务逻辑、数据、显示分离的方法来组织代码。
MVC主要作用是降低了视图与业务逻辑间的双向偶合。
MVC不是一种设计模式,MVC是一种架构模式。

①Model(模型):数据模型,提供要展示的数据,因此包含数据和行为,可以认为是领域模型或JavaBean组件(包含数据和行为),不过现在一般都分离开来:Value Object(数据Dao) 和 服务层(行为Service)。也就是该模型提供了模型数据查询和模型数据的状态更新等功能,包括数据和业务。
② View(视图):负责进行模型的展示,一般就是我们见到的用户界面,客户想看到的东西。
③ Controller(控制器):接收用户请求,委托给模型进行处理(状态改变),处理完毕后把返回的模型数据返回给视图,由视图负责展示。

什么是SpringMVC

SpringMVC是一种基于Java的实现MVC设计模型的请求驱动类型的轻量级Web框架,属于Spring FrameWork的后续产品,已经融合在Spring Web Flow里面。Spring框架提供了构建Web应用程序的全功能MVC模块,使用Spring可插入的MVC架构,从而在使用Spring进行WEB开发时,可以选择使用Spring的SpringMVC框架或集成其他MVC开发框架,如Struts2等。
它通过一套注解,让一个简单的Java类成为处理请求的控制器,而无需实现任何接口。同时它还支持RESTful编程风格。

优势

  1. 清晰的角色划分
  • 前端控制器
  • 处理器映射器
  • 视图解析器
  • 处理器或页面控制器
  • 验证器
  • 命令对象
  • 表单对象
  1. 分工明确
  2. 和Spring其他框架无缝衔接。
  3. 可适配,通过HandlerAdapter可以支持任意的类作为处理器
  4. 可定制性,HandlerMapping、ViewResoler等能够非常简单的定制等

各种组件

前端控制器

web.xml中配置

		   <!--配置SpringMVC的前端控制器-->
		   <servlet>
           <servlet-name>springmvc</servlet-name>
           <servlet-class>org...DispatcherServlet</servlet-class>
           <init-param>
               <param-name>contextConfigLocation</param-name>
               <param-value>classpath:springmvc.xml</param-value>
           </init-param>
           <!--1.当取值为整数时,表示Servlet的加载顺序,数字越小,越先加载。
               当取值为负数时,表示该Servlet不会在容器启动时自动加载,而是在第一次请求时才会被加载。
             2.当取值为布尔值时,true表示在容器启动时自动加载,false表示不自动加载,等到第一次请求时再加载。
               如果没有指定load-on-startup或者取值为负数,则默认在第一次请求时加载Servlet。
            -->
           <load-on-startup>1</load-on-startup>
       </servlet>
       <!--
        '/'不会拦截 .jsp(tomcat中有一个JspServlet,这个会拦截.jsp文件),但是会拦截静态资源。
        '/*'会拦截所有资源
        全路径    /service/*.do  请求必须以/service开头 并且以.do结尾
	    后缀型路径: *.do          要求以.do结尾的请求
	    前缀型路径: /service/*    拦截以service开头的请求
        -->
       <servlet-mapping>
           <servlet-name>springmvc</servlet-name>
           <url-pattern>/</url-pattern>
       </servlet-mapping>

视图解析器

springmvc配置文件中

<!--开启视图解析器-->
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--前缀-->
        <property name="prefix" value="/pages/"></property>
        <!--后缀-->
        <property name="suffix" value=".jsp"></property>
    </bean>

编码过滤器

在post请求方式中,会出现中文乱码问题,这时候我们就需要在web.xml中配置编码过滤器

		 <!--配置编码过滤器-->
         <filter>
             <filter-name>characterEncoding</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>forceEncoding</param-name>
                 <param-value>true</param-value>
             </init-param>
         </filter>
         <filter-mapping>
             <filter-name>characterEncoding</filter-name>
             <url-pattern>/*</url-pattern>
         </filter-mapping>

需要注意的是
我们WEB应用里面有静态资源,比如js css image等,我们不能把静态资源也过滤了,否则会造成静态资源不能正常加载的问题。所以在配置编码过滤器的时候。我们需要在Springmvc配置文件中设置静态资源不过滤。

<!-- location 表示路径,mapping 表示文件,**表示该目录下的文件以及子目录的文件 -->
<mvc:resources location="/css/" mapping="/css/**"/>
<mvc:resources location="/images/" mapping="/images/**"/>
<mvc:resources location="/scripts/" mapping="/javascript/**"/>

拦截器

拦截器实现步骤:

  1. 自定义一个类并实现HandlerInterceptor接口
  2. 重写默认方法preHandle() postHandle() afterCompletion()
  3. springmvc.xml配置文件中,配置拦截器

细节

  1. 各方法执行时机:
    preHandle():控制器方法执行前执行,返回值为boolean类型,true:放行,false:不放行
    postHandle():控制器方法执行后执行
    afterCompletion():视图渲染后执行

  2. 当存在多个拦截器时,其中有一个拦截器返回false后,执行流程是:
    在这里插入图片描述

springmvc配置文件中

	    <!--配置多个拦截器 顺序:谁先配置谁先执行-->
        <mvc:interceptors>
            <mvc:interceptor>
                <!--表示拦截 /interceptor 路径下的所有访问资源-->
                <mvc:mapping path="/interceptor/*"/>
                <bean class="com.herdgod.interceptor.MyInterceptor"/>
            </mvc:interceptor>
            <!--配置单个拦截器-->
            <mvc:interceptor>
                <!--配置拦截的路径/方法-->
                <mvc:mapping path="/interceptor/*"/>
                <!--排除不需要拦截的路径/方法-->
                <mvc:exclude-mapping path="/interceptor/testInterceptor1"/>
                <!--注入自定义拦截器的bean,也可以通过ref引入外部bean方式-->
                <bean class="com.herdgod.interceptor.MyInterceptor1"></bean>
            </mvc:interceptor>
        </mvc:interceptors>

类型转换器

在SpringMVC中已经封装了很多的类型的转换器,比如String转Integer,但是对于日期类型SpringMVC无法自动转换。需要自定义类型转换器。
实现:

  1. 自定义类实现Converter<S, T>接口,表示S类型----->T类型
    S:源对象数据类型,T:转换后对象的数据类型;
  2. springmvc配置文件中,配置类型转换器工厂
  3. 开启springmvc支持类型转换的服务

比如String类型转Date类型

public class StringToDateConverter implements Converter<String, Date> {
    @Override
    public Date convert(String source) {

        if (StringUtils.isEmpty(source)){
            throw new NullPointerException("请输入要转换的日期");
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date date = null;
        try {
            date = sdf.parse(source);
        } catch (ParseException e) {
            throw new RuntimeException("输入日期有误");
        }
        return date;
    }
}

springmvc.xml配置文件中

    <!-- 配置类型转换器工厂 -->
    <bean id="converterService"
          class="org.springframework.context.support.ConversionServiceFactoryBean">
        <!-- 给工厂注入一个新的类型转换器 -->
        <property name="converters">
            <array>
                <!-- 配置自定义类型转换器 -->
                <bean class="com.herdgod.converter.StringToDateConverter"></bean>
            </array>
<!--            <set>-->
<!--                <bean class="com.herdgod.converter.StringToDateConverter"></bean>-->
<!--            </set>-->
        </property>
    </bean>

	<!--开启springmvc注解支持 并开启类型转换的服务-->
    <mvc:annotation-driven conversion-service="converterService"/>

常用注解

@RequestMapping

在类上使用时,表示一级访问目录,不写相当于应用的根目录,写的话需要以/开头
在方法上使用时:表示二级访问目录,/可以省略
作用:用来映射资源的请求路径
属性:
value/path: 描述资源路径的名称,只写这一个属性的情况下,可以省略
method: 请求当前控制器方法需要什么请求方法
params: 请求必须指定携带的参数名称,也可以指定参数的值
heads: 请求必须携带指定的请求头

@RequestParam

作用:把请求中指定名称的参数给控制器中的形参赋值
属性:
value: 用于绑定前端提交的数据和后端参数不一致的情况
required: 前端提交的参数是否是必须,默认为true
defaultValue: 描述请求参数携带的默认值,如果不传递值,则采用默认值代替

	@RequestMapping("literal3")
    public String Literal3(@RequestParam("username") String name, Integer age){
        System.out.println(name+ " " + age);
        return "success";
    }

@PathVaribale

作用:用于绑定url中的占位符。例如:请求url中 /delete/{id},这个{id}就是占位符。url支持占位符是spring3.0之后加入的。是springmvc支持rest风格URL的重要标志。
属性:
value:用于指定url中占位符名称
required:是否必须提供占位符

	/**
     * @PathVariable注解
     */
    @RequestMapping(value = "pathVariable/{id}")
    public String getPathVariable(@PathVariable("id")Integer id){
        System.out.println(id);
        return "success";
    }

@RequestHeader

作用:用户获取请求头(不怎么使用)
属性:
value:提供消息头名称
required:是否必须有此消息头

	/**
     * @RequestHeader注解
     * 一般不怎么使用
     */
    @RequestMapping(value = "requestHeader")
    public String getRequestHeader(@RequestHeader(value = "Accept-Language",required = false)String requestHeader){
        System.out.println(requestHeader);
        return "success";
    }

@CookieValue

作用:用于把指定的cookie名称的值传入控制器方法参数
属性:
value:指定cookie的名称
required:是否必须有此cookie

	 /**
     * @CookieValue 注解
     */
    @RequestMapping(value = "cookieValue")
    public String getCookieValue(@CookieValue(value = "JSESSIONID",required = false)String cookieValue){
        System.out.println(cookieValue);
        return "success";
    }

@ModelAttribute

作用:修饰方法和参数
出现在方法上,表示当前方法会在控制器方法执行之前,先执行
出现在参数上,获取指定的数据给参数赋值
属性:
value/name:用于获取数据的key。key可以是POJO的属性名称,也可以是map结构的key
应用场景:当表单提交的数据不是一个完整的实体类数据时,保证没有提交数据的字段使用数据库对象原来的数据

	@ModelAttribute
    public void showModel(){
        System.out.println("showModel方法执行了");
    }

    @RequestMapping("show")
    public String showUser(){
        System.out.println("show方法执行了");
        return "success";
    }

@SessionAttribute

作用:
只能作用于类上,用于多次执行控制器方法间的参数共享
属性:
value:用于指定存入的属性名称
type:用于指定存入的数据类型

<a href="${pageContext.request.contextPath}/springmvc/putMethod">[SessionAttributes注解,存入]</a>
<br><a href="${pageContext.request.contextPath}/springmvc/getMethod">[SessionAttributes注解,取出]</a>
<br><a href="${pageContext.request.contextPath}/springmvc/removeMethod">[SessionAttributes注解,清除]</a>
@Controller
@RequestMapping("/springmvc")
@SessionAttributes(value = {"username","age","money"},types = {String.class, Integer.class, Double.class})//只能作用于类上
public class SessionAttributeController {
	//存
    @RequestMapping("putMethod")
    public String putMethod(Model model){
        model.addAttribute("username","张三");
        model.addAttribute("age",18);
        model.addAttribute("money",19.0);
        return "success";
    }
    //取
    @RequestMapping("getMethod")
    public String getMethod(ModelMap model){
        String username = (String)model.get("username");
        Integer age = (Integer) model.get("age");
        Double money = (Double) model.get("money");
        System.out.println(username+ " "+ age + " " +money);
        return "success";
    }
	//清除
    @RequestMapping("removeMethod")
    public String removeMethod(SessionStatus sessionStatus){
        sessionStatus.setComplete();
        return "success";
    }
}

@MatrixVariable

作用:接收矩阵变量
前提:在springmvc的配置文件中开启矩阵变量的使用权限

<mvc:annotation-driven enable-matrix-variables="true"/>

测试:

<a href="${pageContext.request.contextPath}/d/testMatrixVariables/1;name=eric;ages=18,19,20">测试矩阵变量</a>

@ResponseBody

作用:该注解用于将 Controller 的方法返回的对象,通过合适的转换器转换为指定格式的数据,如:json,xml 等,通过 Response对象的body区响应给客户端。
注意:使用这个注解后不会走视图解析器,而是直接将数据写入到输出中,效果等同于response对象输出指定格式的数据
引入依赖:

<!-- 对象转json格式-->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.14.2</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.14.2</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.14.2</version>
        </dependency>

控制器方法:

	@RequestMapping("testAjax")
    @ResponseBody
    public User testAjax(User user){
        System.out.println("testAjax 方法执行了......");
        //模拟从数据可能查询的数据
        user.setId(1001);
        user.setName("eric");
        user.setMoney(888.8);
        return user;
    }
   //前台拿到的数据:{"id":1001,"name":"eric","money":888.8}

	//@RequestBody请求来的user,@ResponseBody响应给浏览器
    @RequestMapping("testAjax02")
    public @ResponseBody User testAjax02(@RequestBody User user){
        System.out.println("testAjax02 方法执行了......");
        System.out.println(user);//@Request请求来的user User(id=1, name=test, money=999.0)
        user.setId(1001);
        user.setName("eric");
        user.setMoney(888.8);
        return user;//@ResponseBody响应给浏览器
    }

在这里插入图片描述

参数绑定

字面量数据类型绑定

参数名称必须和控制器中的方法形参的名称完全一致。如果不一致需要使用@RequestParam注解进行绑定

	//参数名称必须和控制器中的方法形参的名称一致
	@RequestMapping("literal")
    public String Literal(String username,Integer age){
        System.out.println(username+ " " + age);
        return "success";
    }
    
	//不一致需要使用@RequestParam注解进行数据绑定
	@RequestMapping("literal3")
    public String Literal3(@RequestParam("username") String name,Integer age){
        System.out.println(name+ " " + age);
        return "success";
    }

pojo类型

前端页面

<form action="${pageContext.request.contextPath}/parameter/pojo" method="post">
    <input type="text" name="name">
    <input type="text" name="age">
    <input type="text" name="money">
    <input type="submit" value="pojo类型">
</form>

实体类

public class Account {
    private  String name;
    private Integer age;
    private Double money;
    //get set方法
}

控制器controller

    @RequestMapping(value = "pojo",method = RequestMethod.POST)
    public String pojo(Account account){
        System.out.println(account);
        return "success";
    }

使用 ServletAPI 传递参数

SpringMVC还支持使用原始的Servlet对象作为控制器方法的参数。支持原始ServletAPI对象有:

HttpServletRequest、HttpServletResponse、HttpSession、InputStream、OutputStream、Reader、Writer等

	@RequestMapping("servletParams")
    public String getServletParams(HttpServletRequest request, HttpServletResponse response) {
        String username = request.getParameter("username");
        String age = request.getParameter("age");
        Integer integer = Integer.valueOf(age);
        System.out.println(username + " " + integer);
        return "success";
    }

请求参数乱码问题

  • POST 请求方式解决乱码问题
    在 web.xml 里面设置编码过滤器,上面已讲述,这里不再赘述
  • GET请求方式解决乱码问题
    tomcat 对 GET 和 POST 请求处理方式是不同的,GET 请求的编码问题,要改 tomcat 的server.xml 配置文件,如下:
<Connector port="8080" protocol="HTTP/1.1"
 connectionTimeout="20000"
 redirectPort="8443" useBodyEncodingForURI="true"/>

如果遇到 ajax 请求仍然乱码,把:useBodyEncodingForURI="true"改为 URIEncoding="UTF-8"即可

请求参数类型无法自动转换问题

比如:我们前台传递的是字符串类型的参数,但是后台使用的是 Date 类型接收的。Springmvc是无法自动做到String类型—>Date类型转换。
我们需要自定义类型转换器,上文已讲述,不在赘述。

响应数据和结果视图

返回值分类

返回字符串

controller 方法返回字符串可以指定逻辑视图名,通过视图解析器解析为物理视图地址,本质是请求转发。这种方式我们一直在使用。
我们也通过 请求转发或者重定向 完成页面跳转
转发:既可以转发到某个页面,也可以转发到其他的控制器方法

  //转发到具体的页面,forward后面的 / 必须要写!!
  @RequestMapping("testForward")
    public String testForward(){
        return "forward:/pages/success.jsp";
    }
	
	//转发到其他控制器方法
    @RequestMapping("testForwardOne")
    public String testForwardOne(){
        return "forward:testModelAndView";
    }

重定向:既可以转发到某个页面,也可以转发到其他的控制器方法

	//重定向,redirect:后面的 / 是一定要写的!!! 404
    @RequestMapping("testRedirect")
    public String testRedirect(){
        return "redirect:/pages/success.jsp";
    }
	//重定向到其他控制器方法
    @RequestMapping("testRedirectOne")
    public String testRedirectOne(){
        return "redirect:testModelAndView";
    }

返回为void

原始Servlet API 可以作为控制器中方法的参数,所以在controller 方法形参上可以定义 request 和 response,使用 request 或 response 指定

	//返回值是void,请求转发
    @RequestMapping("testVoidDispatcher")
    public void testVoidDispatcher(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.getRequestDispatcher("/pages/success.jsp").forward(request,response);
    }

    //返回值是void,重定向
    @RequestMapping("testVoidRedirect")
    public void testVoidRedirect(HttpServletResponse response) throws ServletException, IOException {
        response.sendRedirect("/pages/success.jsp");
    }

返回值是ModelAndView

ModelAndView 是 SpringMVC 为我们提供的一个对象,该对象也可以用作控制器方法的返回值

    //本质是请求转发
    @RequestMapping("testModelAndView")
    public ModelAndView testModelAndView(){
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("username","eric");
        //设置返回视图
        modelAndView.setViewName("success");
        return modelAndView;
    }

SpringMVC作用域传值

使用原生Request域对象传值

//使用原生域对象传值
    @RequestMapping("testRequest")
    public void testRequest(HttpServletRequest req,HttpServletResponse res) throws ServletException, IOException {
        req.setAttribute("name","张三");
        req.getRequestDispatcher("/pages/success.jsp").forward(req,res);
    }

    @RequestMapping("testSession")
    public void testSession(HttpServletRequest req,HttpServletResponse res) throws ServletException, IOException {
        HttpSession session = req.getSession();
        session.setAttribute("age",18);
        req.getRequestDispatcher("/pages/success.jsp").forward(req,res);
    }

使用map传值

	//使用map传值
    @RequestMapping("testMap")
    public String testMap(Map<String,Object> map){
        map.put("gender","男");
        map.put("tel",10086);
        return "success";
    }

使用Model对象传值

	//使用 Model对象传值
    @RequestMapping("testModel")
    public String testModel(Model model){
        model.addAttribute("address","美国");
        model.addAttribute("score",19);
        return "success";
    }

使用ModelAndView传值

	//使用 ModelAndView 对象传值
    @RequestMapping("testModelAndView1")
    public ModelAndView testModelAndView1(){
        ModelAndView model = new ModelAndView();
        model.addObject("u","中国");
        model.setViewName("success");
        return model;
    }

总结:
取值:${xxx}
不论是通过哪种方式(Map、Model、request ModelAndView)都是向request域中放数据。

文件上传

引入依赖

<dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.5</version>
        </dependency>
        
       <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.7</version>
        </dependency>

传统方式进行文件上传

  1. 编写文件上传jsp页面
    enctype="multipart/form-data" 是文件上传表单必须要加的一个属性,标识当前表单是一个文件上传的表单
<form action="${pageContext.request.contextPath}/upload" method="post" enctype="multipart/form-data">
    文件上传:<input type="file" name="imgFile"><br/>
    <input type="submit" value="上传">
</form>
  1. 编写文件上传的servlet代码
@WebServlet("/upload")
public class FileUploadServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse resp) {
        List<FileItem> fileItems = null;
        try {
            //创建磁盘文件项工厂
            DiskFileItemFactory factory = new DiskFileItemFactory();
            //根据磁盘文件项工厂创建文件上传对象
            ServletFileUpload fileUpload = new ServletFileUpload(factory);
            //如果存在,就准备解析 request 作用域里面上传的数据
            fileItems = fileUpload.parseRequest(request);
            // 遍历
            for (FileItem fileItem : fileItems) {
                if (fileItem.isFormField()) {
                    //普通表单项
                } else {
                    //获取文件上传的文件名称
                    String name = fileItem.getName();
                    //上传文件地址
                    File file = new File("F:\\Java", name);
                    fileItem.write(file);
                    //删除临时文件
                    fileItem.delete();
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
        doPost(req, resp);
    }
}

springmvc方式进行文件上传

引入依赖:略

  1. 编写文件上传jsp页面
<%--enctype="multipart/form-data" 是文件上传表单必须要加的一个属性,标识当前表单是一个文件上传的表单--%>
<form action="${pageContext.request.contextPath}/upload/upload" method="post" enctype="multipart/form-data">
    文件上传1:<input type="file" name="imgFile"><br/>
    文件上传2:<input type="file" name="imgFile"><br/>
    <input type="submit" value="上传">
</form>
  1. 编写文件上传contoller的代码
@Controller
@RequestMapping("/upload")
public class FileUploadController {
    /**
     * 注意此处 MultipartFile imgFile参数名称不能乱写!!!!
     * 和前台的name属性值一致,例如:文件上传:<input type="file" name="imgFile"><br/>
	 */
      
    //单个文件上传
    /*@RequestMapping("/upload")
    public String fileUpload(MultipartFile imgFile) throws IOException {
        String filename = imgFile.getOriginalFilename();
        System.out.println(filename); //20230316105837.jpg
        File file = new File("F:\\Java",filename);
        imgFile.transferTo(file);
        return "success";
    }*/

    //多文件上传
    @RequestMapping("/upload")
    public String fileUpload(@RequestParam("imgFile") MultipartFile[] imgFiles) throws IOException {
        for (MultipartFile imgFile : imgFiles) {
            String filename = imgFile.getOriginalFilename();
            //文件输出的位置(路径)
            File file = new File("F:\\Java",filename);
            imgFile.transferTo(file);
        }
        return "success";
    }
}

异常处理

用户请求服务器时,不论是客户端还是服务端错误,亦或是其他错误时,我们都需要给用户一个提示信息,增强用户体验感。
异常处理的方式:

传统Servlet方式

在web.xml中配置以下信息:

         <error-page>
         	 <!--错误码-->
             <error-code>404</error-code>
             <!--出现此类错误时,跳转的页面-->
             <location>/errors/404.jsp</location>
         </error-page>
         <error-page>
             <error-code>500</error-code>
             <location>/errors/500.jsp</location>
         </error-page>
         <!--.......-->

SpringMVC方式

  1. 在出现异常的类使用@ExceptionHandler注解标注一个方法上
    局限性:单一,不够灵活,与核心业务耦合在一起,不方便后期维护
    属性:value用来指定出现异常的类型,例如(value = ArithmeticException.class)
	@ExceptionHandler(value = ArithmeticException.class)
    public ModelAndView testExceptionHandler(Exception e){
        ModelAndView mv = new ModelAndView();
        mv.addObject("msg",e.toString());
        mv.setViewName("error");
        return mv;
    }
  1. 自定义异常类

方法一

1.@ControllerAdvice作用于类上,将类标识为一个异常处理类
2.@ExceptionHandler作用于方法上,value属性指定异常的类型单个处理,例如(value = ArithmeticException.class),
或者 使用更加广泛的异常value=Exception.class统一处理

@ControllerAdvice //将类标识为一个异常处理类
public class HandlerException {

    /**
     * 1.@ExceptionHandler 单个处理
     */
//    @ExceptionHandler(value = ArithmeticException.class)
//    public ModelAndView testExceptionHandler(Exception e){
//        ModelAndView mv = new ModelAndView();
//        mv.addObject("msg",e.toString());
//        mv.setViewName("error");
//        return mv;
//    }
//
//    @ExceptionHandler(value = ArrayIndexOutOfBoundsException.class)
//    public ModelAndView testExceptionHandler1(Exception e){
//        ModelAndView mv = new ModelAndView();
//        mv.addObject("msg",e.toString());
//        mv.setViewName("/error");
//        return mv;
//    }

    /**
     * 2.@ExceptionHandler 统一处理,更广泛的异常
     */
    @ExceptionHandler(value = Exception.class)
    public ModelAndView handlerException(Exception ex){
        ModelAndView mv = new ModelAndView();
        mv.addObject("msg",ex.toString());
        mv.setViewName("error");
        return mv;
    }


}

方法二

1.继承RuntimeException
2.使用@ResponseStatus作用在类上
属性:
code/value = HttpStatus.BAD_GATEWAY,枚举类型,错误的状态码(404/500等)
reason = “” String类型,错误的原因

@ResponseStatus(code = HttpStatus.BAD_GATEWAY,reason = "参数id不能为负数!")
public class CustomizeException extends RuntimeException{
}

方法三

1.使用@Component注解,交给容器管理
2.实现 HandlerExceptionResolver 接口,重写方法

@Component
public class MyExceptionResolver implements HandlerExceptionResolver {

    /**
     * @param request 当前请求的HttpServletRequest对象
     * @param response 当前请求的HttpServletResponse对象
     * @param handler 处理当前请求的处理器对象
     * @param ex 处理器执行过程中抛出的异常对象。该参数为异常信息对象,包含异常类型、异常信息和异常堆栈轨迹等信息
     * @return
     */
    @Override
    public ModelAndView resolveException(HttpServletRequest request,
                                         HttpServletResponse response,
                                         Object handler, Exception ex) {
        ModelAndView mv  = new ModelAndView();
        mv.addObject("msg",ex.toString());
        mv.setViewName("/error");
        return mv;
    }
}

springmvc的执行流程
1.用户通过浏览器发起 HttpRequest 请求到前端控制器(DispatcherServlet)。
2.DispatcherServlet 将用户请求发送给处理器映射器(HandlerMapping)。
3.处理器映射器(HandlerMapping)会根据请求,找到负责处理该请求的处理器,并将其封装为外理器执行链 返回(HandlerExecutionChain) 给 DispatcherServlet
4.DispatcherServlet 会根据 处理器执行链 中的处理器,找到能够执行该处理器的处理器适配器(HandlerAdaptor) --注,处理器适配器有多个
5.处理器适配器(HandlerAdaptoer) 会调用对应的具体的 Controller 也就是Handler
6.Controller 将处理结果及要跳转的视图封装到一个对象 ModelAndView 中并将其返回给处理器适配器(HandlerAdaptor)
7.HandlerAdaptor 直接将 ModelAndView 交给 DispatcherServlet,至此,业务处理完毕
8.业务处理完毕后,我们需要将处理结果展示给用户。于是DisptcherServlet 调用 ViewResolver,将 ModelAndView 中的视图名称封装为视图对象
9.ViewResolver 将封装好的视图 (View) 对象返回给 DIspatcherServlet
10.DispatcherServlet 调用视图对象,让其自己(View) 进行染 (将模型数据填充至视图中),形成响应对象(HttpResponse)
11.前端控制器(DispatcherServlet) 响应(HttpResponse) 给浏览器,展示在页面上。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值