往期文章:
Spring 学习总结笔记【一、快速入门】
Spring 学习总结笔记【二、IoC-控制反转】
Spring 学习总结笔记【三、注解开发】
Spring 学习总结笔记【四、整合Junit】
Spring 学习总结笔记【五、配置数据源】
Spring 学习总结笔记【六、整合Mybatis】
Spring 学习总结笔记【七、AOP面向切面编程】
Spring 学习总结笔记【八、集成Web环境】
Spring 学习总结笔记【九、SpringMVC快速入门】
name=value&age=value2……
Controller中的业务方法的参数名称要与请求参数的name一致
,参数值会自动映射
匹配。并且能自动做类型 转换;自动的类型转换是指从String向其他类型的转换。
@RequestMapping("/t1")
@ResponseBody // 表示不进行页面跳转 回写的数据为空
public void test1(String username, int age){
System.out.println("username = " + username);
// SpringMVC框架会自动将获取到的string类型的age转换为int类型的age
System.out.println("age = " + age);
}
- Get请求普通传参:url地址传参,地址参数名与形参变量名相同,定义形参即可接受参数。
- Post请求普通传参:form表单传参,表单参数名与形参变量名相同,定义形参即可接受参数。
可使用两种解决方法:
① 若Sprign基于xml配置,可在web.xml添加如下代码:
<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>
② 若Spring基于注解开发,则可在SpringMVC核心配置类重写getServletFilters()
方法:
public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
// Post请求乱码处理
@Override
protected Filter[] getServletFilters() {
CharacterEncodingFilter filter = new CharacterEncodingFilter();
filter.setEncoding("UTF-8");
return new Filter[]{filter};
}
}
当请求的参数名称与Controller的业务方法参数名称不一致时,就需要通过@RequestParam
注解显示的绑定 。
@RequestMapping("/t1")
public void test1(@RequestParam(value = "name",required = false,defaultValue = "tyt") String username, int age){
System.out.println("username = " + username);
System.out.println("age = " + age);
}
@RequestParam注解的三个属性:
- value:请求参数名称
- required :默认值为true, 表示是否必须要携带该参数
- defaultValue:默认值,当设置了默认值那么required就会失效
客户端发送的数据到达服务端之后,SpringMVC要将这些参数封装到一个实体类当中。原先我们要将请求参数封装到实体当中是怎样做的?通过getParamterMap获取参数map集合,然后通过beanUtils进行实体封装。SpringMVC框架封装了对实体封装的技术,我们只需要保证:
Controller中的业务方法的POJO参数的属性名与请求参数的name一致
,参数值会自动映射
匹配。
创建一个实体类User
package com.tyt.domain;
/**
* @ClassName User
* @Author 划水艺术家
* @Date 2022/7/17 17:07
* @Version 1.0
**/
public class User {
private String name;
private Integer age;
private String sex;
public User(){
}
public User(String name, Integer age, String sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
", sex='" + sex + '\'' +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
@RequestMapping("/t2")
@ResponseBody // 表示不进行页面跳转 回写的数据为空
public void test2(User user) {
System.out.println("user = " + user);
}
Controller中的业务方法数组名称与请求参数的name一致
,参数值会自动映射
匹配。
@RequestMapping("/t3")
@ResponseBody
public void test3(String[] array){
System.out.println(Arrays.toString(array));
}
简单类型:例如Integer
,String
等。
@RequestParam
注解绑定参数关系@RequestMapping("/t4")
@ResponseBody
public void test4(@RequestParam List<String> list){
System.out.println("list = " + list);
}
对象集合不支持直接获取,可使用json数据传输。
使用json作为传输数据格式时,需要引入相关坐标。
<dependency>
<groupId>com.fasterxml.jackson.coregroupId>
<artifactId>jackson-databindartifactId>
<version>2.12.1version>
dependency>
@EnableWebMvc
@ComponentScan("com.tyt.controller")
@EnableWebMvc // 根据类型匹配对应的类型转换器
public class SpringMvcConfig {
}
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
list>
property>
bean>
Content-Type
为application/json
形式,在方法参数位置使用@RequestBody
接收集合数据。Content-Type
为application/json
形式,在方法参数位置使用@RequestBody
接收集合数据。Content-Type
为application/json
形式,在方法参数位置使用@RequestBody
接收集合数据。@RequestMapping(value = "/t5")
@ResponseBody
public void test5(@RequestBody List<String> list){
System.out.println("list = " + list);
}
@RequestMapping("/t6")
@ResponseBody
public void test6(@RequestBody User user) {
System.out.println("user = " + user);
}
@RequestMapping(value = "/t7")
@ResponseBody
public void test7(@RequestBody List<User> userList){
System.out.println("userList = " + userList);
}
@DateTimeFormat
注解,根据不同日期格式设置不同的接受方式@RequestMapping("/t8")
@ResponseBody
public void test8(Date date,
@DateTimeFormat(pattern = "yyyy-mm-dd") Date date1,
@DateTimeFormat(pattern = "yyyy-mm-dd hh:mm:ss") Date date2){
System.out.println("date = " + date);
System.out.println("date1 = " + date1);
System.out.println("date2 = " + date2);
}
自定义类型转换器步骤:
① 定义转换器类实现Converter接口
② 声明引用转换器
① 定义转换器类实现Converter接口
package com.tyt.convert;
public class DateConverter implements Converter<String, Date> {
public Date convert(String source) {
// 将日期字符串转换成日期对象并返回
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
Date date = null;
try {
date = simpleDateFormat.parse(source);
} catch (ParseException e) {
e.printStackTrace();
}
return date;
}
}
若Spring基于xml配置
② 在配置文件中声明并引用转换器
<bean id="myConvert" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters" >
<list>
<bean class="com.tyt.convert.DateConverter"/>
list>
property>
bean>
<mvc:annotation-driven conversion-service="myConvert"/>
若Spring基于注解开发
② 定义类,注册转换器
@ControllerAdvice
public class DateConvertRegister {
@Autowired
private DateConverter dateConverter;
@InitBinder
public void dateBinder(WebDataBinder dataBinder){
//1.获取转换服务对象
ConversionService conversionService = dataBinder.getConversionService();
//2.判断conversionService是否为GenericConversionService类型
if(conversionService instanceof GenericConversionService){
//3.强转
GenericConversionService genericConversionService = (GenericConversionService)conversionService;
//4.添加类型转换器
genericConversionService.addConverter(dateConverter);
}
}
}
响应方式分为两种方式:
- 页面跳转
① 直接返回字符串
② 通过ModelAndView
对象返回- 回显数据
① 直接返回字符串
② 返回对象或集合
直接返回字符串:此种方式会将返回的字符串与视图解析器
的前后缀拼接后跳转。
若基于xml配置
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
bean>
若基于注解开发
@ComponentScan("com.tyt.controller")
@EnableWebMvc // 根据类型匹配对应的类型转换器
public class SpringMvcConfig{
/**
* 视图解析器
*/
@Bean(name="tnternalResourceViewResolver")
public ViewResolver initViewResolver(){
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/jsp/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
}
index.jsp代码:
<html>
<body>
<h2>Hello World!h2>
<h1>${username}h1>
body>
html>
① 设置视图、模型
// 设置当前操作访问路径
@RequestMapping("/test")
public ModelAndView test(){
/*
* model:模型,封装数据
* view:视图,展示数据
*/
System.out.println("返回 modelAndView...");
ModelAndView modelAndView = new ModelAndView();
// 设置视图名称
modelAndView.setViewName("index");
// 设置模型数据
modelAndView.addObject("username", "tyt");
return modelAndView;
}
② 在Controller中方法形参上直接声明ModelAndView,无需在方法中自己创建,在方法中直接使用该对象设置 视图,同样可以跳转页面
@RequestMapping("/test2")
public ModelAndView test2(ModelAndView modelAndView){
modelAndView.addObject("username","tyt");
modelAndView.setViewName("index");
return modelAndView;
}
SpringMVC对方法的参数可以进行相应的注入,当解析该方法时发现需要一个ModelAndView
那么SpringMVC就会提供一个ModelAndView。
③ 只设置模型model ,返回字符串
@RequestMapping("/test3")
public String test3(Model model){
// 设置模型
model.addAttribute("username","tyt");
// 返回逻辑视图名称
return "index";
}
④ 在Controller方法的形参上可以直接使用原生的HttpServeltRequest对象,只需声明即可
@RequestMapping("/test4")
public String test4(HttpServletRequest request){
request.setAttribute("username","tyt");
// 返回逻辑视图名称
return "index";
}
- 通过SpringMVC框架注入的response对象,使用
response.getWriter().print("")
回写数据,此时不需要视图跳转,业务方法返回值为void- 将需要回写的字符串直接返回,但此时需要通过
@ResponseBody
注解告知SpringMVC框架,方法返回的字符串不是跳转是直接在http响应体中返回
@RequestMapping("/test5")
// 设置当前操作返回值类型
public void test5(HttpServletResponse response) throws IOException {
response.getWriter().println("hello world");
}
@RequestMapping("/test6")
// 使用该注解 告知SpringMVC返回的字符串直接在响应体返回
@ResponseBody
public String test6() {
return "hello world";
}
@RequestMapping(value = "/test7")
@ResponseBody
public String test7() {
// 引号需要进行转义
return "{\"username\":\"tyt\",\"age\":20}";
}
手动拼接json格式字符串的方式很麻烦,开发中往往要将复杂的Java对象转换成json格式的字符串,我们可以使用json转换工具fastjson
进行转换。
导入fastjson相关坐标
<dependency>
<groupId>com.alibabagroupId>
<artifactId>fastjsonartifactId>
<version>1.2.62version>
dependency>
// produces="text/html;charset=utf-8" 解决返回中文乱码问题
@RequestMapping(value = "/test8",produces="text/html;charset=utf-8")
@ResponseBody
public String test8(HttpServletResponse response){
User user = new User("tyt", 20, "男");
// 将对象转换为 JSON 字符串
String json = JSON.toJSONString(user);
// 将 JSON 字符串转换为对象
User user1 = JSON.parseObject(json, User.class);
return json;
}
@RequestMapping(value = "/test9")
@ResponseBody
public User test9(HttpServletResponse response){
User user = new User("tyt", 20, "男");
return user;
}
通过SpringMVC帮助我们对对象或集合进行json字符串的转换并回写,为处理器适配器配置消息转换参数,指定使用jackson进行对象或集合的转换,因此需要做出以下配置:
① 导入 jackson 坐标
<dependency>
<groupId>com.fasterxml.jackson.coregroupId>
<artifactId>jackson-databindartifactId>
<version>2.12.1version>
dependency>
② 有三种方法:
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
list>
property>
bean>
<mvc:annotation-driven />
@EnableWebMvc
注解
@Controller
@EnableWebMvc // 根据类型匹配对应的类型转换器
public class UserController {
@RequestMapping(value = "/test9")
@ResponseBody
public User test9(HttpServletResponse response){
User user = new User("tyt", 20, "男");
return user;
}
}
Restful
是一种软件架构风格、设计风格
,而不是标准,只是提供了一组设计原则和约束条件。主要用于客户端和服务器交互类的软件,基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存机制等。
Restful风格的请求是使用“url+请求方式”
表示一次请求目的,HTTP 协议里面四个表示操作方式的动词如下:
- GET:用于获取资源
- POST:用于新建资源
- PUT:用于更新资源
- DELETE:用于删除资源
- 传统风格资源描述形式
http://localhost/user/getById?id=1
http://localhost/user/saveUser- REST风格描述形式
http://localhost/user/1
http://localhost/user
REST风格描述模块的名称通常使用复数,也就是加s
的格式描述,表示此类资源,而非单个资源,例如:books、users…
上述url地址 http://localhost/user/1
中的1
就是要获得的请求参数,在SpringMVC中可以使用占位符
进行参数绑定。地 址/user/1
可以写成/user/{id}
,占位符{id}对应的就是1的值。在业务方法中我们可以使用@PathVariable
注解进行占位符的匹配获取工作。
@RequestMapping("/t9/{id}")
@ResponseBody
public void test9(@PathVariable(value = "id") Integer id){
System.out.println("id = " +id);
}
SpringMVC支持使用原始ServletAPI对象作为控制器方法的参数进行注入,常用的对象如下:
HttpServletRequest
HttpServletResponse
HttpSession
@RequestMapping("/t10")
public void test10(HttpServletRequest request, HttpServletResponse response, HttpSession session){
System.out.println(request);
System.out.println(response);
System.out.println(session);
}
使用@RequestHeader
可以获得请求头信息,相当于JavaWebz中的的request.getHeader(name)
。
@RequestHeader注解的属性如下:
value
:请求头的名称required
:是否必须携带此请求头@RequestMapping("/t10")
public void test10(@RequestHeader(value = "User-Agent",required = false) String userAgent){
System.out.println(userAgent);
}
使用@CookieValue
可以获得指定Cookie的值。
@CookieValue注解的属性如下:
value
:指定cookie的名称required
:是否必须携带此cookie@RequestMapping("/t11")
public void test11(@CookieValue(value = "JSESSIONID") String jsessionID){
System.out.println(jsessionID);
}
区别
@RequestBody用于接受json数据【application/json】
@RequestParam用于接受url地址传参,表单传参【application/x-www-form-urlencoded】
@PathVariable用于接受路径参数,映射url绑定的占位符
应用
后期开发中,请求参数超过1个,以json格式数据为主,@RequestBody应用较广
如果发送非json格式数据,选用@RequestParam接受请求参数
采用RESTful进行开发,当参数数量较少,可以采用@PathVariable接受请求路径变量,通常用于传递id值
下期文章:
Spring 学习总结笔记【十一、SpringMVC拦截器】