横扫盲区:Spring MVC,图文结合,思路超清晰(附思维脑图)

 

一文讲透Spring MVC,图文结合,思路超清晰(附XMind脑图)

MVC基础知识与应用

MVC体系结构

三层架构

在B / S架构中,系统标准的三层架构为:表现层 、业务层、持久层。三层架构中,每一层各司其职,共同协作实现对功能的支持与实现。

  • 表现层
  • 业务层
  • 持久层

MVC设计模式

MVC全称是Model View Controller,就是模型 - 视图 - 控制器的缩写。是一种用于设计Web应用程序表现层的模式。

  • Model(模型):模型包含了数据模型和业务模型,数据模型用于封装数据,业务模型用于处理业务。
  • View(View ):通常指的是jsp或者html。用于展示数据。
  • Controller(Controller):负责应用程序与客户端交互的核心入口。基本只负责接受请求和响应。

Spring MVC简介

​ Spring MVC全称是Spring Web MVC,是基于Java的实现MVC设计模式的请求驱动类型的轻量级Web框架,属于Spring FrameWork的后续产品。

​ Spring MVC已经成为目前最流行的MVC框架之一,并且随着Spring3.0的发布,全面超过Struts2成为最优秀的MVC框架。

​ servlet / struts开发需要实现接口,Spring MVC可以实现接口Controller,也提供了注解方式,只需要一个注解就可以(简便开发)。Spring MVC提供一整套注解,让一个简单的Java类成为处理请求的控制器,不需要实现任何接口。并且对Restful编程风格提供了支持。

本质 Spring MVC其实就是对Servlet的封装,简化了我们Servlet的开发。

一文讲透Spring MVC,图文结合,思路超清晰(附XMind脑图)

开发流程

  • web.xml配置DispatcherServlet前端控制器
