Spring MVC的进阶使用-1
(1)SpringMVC的请求处理
1、SpringMVC对请求参数的处理
在之前的servlet中我们可以通过request.getParameter()来获取请求中的参数,但是在我们编写的SpringMVC的应用程序中,在具体请求的方法中并不包含request参数,那么我们应该如何获取请求中的参数呢?
需要使用以下几个注解:
@RequestParam:获取请求的参数
@RequestHeader:获取请求头信息
@CookieValue:获取cookie中的值
@RequestParam的基本使用
1 | package com.oi.controller; |
@RequestHeader的基本使用:
1 | package com.oi.controller; |
@CookieValue的基本使用
1 | package com.oi.controller; |
如果请求中传递的是某一个对象的各个属性值,此时如何在控制器的方法中获取对象的各个属性值呢?
在SpringMVC的控制中,能直接完成对象的属性赋值操作,不需要人为干预。
User.java
1 | package com.oi.bean; |
Address.java
1 | package com.oi.bean; |
login.jsp
1 | <%-- |
UserController.java
1 | package com.oi.controller; |
2、乱码问题的解决
我们在表单或者发送请求的时候,经常会遇到中文乱码的问题,那么如何解决乱码问题呢?
GET请求:在server.xml文件中,添加URIEncoding=“UTF-8”
POST请求:编写过滤器进行实现
1 |
|
注意:如果配置了多个过滤器,那么字符编码过滤器一定要在最前面,否则失效。
3、SpringMVC对原生API的支持
1 | package com.oi.controller; |
4、使用Model,Map,ModelMap传输数据到页面
在刚开始的helloworld项目中,我们传递了参数回到我们页面,但是后续的操作都只是接受用户的请求,那么在SpringMVC中除了可以使用原生servlet的对象传递数据之外,还有什么其他的方式呢?
可以在方法的参数上传入Model,ModelMap,Map类型,此时都能够将数据传送回页面
OutputController.java
1 | package com.oi.controller; |
当使用此方式进行设置之后,会发现所有的参数值都设置到了request作用域中,那么这三个对象是什么关系呢?
![](Spring MVC的进阶使用-1/BindingAwareModelMap.png)
5、使用ModelAndView对象传输数据到页面
1 | package com.oi.controller; |
发现当使用modelAndView对象的时候,返回值的类型也是此对象,可以将要跳转的页面设置成view的名称,来完成跳转的功能,同时数据也是放到request作用中。
6、使用session传输数据到页面
@SessionAttribute:此注解可以表示,当向request作用域设置数据的时候同时也要向session中保存一份,此注解有两个参数,一个value(表示将哪些值设置到session中),另外一个type(表示按照类型来设置数据,一般不用,因为有可能会将很多数据都设置到session中,导致session异常)。
1 |
|
7、使用@ModelAttribute来获取请求中的数据
@ModelAttribute注解用于将方法的参数或者方法的返回值绑定到指定的模型属性上,并返回给web视图。首先来介绍一个业务场景,来帮助大家做理解,在实际工作中,有些时候我们在修改数据的时候可能只需要修改其中几个字段,而不是全部的属性字段都获取,那么当提交属性的时候,从form表单中获取的数据就有可能只包含了部分属性,此时再向数据库更新的时候,肯定会丢失属性,因为对象的封装是springmvc自动帮我们new的,所以此时需要先将从数据库获取的对象保存下来,当提交的时候不是new新的对象,而是在原来的对象上进行属性覆盖,此时就需要使用@ModelAttribute注解。
User.java
1 | package com.oi.bean; |
UserController.java
1 | package com.oi.controller; |
index.jsp
1 | <%-- |
其实在使用的时候可以简化写法,也就是说,在方法的参数上不加@ModelAttribute也不会有问题
1 | "update") ( |
如果添加的@ModelAttribute(“”)属性的值不对,那么也是获取不到值的。同时可以添加@SessionAttributes属性,但是注意,如果没有设置值的话,会报错
1 | package com.oi.controller; |
注意:ModelAttribute除了可以使用设置值到model中之外,还可以利用返回值。
1 | package com.oi.controller; |
总结:通过刚刚的给参数赋值,大家应该能够发现,当给方法中的参数设置值的时候,如果添加了@ModelAttribute注解,那么在查找值的时候,是遵循以下方式:
1、方法的参数使用参数的类型首字母小写,或者使用@ModelAttribute(“”)的值
2、先看之前是否在model中设置过该属性值,如果设置过就直接获取
3、看@SessionAttributes注解标注类中的方法是否给session中赋值,如果有的话,也是直接获取,没有报异常
8、使用forward实现页面转发
在发送请求的时候,可以通过forward:来实现转发的功能:
1 | package com.oi.controller; |
9、使用redirect来实现重定向
1 | package com.oi.controller; |
在javaweb的时候大家应该都接触过重定向和转发的区别,下面再详细说一下:
转发:
由服务器的页面进行跳转,不需要客户端重新发送请求:
特点如下:
1、地址栏的请求不会发生变化,显示的还是第一次请求的地址
2、请求的次数,有且仅有一次请求
3、请求域中的数据不会丢失
4、根目录:localhost:8080/项目地址/,包含了项目的访问地址
![转发](Spring MVC的进阶使用-1/转发.png)
重定向:
在浏览器端进行页面的跳转,需要发送两次请求(第一次是人为的,第二次是自动的)
特点如下:
1、地址栏的地址发生变化,显示最新发送请求的地址
2、请求次数:2次
3、请求域中的数据会丢失,因为是不同的请求
4、根目录:localhost:8080/ 不包含项目的名称
![](Spring MVC的进阶使用-1/重定向.png)
对比:
区别 | 转发forward() | 重定向sendRedirect() |
---|---|---|
根目录 | 包含项目访问地址 | 没有项目访问地址 |
地址栏 | 不会发生变化 | 会发生变化 |
哪里跳转 | 服务器端进行的跳转 | 浏览器端进行的跳转 |
请求域中数据 | 不会丢失 | 会丢失 |
10、静态资源的访问
当页面中包含静态资源的时候我们能够正确的获取到吗?
hello.jsp
1 | <%@ page contentType="text/html;charset=UTF-8" language="java" %> |
此时大家发现我们请求的图片根本访问不到,根据查看发现路径是没有问题的,那么为什么会找不到静态资源呢?
![image-20200312233843775](Spring MVC的进阶使用-1/静态资源.png)
大家发现此时是找不到对应的mapping映射的,此时是因为DispatcherServlet会拦截所有的请求,而此时我们没有对应图片的请求处理方法,所以此时报错了,想要解决的话非常简单,只需要添加一个配置即可
1 | <!-- |
但是加上此配置之后,大家又发现此时除了静态资源无法访问之外,我们正常的请求也无法获取了,因此还需要再添加另外的配置:
1 | <!--保证静态资源和动态请求都能够访问--> |
(2)自定义视图解析器
我们在之前的操作中已经用了SpringMVC中提供的视图解析器,那么如果我们需要实现自己的视图解析器该如何操作呢?
![image-20200312211420457](Spring MVC的进阶使用-1/视图解析器.png)
![image-20200312211552245](Spring MVC的进阶使用-1/视图对象.png)
MyViewController.java
1 | package com.oi.controller; |
MyViewResolver.java
1 | package com.oi.view; |
MyView.java
1 | package com.oi.view; |
springmvc.xml
1 |
|
(3)自定义类型转换器
在日常的企业开发需求中,我们输入文本框的内容全部都是字符串类型,但是在后端处理的时候我们可以用其他基本类型来接受数据,也可以使用实体类来接受参数,这个是怎么完成的呢?就是通过SpringMVC提供的类型转换器,SpringMVC内部提供了非常丰富的类型转换器的支持,但是有些情况下有可能难以满足我们的需求,因此需要我们自己实现,如下:
![image-20200312211944841](Spring MVC的进阶使用-1/类型转换器.png)
User.java
1 | package com.oi.bean; |
MyConverter.java
1 | package com.oi.converter; |
UserController.java
1 | package com.oi.controller; |
success.jsp
1 | <%-- |
springmvc.xml
1 |
|
(4)自定义日期格式化转换器
有时候我们经常需要在页面添加日期等相关信息,此时需要制定日期格式化转换器,此操作非常简单:只需要在单独的属性上添加@DateTimeFormat注解即可,制定对应的格式
User.java
1 | package com.oi.bean; |
index.jsp
1 | <%@ page contentType="text/html;charset=UTF-8" language="java" %> |
DateConvertionController.java
1 | package com.oi.controller; |
springmvc.xml
1 |
|
此时运行发现是没有问题的,但是需要注意的是,如果同时配置了自定义类型转换器之后,那么日期格式转化是有问题的。
springmvc.xml
1 |
|
原因就在于ConversionServiceFactoryBean对象中有且仅有一个属性converters,此时可以使用另外一个类来做替换FormattingConversionServiceFactoryBean
springmvc.xml
1 |
|
(5)数据校验
一般情况下我们会在前端页面实现数据的校验,但是大家需要注意的是前端校验会存在数据的不安全问题,因此一般情况下我们都会使用前端校验+后端校验的方式,这样的话既能够满足用户的体验度,同时也能保证数据的安全,下面来说一下在springmvc中如何进行后端数据校验。
JSR303是 Java 为 Bean 数据合法性校验提供的标准框架,它已经包含在 JavaEE 6.0 中 。JSR 303 (Java Specification Requests意思是Java 规范提案)通过在 Bean 属性上标注类似于 @NotNull、@Max 等标准的注解指定校验规则,并通过标准的验证接口对 Bean 进行验证。
JSR303:
![](Spring MVC的进阶使用-1/JSR303.png)
Hibernate Validator 扩展注解:
![](Spring MVC的进阶使用-1/hibernate.png)
spring中拥有自己的数据校验框架,同时支持JSR303标准的校验框架,可以在通过添加注解的方式进行数据校验。在spring中本身没有提供JSR303的实现,需要导入依赖的包。
pom.xml
1 |
|
index.jsp
1 | <%-- |
DataValidateController.java
1 | package com.oi.controller; |
User.java
1 | package com.oi.bean; |
此时大家发现在报错的地方无法出现错误提示,可以换另外一种方式:
index.jsp
1 | <%@ page contentType="text/html;charset=UTF-8" language="java" %> |
add.jsp
1 | <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> |
DataValidateController.java
1 | package com.oi.controller; |
web.xml
1 |
|
原生的表单如何获取错误信息:
DataValidateController.java
1 | package com.oi.controller; |
add.jsp
1 | <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> |