<!--配置spring mvn核心Servlet-->  <servlet>    <servlet-name>dispatcherServlet</servlet-name>    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>  </servlet>  <!--配置servlet拦截规则-->  <!--    url-pattern规则:      方式一:后缀拦截如:.action / .do 这种方式比较精确、方便,无论以前还是现在企业中都有比较大的使用比例      方式二:/* 拦截所有,包括jsp,这样不好,如果这样所有的跳转都需要经过handler处理器,有的静态资源不需要这样处理(不推荐)      方式三:/ 不会拦截.jsp 但是会拦截.html / .css / .js / .jpg / .png等静态资源        为什么配置url-pattern / 会拦截静态资源??          在tomcat容器中也有一个web.xml(父配置文件),我们的项目中也有一个web.xml(子配置文件),          我们项目的web.xml继承了tomcat的web.xml,tomcat的web.xml有一个DefaultServlet 、 url-pattern是 /          那么我们项目的web.xml也配置了一个 url-pattern / ,覆盖了tomcat的web配置        为什么不会拦截 .jsp呢???          在tomcat的web.xml中,有一个JspServlet,这个servlet配置拦截.jsp,而此时我们没有覆盖这个url-pattern          所以对于jsp的拦截交给了tomcat,而springMVC不拦截        如何解决静态资源被拦截的问题??? 看springMVC  -->  <servlet-mapping>    <servlet-name>dispatcherServlet</servlet-name>    <url-pattern>/</url-pattern>  </servlet-mapping>
  • 开发具体的处理业务逻辑Handler(@Controller / @RequestMapper)
@Controller@RequestMapping(value = "/demo")public class DemoController {    /**     * SpringMVC 项目配置(三大核心组件):     *      1)配置前端控制器:org.springframework.web.servlet.DispatcherServlet(核心)     *   <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>/</url-pattern>     *   </servlet-mapping>     *      2)配置配置视图处理器:     *          <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">     *              <property name="prefix" value="/WEB-INF/jsp/" />     *              <property name="suffix" value=".jsp" />     *          </bean>     *      3)配置映射处理器(不指定,将自动匹配合适的映射处理器):     *          <mvc:annotation-driven />     */    /**     * 数据返回方式一:model和view封装到对象中     * ModelAndView对象内部包含了:ModelMap 和 Object view两个属性,分别用于封装Model数据模型和View视图     * @return     */    @RequestMapping(value = "/handler01")    public ModelAndView handler01() {        LocalDateTime now = LocalDateTime.now();        // 封装了Model和View视图        ModelAndView modelAndView = new ModelAndView();        // 封装返回结果到Model中        modelAndView.addObject("date", now);        // 设置返回的视图名称        modelAndView.setViewName("success");        return modelAndView;    }    /**     * 探究ModelMap / Model / Map之间的关系,为什么可以将数据存储到域并且被视图解析器读取到???     *      class ModelMap extends LinkedHashMap  继承了LinkedHashMap,LinkedHashMap又实现了Map接口     *      interface Model  只是一个接口     *      interface Map    只是一个接口     *     *      ModelMap / Model / Map 在SpringMVC注入的时候打印的都是org.springframework.validation.support.BindingAwareModelMap对象     *      探究 BindingAwareModelMap     *          class BindingAwareModelMap extends ExtendedModelMap     *              class ExtendedModelMap extends ModelMap implements Model     *     *      探究结果:BindingAwareModelMap继承了ModelMap类,实现了Model接口,最终封装数据的是BindingAwareModelMap     *     */    /**     * 数据返回方式二:view视图路径直接return,使用ModelMap封装数据     *      ModelMap对象:org.springframework.validation.support.BindingAwareModelMap     * @param modelMap     * @return     */    @RequestMapping(value = "/handler11")    public String handler11(ModelMap modelMap) {        LocalDateTime now = LocalDateTime.now();        modelMap.addAttribute("date",now);        System.out.println("--------------" + modelMap.getClass());        return "success";    }    /**     * 数据返回方式三:view视图路径直接return,使用Model封装数据     *      Model对象:org.springframework.validation.support.BindingAwareModelMap     * @param model     * @return     */    @RequestMapping(value = "/handler12")    public String handler12(Model model) {        LocalDateTime now = LocalDateTime.now();        model.addAttribute("date",now);        System.out.println("--------------" + model.getClass());        return "success";    }    /**     * 数据返回方式四:view视图路径直接return,使用Map封装数据     *      Map对象:org.springframework.validation.support.BindingAwareModelMap     * @param map     * @return     */    @RequestMapping(value = "/handler13")    public String handler13(Map map) {        LocalDateTime now = LocalDateTime.now();        map.put("date",now);        System.out.println("--------------" + map.getClass());        return "success";    }    /**     * BindingAwareModelMap也可以封装数据,因为最终Spring就是通过这个对象将数据放入域中     * @param bindingAwareModelMap     * @return     */    @RequestMapping(value = "/handler14")    public String handler14(BindingAwareModelMap bindingAwareModelMap) {        LocalDateTime now = LocalDateTime.now();        bindingAwareModelMap.put("date",now);        System.out.println("--------------" + bindingAwareModelMap.getClass());        return "success";    }}
  • springmvc.xml配置注解扫描、配置InternalResourceViewResolver视图解析器、<mvc:annotation-driven />映射处理器
	<!--配置启动注解扫描-->    <context:component-scan base-package="com.zhichunqiu.controller" />    <!--配置sprign mvc的视图解析器-->    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">        <!--配置视图的前后缀-->        <property name="prefix" value="/WEB-INF/jsp/" />        <property name="suffix" value=".jsp" />    </bean>    <!--配置spring mvc的映射处理器-->    <mvc:annotation-driven />
  • 在web.xml的DispatcherServlet中配置springmvc.xml路径
  <!--配置spring mvn核心Servlet-->  <servlet>    <servlet-name>dispatcherServlet</servlet-name>    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>    <init-param>      <!--配置springmvc的配置文件-->      <param-name>contextConfigLocation</param-name>      <param-value>classpath:springmvc.xml</param-value>    </init-param>  </servlet>

Spring MVC请求处理流程

一文讲透Spring MVC,图文结合,思路超清晰(附XMind脑图)

流程说明

  • 1)用户发送请求到前端控制器DispatcherServlet
  • 2)DispatcherServlet接受到用户发起的请求后调用HandlerMapping映射处理器
  • 3)映射处理器根据请求的url找到具体的Handler(后端控制器),生成处理器对象以及处理器拦截器(有就生成)并将Handler返回给DispatcherServlet
  • 4)DispatcherServlet调用HandlerAdapter处理器适配器去调用Handler
  • 5)处理器适配器执行Handler
  • 6)Handler处理完毕后返回ModelAndView给处理器适配器
  • 7)处理器适配器将ModelAndView返回给前端控制器DispatcherServlet
  • 8)前端控制器DispatcherServlet请求视图解析器ViewResolver解析视图
  • 9)视图解析器将解析后的视图View返回给前端控制器DispatcherServlet
  • 10)前端控制器DispatcherServlet对视图渲染,就是将数据模型填充到request域中
  • 11)前端控制器DispatcherServlet想用户响应结果

Spring MVC九大组件

  • HandlerMapping(处理器控制器)
  • HandlerAdapter(处理器适配器)
  • HandlerExceptionResolver(异常解析器)
  • ViewResolver(视图解析器)
  • RequsetToViewNameTranslator
  • LocalResolver
  • ThemeResolver
  • MultipartResolver
  • FlashMapManager

请求参数绑定

基础数据类型绑定

​ 简单的基础数据类型:八种基础数据类型及其包装类型,参数类型推荐使用包装类类型,因为基础数据类型不可以为null。

​ Short / short 、Long / long 、Integer / int 、Float / float 、Double / double 、Char / char 、Boolean / boolean 、String

说明:对于布尔值类型的参数,参数值只能为trur / false / 1 / 0。

注意:绑定基础数据类型,只需要直接声明形参即可。建议请求参数和形参参数名称一致,如不一致使用@RequestParam注解。

html

<fieldset>    <p>测试用例:SpringMVC 接收简单数据类型参数</p>    <a href="/demo/handle03?ids=1">点击测试</a></fieldset>

java

@RequestMapping("/handle03")public ModelAndView handle03(@RequestParam("ids") Integer id,Boolean flag) {    Date date = new Date();    ModelAndView modelAndView = new ModelAndView();    modelAndView.addObject("date",date);    modelAndView.setViewName("success");    return modelAndView;}

Pojo类型参数绑定

html

<fieldset>    <p>测试用例:SpringMVC接收pojo类型参数</p>    <a href="/demo/handle04?id=1&name=zhangsan">点击测试</a></fieldset>

java

/* * SpringMVC接收pojo类型参数  url:/demo/handle04?id=1&username=zhangsan * 接收pojo类型参数,直接形参声明即可,类型就是Pojo的类型,形参名无所谓 * 但是要求传递的参数名必须和Pojo的属性名保持一致 */@RequestMapping("/handle04")public ModelAndView handle04(User user) {    Date date = new Date();    ModelAndView modelAndView = new ModelAndView();    modelAndView.addObject("date",date);    modelAndView.setViewName("success");    return modelAndView;}

Pojo包装对象绑定

html

<fieldset>    <p>测试用例:SpringMVC接收pojo包装类型参数</p>    <a href="/demo/handle05?user.id=1&user.name=zhangsan">点击测试</a></fieldset>

java

/* * QueryVo中有User user 属性,需要将请求参数封装到queryVo中 * SpringMVC接收pojo包装类型参数  url:/demo/handle05?user.id=1&user.username=zhangsan * 不管包装Pojo与否,它首先是一个pojo,那么就可以按照上述pojo的要求来 * 1、绑定时候直接形参声明即可 * 2、传参参数名和pojo属性保持一致,如果不能够定位数据项,那么通过属性名 + "." 的方式进一步锁定数据 * */@RequestMapping("/handle05")public ModelAndView handle05(QueryVo queryVo) {    Date date = new Date();    ModelAndView modelAndView = new ModelAndView();    modelAndView.addObject("date",date);    modelAndView.setViewName("success");    return modelAndView;}

日期类型绑定

html

<fieldset>    <p>测试用例:SpringMVC接收日期类型参数</p>    <a href="/demo/handle06?birthday=2019-10-08">点击测试</a></fieldset>

java

/** * 绑定日期类型参数 * 定义一个SpringMVC的类型转换器  接口,扩展实现接口接口,注册你的实现 * @param birthday * @return */@RequestMapping("/handle06")public ModelAndView handle06(Date birthday) {    Date date = new Date();ModelAndView modelAndView = new ModelAndView();    modelAndView.addObject("date",date);    modelAndView.setViewName("success");    return modelAndView;}

自定义类型转化器

/** * Converter<S, T> *     S : 是传递进来的数据类型 *     T : 是处理后需要返回的数据类型 * @Author zhang yong jun * @time 2020/6/11 11:25 */public class DateConverter implements Converter<String, Date> {    private static final SimpleDateFormat SDF = new SimpleDateFormat("yyyy-MM-dd");    @Override    public Date convert(String s) {        Date parse = null;        try {            parse = SDF.parse(s);        } catch (ParseException e) {            e.printStackTrace();        }        return parse;    }}

配置自定义类型转换器

<!--配置spring mvc的映射处理器--><mvc:annotation-driven conversion-service="conversionService" /><!--注册自定义类型转换器--><bean id="conversionServiceBean" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">    <property name="converters">        <set>            <bean class="com.zhichunqiu.converter.DateConverter"></bean>        </set>    </property></bean>

对Restful风格请求的支持

​ Restful是一种web软件架构风格,它不是标准也不是协议,只是倡导url设计的时候使用资源定义以及资源操作的风格。

Restful是什么

​ REST(Representational State Transfer)描述了一个架构样式的网络系统。它由Roy Fielding在2000年的博士论文中提出,Roy Fielding是HTTP规范的主要编写者之一。REST相比SOAP(Simple Object Access protocol,简单对象访问协议)和XML-RPC更加简单明了,REST更倾向于简单轻量的方法设计和实现。所以REST是一种设计风格。

Restful的优点

结构清晰、符合标准、易于理解、方便扩展

Restful的特征

资源(Resources): 网络上的一个实体,可以是一段文本、一张图片、一首歌曲、一种服务。可以用URI(统一资源定位符)指定它,每种资源对应一个特定的URI。要获得资源只需要访问这个资源的URI即可。

表现层(Representation): 把资源呈现出来的形式,叫做表现层。比如:文本用txt格式、HTML格式、XML格式、JSON格式表现。

状态转化(State Transfer): 每一个请求,就代表了客户端和服务器的一次交互。

HTTP协议是一个无状态协议,所有的状态都保存在服务器端。如果客户端想要操作服务器,就必须通过一些手段,让服务器端发生状态转化。具体在HTTP协议中有四个表示操作方式的动词:PUT / DELETE / GET / POST。

Restful风格URL

互联网所有的一切都是资源,要求URL中只有表示资源的名称,没有动词。

Restful资源操作

使用HTTP请求中的method方法put(更新) / delete(删除) / post(新增) / get(查询)来操作资源。但是由于安全性问题主要使用post和get。put和delete基本不使用。如果强制要使用put和delete,可以在请求中使用post并携带参数_method=put,服务端再配置请求方式过滤器,如果请求参数中有__method就会转换请求方式org.springframework.web.filter.HiddenHttpMethodFilter。

Restful请求方式转换

html

<!-- 新增一个隐藏值_method 设置转变的请求方式 --><form method="post" action="/demo/handle/15/lisi">    <input type="hidden" name="_method" value="put"/>    <input type="submit" value="提交rest_put请求"/></form><form method="post" action="/demo/handle/15">    <input type="hidden" name="_method" value="delete"/>    <input type="submit" value="提交rest_delete请求"/></form>

web.xml

<!--请求参数转变过滤器,如post请求转换为put请求--><filter>  <filter-name>hiddenHttpMethodFilter</filter-name>  <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class></filter><filter-mapping>  <filter-name>hiddenHttpMethodFilter</filter-name>  <url-pattern>/*</url-pattern></filter-mapping>

java

/* * restful  put  /demo/handle/15/lisi */@RequestMapping(value = "/handle/{id}/{name}",method = {RequestMethod.PUT})public ModelAndView handlePut(@PathVariable("id") Integer id, @PathVariable("name") String username) {    Date date = new Date();    ModelAndView modelAndView = new ModelAndView();    modelAndView.addObject("date",date);    modelAndView.setViewName("success");    return modelAndView;}/* * restful  delete  /demo/handle/15 */@RequestMapping(value = "/handle/{id}",method = {RequestMethod.DELETE})public ModelAndView handleDelete(@PathVariable("id") Integer id) {    Date date = new Date();    ModelAndView modelAndView = new ModelAndView();    modelAndView.addObject("date",date);    modelAndView.setViewName("success");    return modelAndView;}

Ajax Json交互

什么是Json

  • JSON 指的是 JavaScript 对象表示法(JavaScript Object Notation)
  • JSON 是轻量级的文本数据交换格式
  • JSON 独立于语言:JSON 使用 Javascript语法来描述数据对象,但是 JSON 仍然独立于语言和平台。JSON 解析器和 JSON 库支持许多不同的编程语言。 目前非常多的动态(PHP,JSP,.NET)编程语言都支持JSON

Json的语法

JSON 语法是 JavaScript 对象表示语法的子集。

  • 数据在名称/值对
  • 数据由逗号分隔
  • 大括号保存对象
  • 中括号保存数组

@RequestBody注解

@ReqeustBody注解是Spring MVC对Json的支持,作用是将用户请求的Json格式数据解析转换为对应的参数对象。这个注解解析的是Post请求的body区域参数。

@ResponseBody注解

@ResponseBody注解是Spring MVC对Json的支持,作用是将Controller返回的对象通过转换器转换为指定的格式之后,写入到reqsponse对象的body区域。

注意 使用这个注解后返回结果不走视图处理器,而是直接将数据写入到输出流中响应给客户端。

Spring MVC使用Json交互

pom引入jar

<!--json数据交互所需jar,start--><dependency>  <groupId>com.fasterxml.jackson.core</groupId>  <artifactId>jackson-core</artifactId>  <version>2.9.0</version></dependency><dependency>  <groupId>com.fasterxml.jackson.core</groupId>  <artifactId>jackson-databind</artifactId>  <version>2.9.0</version></dependency><dependency>  <groupId>com.fasterxml.jackson.core</groupId>  <artifactId>jackson-annotations</artifactId>  <version>2.9.0</version></dependency><!--json数据交互所需jar,end-->

html

<div>    <h2>Ajax json交互</h2>    <fieldset>        <input type="button" id="ajaxBtn" value="ajax提交"/>    </fieldset></div>

javascript

$(function () {    $("#ajaxBtn").bind("click",function () {        // 发送ajax请求        $.ajax({            url: '/demo/handle07',            type: 'POST',            data: '{"id":"1","name":"李四"}',            contentType: 'application/json;charset=utf-8',            dataType: 'json',            success: function (data) {                alert(data.name);            }        })    })})

java

@RequestMapping("/handle07")// 添加@ResponseBody之后,不再走视图解析器那个流程,而是等同于response直接输出数据public @ResponseBody User handle07(@RequestBody User user) {    // 业务逻辑处理,修改name为张三丰    user.setName("张三丰");    return user;}

拦截器(Interceptor)

拦截器需要实现HandlerInterceptor接口,其中包含三个方法

preHandle : 在Handler方法执行前执行。

postHandle : 在Handler方法返回前执行。

afterCompletion : 在Handler方法返回后执行。

自定义拦截器

public class MyInterceptor01 implements HandlerInterceptor {    @Override    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {        System.out.println("MyInterceptor01 preHandle......");        return true;    }    @Override    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {        System.out.println("MyInterceptor01 postHandle......");    }    @Override    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {        System.out.println("MyInterceptor01 afterCompletion......");    }}

配置拦截器

<!--配置拦截器,配置拦截器的顺序就是拦截器执行的顺序。多个拦截器形成拦截器链--><mvc:interceptors>    <mvc:interceptor>        <mvc:mapping path="/**"/>        <bean class="com.zhichunqiu.interceptor.MyInterceptor01"></bean>    </mvc:interceptor>    <mvc:interceptor>        <mvc:mapping path="/**"/>        <bean class="com.zhichunqiu.interceptor.MyInterceptor02"></bean>    </mvc:interceptor></mvc:interceptors>

multipart文件形式数据处理

引入jar

<!--⽂件上传所需jar坐标--><dependency>  <groupId>commons-fileupload</groupId>  <artifactId>commons-fileupload</artifactId>  <version>1.3.1</version></dependency>

配置springmvc.xml

<!--配置文件上传解析器--><bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">    <!--自定义配置-->    <property name="maxUploadSize" value="2048000000" /></bean>

文件上传写法一

html

<div>    <h2>multipart 文件上传,写法一</h2>    <fieldset>        <%--            1 method="post"            2 enctype="multipart/form-data"            3 type="file"        --%>        <form method="post" enctype="multipart/form-data" action="/demo/upload01">            <input type="file" name="uploadFile"/>            <input type="submit" value="上传"/>        </form>    </fieldset></div>

java

/** * 从文件上传的request中获取文件 * * @param req * @param resp * @return * @throws Exception */@RequestMapping("/upload01")public String fileUpload01(MultipartHttpServletRequest req, HttpServletResponse resp) throws Exception {    // 获取上传的文件    MultipartFile uploadFile = req.getFile("uploadFile");    // 获取上传文件的名称    String originalFilename = uploadFile.getOriginalFilename();    // 获取文件的流    InputStream inputStream = uploadFile.getInputStream();    // 获取磁盘路径, / 表示WEB-INF目录    String realPath = req.getServletContext().getRealPath("/upload") + "/";    System.out.println("磁盘目录为:" + realPath);    // 将文件输出到这个目录,这里文件没有重命名处理,但是生产中对文件需要重命名    uploadFile.transferTo(new File(realPath + originalFilename));    return "success";}

文件上传写法二

html

<div>    <h2>multipart 文件上传,方式二</h2>    <fieldset>        <%--            1 method="post"            2 enctype="multipart/form-data"            3 type="file"        --%>        <form method="post" enctype="multipart/form-data" action="/demo/upload02">            <input type="file" name="uploadFile"/>            <input type="submit" value="上传"/>        </form>    </fieldset></div>

java

/** * 直接定义MultipartFile对象 * * @param multipartFile * @param session * @return * @throws Exception */@RequestMapping("/upload02")public String fileUpload02(MultipartFile multipartFile, HttpSession session) throws Exception {    // 获取上传的文件名称    String originalFilename = multipartFile.getOriginalFilename();    // 获取磁盘路径, / 表示WEB-INF目录    String realPath = session.getServletContext().getRealPath("/upload") + "/" + originalFilename;    System.out.println("磁盘目录为:" + realPath);    // 将文件输出到这个目录,这里文件没有重命名处理,但是生产中对文件需要重命名    multipartFile.transferTo(new File(realPath));    return "success";}

控制器异常处理

局部异常处理

局部异常处理是在单个Controller中使用@ExceptionHandler标记一个方法为这个Controller的局部异常处理Handler。可以定义多个异常处理器,分别处理不同类型的异常。

@ExceptionHandler(value = {IOException.class})public ModelAndView methodException(Exception exception) {    ModelAndView modelAndView = new ModelAndView();    modelAndView.addObject("msg", exception.getMessage());    modelAndView.setViewName("error");    return modelAndView;}@ExceptionHandler(value = {ArithmeticException.class})public ModelAndView arithmeticException(Exception exception) {    ModelAndView modelAndView = new ModelAndView();    modelAndView.addObject("msg", exception.getMessage() + " / 局部异常处理器:arithmeticException");    modelAndView.setViewName("error");    return modelAndView;}

全局异常处理

全局异常处理是创建一个Class,并且使用注解@ControllerAdvice标记这个Controller增强类。这样可以在类中定义多个异常处理器,分别处理不同的异常。

注意 如果同时定义了局部异常和全局异常,那么优先匹配的是局部异常。

@ControllerAdvicepublic class GlobalExceptionHandler {    @ExceptionHandler(value = {ArithmeticException.class})    public ModelAndView arithmeticException(Exception exception) {        ModelAndView modelAndView = new ModelAndView();        modelAndView.addObject("msg", exception.getMessage() + " / 全局异常处理器:arithmeticException");        modelAndView.setViewName("error");        return modelAndView;    }}

基于Flash属性的重定向数据传递

​ 对于重定向后的参数传递问题,一般都是重定向后拼接参数,这种方式效率不高,而且使用get方式对于参数有长度限制而且不安全。spring mvc在Controller的方法参数中提供了RedirectAttributes参数用于解决重定向后的参数传递问题。传递后的参数使用@ModelAttribute注解接收。

/** * SpringMVC 重定向时参数传递的问题 */@RequestMapping("/handleRedirect")public String handleRedirect(String name, RedirectAttributes redirectAttributes) {    // addFlashAttribute方法设置了一个flash类型属性,该属性会被暂存到session中,在跳转到页面之后该属性销毁    redirectAttributes.addFlashAttribute("name",name);    return "redirect:handleRedirect01";}/** * 重定向后用@ModelAttribute注解取出属性:ModelAttribute * @param name * @return */@RequestMapping("/handleRedirect01")public ModelAndView handleRedirect01(@ModelAttribute("name") String name) {    LocalDateTime now = LocalDateTime.now();    // 封装了Model和View视图      ModelAndView modelAndView = new ModelAndView();    // 封装返回结果到Model中    modelAndView.addObject("date", now);    // 设置返回的视图名称    modelAndView.setViewName("success");    return modelAndView;}

SpringMVC学习思维导图

一文讲透Spring MVC,图文结合,思路超清晰(附XMind脑图)

作者:知春秋

来源:https://xie.infoq.cn/article/118d19a4ca5de87163de4942c

猜你喜欢

转载自blog.csdn.net/java_xiaoo/article/details/111395751
今日推荐