SpringMVC

SpringMVC

学习目标:
1.掌握基于SpringMVC获取请求参数与响应json数据操作
2.熟练应用基于REST风格的请求路径设置与参数传递
3.能够根据实际业务建立前后端开发通信协议并进行实现
4.基于SSM整合技术开发任意业务模块功能

1.SpringMVC简介

1.1SpringMVC概述

SpringMVC技术与Servlet技术功能相同,均属于web层开发技术,但SpringMVC技术更简洁,能用更少的代码进行开发

  • 定义:SpringMVC是一种基于Java实现MVC模型的轻量级==Web框架==
  • 优点:
    • 使用简单,开发便捷(相比于Servlet)
    • 灵活性强

1.2SpringMVC入门案例

1.2.1Servlet开发步骤:

1.创建web工程(Maven结构)

2.设置tomcat服务器,加载web工程(tomcat插件)

3.导入坐标(Servlet)

4.定义处理请求的功能类(UserServlet)

5.设置请求映射(配置映射关系)

1.2.2步骤:

①使用SpringMVC技术需要县导入SpringMVC坐标与Servlet坐标

<!--1.导入坐标springmvc和servlet的-->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.1.0</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>5.2.10.RELEASE</version>
    </dependency>

②创建SpringMVC控制器类(等同于Servlet功能)。一般来说@Component是用来定义Bean,在SpringMVC中开发表现层的Bean要使用@Controller注解

@Controller
public class UserController{
	@RequestMapping("/save")//访问路径
	@ResponseBody
	public String save(){//返回Json数据用String
		System.out.println("user save ...");
		return "{'module':'springmvc'}";
	}
}

③初始化SpringMVC环境(同Spring环境),设定SpringMVC加载对应的bean

@Configuration
@ComponentScan("com.iteima.controller")
public class SpringMvcConfig{
}

④初始化Servlet容器,加载SpringMVC环境,并设置SpringMVC技术处理请求

import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.support.AbstractDispatcherServletInitializer;

//4.定义一个servlet容器启动的配置类,在里面加载spring的配置
public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer {
    //加载springMVC容器配置
    @Override
    protected WebApplicationContext createServletApplicationContext() {
        AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
        context.register(SpringMvcConfig.class);
        return context;
    }
    //设置哪些请求归属springMVC处理
    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
	//加载spring容器配置
    @Override
    protected WebApplicationContext createRootApplicationContext() {
        return null;
    }
}
1.2.3入门案例用到的注解
  • 名称:@Controller
  • 类型:类注解
  • 位置:SpringMVC控制器定义上方
  • 作用:设置SpringMVC的核心控制器bean
  • 范例:
@Controller
public class UserController{
}
  • 名称:@ResquestMapping
  • 类型:方法注释
  • 位置:SpringMVC控制器方法定义上方
  • 作用:设置当前控制器方法请求访问路径
  • 相关属性
    • value(默认):请求访问路径
  • 范例:
@ResquestMapping("/save")
public void save(){
	System.out.println("user save ...");
}
  • 名称:@ResponseBody
  • 类型:方法注释
  • 位置:SpringMVC控制器方法定义上方
  • 作用:设置当前控制器方法响应内容为当前返回值,无需解析
  • 范例:
@RequestMapping("/save")
@ResponseBody
public String save(){
System.out.println("user save ...");
return "{'info':"springmvc"}";
}
1.2.4SpringMVC入门程序开发总结(1+N)
  • 一次性工作
    • 创建工程,设置服务器,加载工程
    • 导入坐标
    • 创建web容器启动类,加载SpringMVC配置,并设置SpringMVC请求拦截路径
    • SpringMVC核心配置类(设置配置类,扫描controller包,加载Controller控制器bean)
  • 多次工作
    • 定义处理请求的控制器类
    • 定义处理请求的控制器方法,并配置映射路径(@RequestMapping)与返回json数据(@ResponseBody)
1.2.5Servlet容器配置类

AbstractDispatcherServletInitializer类是SpringMVC提供的快速初始化web3.0容器的抽象类
AbstractDispatcherServletInitializer提供三个接口方法供用户实现
createServletAppilcationContext(),创建servlet容器时,加载SpringMVC对应的bean并放入WebApplicationContext对象中,而WebApplicationContext的作用范围为ServletContext范围,即整个web容器范围

protected WebApplicationContext createServletApplicationContext(){
AnnotattionConfigWebApplicationContext context = new AnnotattionConfigWebAppklicationtContext();
context.register(SpringMvcConfig.class);
return context;
}

getServletMappings(),设定SpringMVC对应的请求映射路径,设置为/表示拦截所有请求,任意请求都将转入道SpringMVC进行处

protected String[] getServletMapping(){
	return new String[]("/");
}

createRootApplicationContext(),如果创建Servlet容器时需要加载飞SpringMVC对应的bean,使用当前方法进行,使用方式用createServletAppilcationContext()

protected WebApplicationContext createRootApplicationContext(){
return null;
}
1.2.6入门案例工作流程分析
  • 启动服务器初始化过程
    • 服务器启动,执行ServletContainersInitConfig类,初始化web容器
    • 执行createServletApplicationContext方法,创建了WebApplicationContext对象
    • 加载SpringMvcConfig
    • 执行@ComponentScan加载对应的bean
    • 加载UserController,每过@RequestMapping的名称对应一个具体的方法
    • 执行getServletMappings方法,定义所有请求都通过SpringMVC
  • 单次请求过程
    • 发射请求localhost/save
    • web容器发现所有请求都经过SpringMVC,将请求交割SpringMVC处理
    • 解析请求路径/save
    • 由/save匹配执行对应的方法save()
    • 执行save()
    • 检测道由@ResponseBody之际将save()方法的返回值作为响应体返回给请求方

1.3Bean加载控制

1.3.1问题分析

项目目录结构:
在这里插入图片描述

  • config目录存入的是配置类,写过的配置类有:
    • ServletContainersInitConfig SpringConfig
    • SpringMVCConfig
    • JdbcConfig
    • MybatisConfig
  • controller目录存放的是SpringMVC的controller类
  • service目录存放的是service接口和实现类
  • dao目录存放的是dao/Mapper接口
1.3.2问题引出

controller、service和dao这些类都需要被容器管理的bean对象,其中controller中的bean是让SpringMVC加载的,那怎么能让Spring不加载呢?
解决方法Controller加载控制与业务bean加载控制

  • SpringMVC相关bean(表现层bean)
  • Spring控制的bean
    • 业务bean(Service)
    • 功能bean(DatatSource等)
  • SpringMVC相关bean加载控制
    • SpringMVC加载的bean对应的包均在com.hcx.controller包内
  • Spring相关bean加载控制
    • 方式一:Spring加载的bean设定扫描范围为com.hcx,排除controller包内的bean
    • 方式二:Spring加在的bean设定扫描范围为精准范围,例如service包,dao包等
      注解:
      名称:@ComponentScan
      类型:类注解
      范例:
@Configuration
@ConmponentScan(value="com.itheima",
	excludeFilters = @ComponentScna.Filter(
		type = FilterType.ANNOTATION,
		classer = Controller.class
		)
)
public class SpringConfig{}

属性:
excludeFilters: 排除扫描路径中加载的bean,需要指定类别(type)与具体项(classer)
includeFilters: 加载指定的bean,需要指定类别(type)与具体项(class)
Tomcat启动时bean的加载格式,Servlet容器配置类
有了Spring的配置类,要想在tomcat服务器启动将其加载,修改ServletContainersInitConfig的createRootApplicationContext方法

//4.定义一个servlet容器启动的配置类,在里面加载spring的配置
public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer {
    //加载springMVC容器配置
    @Override
    protected WebApplicationContext createServletApplicationContext() {
        AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
        context.register(SpringMvcConfig.class);
        return context;
    }
    //设置哪些请求归属springMVC处理
    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
//加载spring容器配置
    @Override
    protected WebApplicationContext createRootApplicationContext() {
         AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
        context.register(SpringConfig.class);
        return context;
    }
}

简化开发,Servlet容器配置类:
对于上述的配置方式,Spring还提供了一种更简单的配置方式,可以不用再去创建AnnotationConfigWebApplicationContext对象,不用手动register对应的配置类。

public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
 
    protected Class<?>[] getRootConfigClasses() {
        return new Class[]{SpringConfig.class};
    }
 
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{SpringMvcConfig.class};
    }
 
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
}

但是,这种方式无法看清容器对象是由谁创建的

2.PostMan简介

2.1PostMan简介

1.PostMan是一款功能强大的网页调试与发送网页HTTP请求的Chrome插件(模拟HTTP请求发送的工具,实现快速发送请求,加快程序测试速度
2.作用:常用于进行接口测试
3.特征:
简单、实用、美观、大方

2.2Postman下载

https://www.postman.com/downloads/

2.3Postman使用

1.创建WorkSpace
2.点击+号新建请求
在这里插入图片描述
3.选择请求方式,输入请求地址,并点击send发送请求
在这里插入图片描述
4.保存请求,方便后续使用
在这里插入图片描述

3.请求与响应

SpringMVC是web层的框架,主要的作用是接收请求、接收数据、响应结果,本节介绍与web技术具体相关的内容:
1.请求映射路径
2.请求参数
3.日期类型参数传递
4.响应json数据(异步数据)

3.1请求映射路径

思考:1.团队多人开发,每人设置不同的请求路径,冲突问题如何解决?
在如下代码中出现了BookController和UserController,都有一个/save路径的情况,产生了冲突

@Controller
public class UserController {
 
    @RequestMapping("/save")
    @ResponseBody
    public String save(){
        System.out.println("user save ...");
        return "{'module':'user save'}";
    }
 
    @RequestMapping("/delete")
    @ResponseBody
    public String save(){
        System.out.println("user delete ...");
        return "{'module':'user delete'}";
    }
}
 
@Controller
public class BookController {
 
    @RequestMapping("/save")
    @ResponseBody
    public String save(){
        System.out.println("book save ...");
        return "{'module':'book save'}";
    }
}

在BookController和UserController,都有一个/save路径,启动Tomcat服务器,后台会报错:
在这里插入图片描述
这里UserController有一个save方法,BookController也有一个save方法,且访问路径都为http://localhost/save,这样在请求访问http://localhost/saved时,无法分清访问UserController还是BookController
解决方案:
设置模块名作为请求路径前缀
BookController中:

@Controller
public class BookController {
    //请求路径映射
    @RequestMapping("/book/save")
    @ResponseBody
    public String save(){
        System.out.println("book save ...");
        return "{'module':'book save'}";
    }
}

UserController中:

@Controller
//类上方配置的请求映射与方法上面配置的请求映射连接在一起,形成完整的请求映射路径
public class UserController {
    //请求路径映射
    @RequestMapping("/user/save")
    @ResponseBody
    public String save(){
        System.out.println("user save ...");
        return "{'module':'user save'}";
    }
    //请求路径映射
    @RequestMapping("/user/delete")
    @ResponseBody
    public String delete(){
        System.out.println("user delete ...");
        return "{'module':'user delete'}";
    }
}

注:上述这种写法在每个方法上都要写上注解,产生大量重复工作,故可以将@RequestMapping(“/user”)写在方法对应的控制器的类上方,去掉功能留下模块名user,把@RequestMapping(“/user”)称为请求路径的前缀

@Controller
//类上方配置的请求映射与方法上面配置的请求映射连接在一起,形成完整的请求映射路径
@RequestMapping("/user")
public class UserController {
    //请求路径映射
    @RequestMapping("/save")
    @ResponseBody
    public String save(){
        System.out.println("user save ...");
        return "{'module':'user save'}";
    }
    //请求路径映射
    @RequestMapping("/delete")
    @ResponseBody
    public String delete(){
        System.out.println("user delete ...");
        return "{'module':'user delete'}";
    }
}

总结:
请求映射路径
名称:@RequestMapping
类型:方法注解 类注解
位置:SpringMVC控制器方法定义上方
作用:设置当前控制器方法请求访问路径,如果设置在类上统一设置当前方法请求访问路径前缀
范例:

@Controller
@RequestMapping("/user")
public class UserController{
	@RequestMapping("/save")
	@ResponseBody
	public String save(){
		System.out.println("user save ...");
		return "{'module':'user save'}";
	}
}

属性:
value(默认):请求访问路径,或访问路径前缀

3.2请求方式

  1. Get请求
    GET发送单个参数:
    在这里插入图片描述
    Get接收单个参数:
    controller里方法形参名必须和请求参数名一致:
@Controller
public class UserController {
 
    @RequestMapping("/commonParam")
    @ResponseBody
    public String commonParam(String name){
        System.out.println("普通参数传递 name ==> "+name);
        return "{'module':'commonParam'}";
    }
}

GET发送多个参数
在这里插入图片描述
Get接收多个参数:

@Controller
public class UserController {
 
    @RequestMapping("/commonParam")
    @ResponseBody
    public String commonParam(String name){
        System.out.println("普通参数传递 name ==> "+name);
        return "{'module':'commonParam'}";
    }
}
  1. Post请求
    Post请求的参数属于请求体类,在Postman中需要选择Body
    普通参数:formbiaodanpost请求传参,表单参数名与形参变量名相同,定义形参即可接收参数
    在这里插入图片描述
    再选择x-www-form-urlencoded
    在这里插入图片描述
    最后添加key-value的值
    在这里插入图片描述
    Post接收参数与Get一样:
@Controller
public class UserController {
 
    @RequestMapping("/commonParam")
    @ResponseBody
    public String commonParam(String name){
        System.out.println("普通参数传递 name ==> "+name);
        return "{'module':'commonParam'}";
    }
}

乱码处理
在servlet容器配置类中重写getServletFilters过滤器方法,为web容器添加过滤器并指定字符集,Spring-web包中提供了专用的字符过滤器

public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
    protected Class<?>[] getRootConfigClasses() {
        return new Class[0];
    }

    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{SpringMvcConfig.class};
    }

    protected String[] getServletMappings() {
        return new String[]{"/"};
    }

    //乱码处理
    @Override
    protected Filter[] getServletFilters() {
        CharacterEncodingFilter filter = new CharacterEncodingFilter();
        filter.setEncoding("UTF-8");
        return new Filter[]{filter};
    }
}

注:这种处理方法仅针对Post方式,而Get请求更为复杂
所有Tomcat版本Post请求都中文乱码
CharacterEncodingFilter是在spring-webmvc包中

3.3请求参数

3.3.1参数种类

①普通参数
②POJO类型参数
③嵌套POJO类型参数
④数组类型参数
⑤集合类型参数

3.3.2普通参数

url 地址传参,地址参数名与形参变量名相同,定义形参即可接收参数

@RequestMapping("/commoParam")
@ResponseBody
public String commonParam(String name,int age){
	Stystem.out.println("普通参数传递 name ==> " + name );
	System.out.println("普通参数 age ==> " + age);
	return "{'module':'common param'}";
}

在这里插入图片描述
如果形参与地址参数名不一致该如何解决?
发送请求与参数:

http://localhost/commonParamDifferentName?name=张三&age=18

后台接收参数:

@RequestMapping("/commonParamDifferentName")
@ResponseBody
public String commonParamDifferentName(String userName , int age){
    System.out.println("普通参数传递 userName ==> "+userName);
    System.out.println("普通参数传递 age ==> "+age);
    return "{'module':'common param different name'}";
}

因为前端给的是name,后台接收使用的是userName,两个名称对不上,导致接收数据失败:
在这里插入图片描述
解决方案:使用@RequestParam注解
名称:@RequestParam
类型:形参注释
位置:SpringMVC控制器方法形参定义前面
作用:绑定请求参数与处理器方法形参间的关系
范例:

@RequestMapping("/commonParamDifferentName")
@ResponseBody
public String commonParamDifferentName(@RequestParam("name") String userName , int age){
 	System.out.println("普通参数 userName ==>" + userName);
 	System.out.println("普通参数 userName ==>" + age);
 	return "{'module':'common param different name'}";
}

参数:
required:是否为必传参数
defaultValue:参数默认值
这里个人的理解是给userName起别名,从而达到解耦的目的

@RequestMapping("/commonParamDifferentName")
    @ResponseBody
    public String commonParamDifferentName(@RequestPaam("name") String userName , int age){
        System.out.println("普通参数传递 userName ==> "+userName);
        System.out.println("普通参数传递 age ==> "+age);
        return "{'module':'common param different name'}";
    }

注:写上@RequestParam注解框架就不需要自己去解析注入,能提升框架处理性能

3.3.3POJO参数类型

简单数据类型一般处理的是参数个数比较少的请求,如果参数比较多,那么后台接收参数的时候就比较复杂,这个时候我们可以考虑使用POJO数据类型。
POJO参数:请求参数名与形参对象属性名相同,定义POJO类型形参即可接收参数,按照形参层次结构关系即可接收嵌套POJO属性参数
此时需要使用前面准备好的POJO类,先来看下User

private String name;
    private int age;

    private Address address;


    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", address=" + address +
                '}';
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

发送请求和参数:
在这里插入图片描述

3.3.4嵌套POJO参数

若POJO对象中嵌套了其他的POJO类,如在User类中有Address属性,而这里Address类属性引用类型

public class User {
    private String name;
    private int age;
    private Address address;
}
public class Address {
    private String province;
    private String city;
}

发送请求和参数
这里内嵌的pojo类在发送请求时参数要写成内嵌类对象.属性名
在这里插入图片描述
后台接收参数:
嵌套POJO参数:与POJO参数要求一样:请求参数名与形参对象属性名相同,形参依然是传外层类的对象

  //嵌套POJO参数:嵌套属性按照层次结构设定名称即可完成参数传递
    @RequestMapping("/pojoContainPojoParam")
    @ResponseBody
    public String pojoContainPojoParam(User user){
        System.out.println("pojo嵌套pojo参数传递 user ==> "+user);
        return "{'module':'pojo contain pojo param'}";
    }
3.3.5数组参数

数组参数:请求参数名与形参数组名相同,且请求参数为多个,定义数组类型即可接收参数
发送请求和参数:
在这里插入图片描述
后台接收参数:

 //数组参数
    @RequestMapping("/arrayParam")
    @ResponseBody
    public String arrayParam(String[] likes){
        System.out.println("数组参数传递 arrayParam ==> "+Arrays.toString(likes));
        return "{'module':'array param'}";
    }
3.3.6集合类型参数

集合保存普通参数:请求参数名与形参集合对象名称相同且请求参数为多个,@RequestParam绑定参数关系
集合直接做形参会报错
原因解释:SpringMVC首先会将List看成POJO对象,会为其创建一个对象并把前端的数据封装完send进对象中,但是List是一个接口没有构造方法也即无法创建对象,所以报错。
解决方法:使用**@RequestParam**注解绑定参数关系
发送请求与参数:
在这里插入图片描述
后台接收参数:

//集合参数
    @RequestMapping("/listParam")
    @ResponseBody
    public String listParam(@RequestParam List<String> likes){
        System.out.println("集合参数传递 arrayParam ==> "+likes);
        return "{'module':'list param'}";
    }

3.4请求参数(传递json数据)

  1. json数组
  2. json对象(POJO)
  3. json数组(POJO)
3.4.1json数组

具体流程如下:
①pom.xml添加依赖jackson-databind
SpringMVC默认使用的是jackson来处理json的转换
步骤②使用PostMan发送json数据
在这里插入图片描述
写入json数据
在这里插入图片描述
③:开启SpringMVC注解支持@EnableWebMvc

在SpringMVC的配置类中开启SpringMVC的注解支持,包含了将JSON转换成对象的功能

@Configuration
@ComponentScan("com.itheima.controller")
//开启json数据类型自动转换
@EnableWebMvc
public class SpringMvcConfig {
}

在这里插入图片描述
④在形参前加上@RequestBody
这里仍然默认给:List造对象然后传数据进去,但是json数据存储在请求体中,所以无法使用@RequestParam注解,这里使用@RequestBody

    @RequestMapping("/listParamForJson")
    @ResponseBody
    public String listParamForJson(@RequestBody List<String> likes){
        System.out.println("list common(json)参数传递 list ==> "+likes);
        return "{'module':'list common for json param'}";
    }
3.4.2json对象数据

在servlet中
①Servlet接收json对象:
1.Servlet的getParameter()获取String形式的json对象
2.fastjson的JSON.parseObject()将json对象转为实体类对象
②Servlet响应JSON对象到前端:
1.将实体类对象通过fastjson的JSON.toJSONString方法转为String类型
2.response.getWriter().write(jsonStr)
发送json对象数据
在这里插入图片描述
后台controller接收参数:
使用@RequestBody注解将这里的形参实体类对象User直接转换JSON对象

    //PoJO参数:json格式
    @RequestMapping("/pojoParamForJson")
    @ResponseBody
    public String pojoParamForJson(@RequestBody User user){
        System.out.println("pojo(json)参数传递 list ==> "+user);
        return "{'module':'pojo for json param'}";
    }

注意事项:@EnableWebMvc功能强大,该注解整合了多个功能,此处仅使用其中一部分功能,即json数据进行自动类型转换
注解:
名称:@EnableWebMvc
类型:配置类注解
位置:SpringMVC配置定义上方
作用:开启SpringMVC多项负责功能
范例:

@Configuration
@ComponentScan("com.itheima.controller")
//开启json数据类型自动转换
@EnableWebMvc
public class SpringMvcConfig {
}

名称:@RequestBody
类型:形参注解
位置:SpringMVC控制器方法形参定义前面
作用:将请求中请求体所包含的数据传递给请求参数,此注解一个处理器方法只能使用一次
范例:

@RequestMapping("/listParamForJson")
@ResponseBody
public String listParamForJson(@RequestBody List<String> likes){
 	System.out.println("list common(json)参数传递 list ==>"+ likes);
 	return "{'moudle':'list common for json param'}";
}

3.4.3json对象集合参数

发送对象集合参数与请求
在这里插入图片描述
后台接收参数:

    //集合参数:json格式
    @RequestMapping("/listPojoParamForJson")
    @ResponseBody
    public String listPojoParamForJson(@RequestBody List<User> list){
        System.out.println("list pojo(json)参数传递 list ==> "+list);
        return "{'module':'list pojo for json param'}";
    }

总结:
SpringMVC接收json参数的过程如下:

  1. 导入jackson包
  2. 使用PostMan发送JSON数据
  3. 开启SpringMVC注解驱动,在配置类上添加@EnableWebMvc注解
  4. Controller方法的参数前添加@RequestBody注解
3.4.4@RequestBody与@RequestParam的区别

区别:
@RequestParam用于接收url地址传参,表单传参【application/x-www-form-urlencoded
@RequestBody用于接收json数据【application/json
应用:
后期开发中,发送json格式数据为主,@RequestBody应用较广
如果发送非json格式数据,选用@RequestParam接收请求参数

3.4.4日期类型参数传递

日期类型数据基于系统不同格式也不尽相同
2088-08-18
2088/08/18
08/18/2088
对于2088/08/18这种格式,controller可以自动转换成Date对象,其他格式其无法转为Date类型对象
需要根据不同的日期格式设置不同的接收方式
步骤1:编写方法接收日期数据
在UserController类中添加方法,把参数设置为日期类型

@RequestMapping("/dataParam")
@ResponseBody
public String dataParam(Date date)
    System.out.println("参数传递 date ==> "+date);
    return "{'module':'data param'}";
}

步骤2:启动Tomcat服务器
查看控制台是否报错,如果有错误,先解决错误。
步骤3:使用PostMan发送请求
使用PostMan发送GET请求,并设置date参数
在这里插入图片描述
步骤4:查看控制台
在这里插入图片描述
步骤5:更换日期格式
为了便于观测不同日期格式程序运行的结果,在方法中多添加一个日期参数

@RequestMapping("/dataParam")
@ResponseBody
public String dataParam(Date date,Date date1)
    System.out.println("参数传递 date ==> "+date);
    return "{'module':'data param'}";
}

发送请求,携带两个不同的日期格式
在这里插入图片描述
发送请求和数据后,页面会报400,控制台会报出一个错误
从错误信息可以看出,错误的原因是在将2088-08-08转换成日期类型的时候失败了,原因是SpringMVC默认支持的字符串转日期的格式为yyyy/MM/dd,而我们现在传递的不符合其默认格式,SpringMVC就无法进行格式转换,所以报错。

解决方案也比较简单,需要使用@DateTimeFormat

@RequestMapping("/dataParam")
@ResponseBody
public String dataParam(Date date,
                        @DateTimeFormat(pattern="yyyy-MM-dd") Date date1)
    System.out.println("参数传递 date ==> "+date);
	System.out.println("参数传递 date1(yyyy-MM-dd) ==> "+date1);
    return "{'module':'data param'}";
}

注:pattern用于指定具体的日期格式
步骤6:携带时间的日期
尝试发送一个携带时间的日期,看下SpringMVC该如何处理
先修改UserController类,添加第三个参数

@RequestMapping("/dataParam")
@ResponseBody
public String dataParam(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(yyyy-MM-dd) ==> "+date1);
	System.out.println("参数传递 date2(yyyy/MM/dd HH:mm:ss) ==> "+date2);
    return "{'module':'data param'}";
}

发送请求,携带三个不同格式的日期
在这里插入图片描述
重新启动服务器,重新发送请求测试,SpringMVC就可以将日期时间的数据进行转换
在这里插入图片描述
分析:
①这里类型转换是由SpeingMVC完成的,是利用了类型转换器Convert接口

public interface Converter<S,T>{
	@Nullable
	T convert(S source);
}

请求参数年龄数据(String>>Integer)
日期格式转换 (String >> Date)
②**@EnableWebMvc功能之一:根据类型匹配对应类型转换器**

4响应

1.响应页面
2.响应数据:①文本数据;②json数据(重点)

4.1响应jsp页面[了解]

设置返回页面

@Controller
public class UserController {
 
    @RequestMapping("/toJumpPage")
    //注意
    //1.此处不可以加@ResponseBody,否则会将page.jsp当字符串返回前端
    //2.这里的返回值是String
    public String toJumpPage(){
        System.out.println("跳转页面");
        return "page.jsp";
    }
 
}

4.2响应文本数据[了解]

设置返回文本内容

@Controller
public class UserController {
	@RequestMapping("/toText")
    //与响应页面不同,这里的注解不可以省略,否则会把response text当前页面名称,如果找不到该页面就会报404
    @ResponseBody
    public String toText(){
        System.out.println("返回纯文本数据");
        return "response text";
    }
 
}

4.3响应JSON数据

响应POJO对象:直接返回对象
这里必须加上@ResponseBody,因为对于SpringMVC来说返回值的位置默认跳转页面,而我们希望他能够按照我们想要的类型给出返回值,这时候我们就要修改响应的内容,需要自定义响应内容,就用到@ResponseBody。

 @RequestMapping("/toJsonPOJO")
    @ResponseBody
    public User toJsonPOJO(){
        System.out.println("返回json对象数据");
        User user = new User();
        user.setName("itcast");
        user.setAge(15);
        return user;
    }

注:转json对象这件事情不是SpringMVC做的,而是我们导入的Jackson坐标来实现的

4.4返回Json集合对象

加上@ResponseBody,返回集合

@Controller
public class UserController {
 
    @RequestMapping("/toJsonList")
    @ResponseBody
    public List<User> toJsonList(){
        System.out.println("返回json集合数据");
        User user1 = new User();
        user1.setName("传智播客");
        user1.setAge(15);
 
        User user2 = new User();
        user2.setName("黑马程序员");
        user2.setAge(12);
 
        List<User> userList = new ArrayList<User>();
        userList.add(user1);
        userList.add(user2);
 
        return userList;
    }
 
}

注解:
名称:@ResponseBody
类型:方法注解
位置:SpringMVC控制器方法定义上方
作用:设置当前控制器方法响应内容为当前返回值,无需解析>>>>>>>>>>设置当前控制器返回值作为响应体
范例:

@RequestMapping("/save")
@ResponseBody
public String save(){
	System.out.print("Save...");
	return "{'info':'springmvc'}";
}

注:加上@ResponseBody注解之后不同的返回值类型会产生不同的响应类型
方法的返回值为字符串,会将其作为文本内容直接响应给前端
方法的返回值为对象,会将对象转换成JSON响应给前端

上述的转换不再是Convert接口实现的,而是HttpMessageConverter接口实现的

public interface HttpMessageConverter<T> {
    boolean canRead(Class<?> var1, @Nullable MediaType var2);

    boolean canWrite(Class<?> var1, @Nullable MediaType var2);

    List<MediaType> getSupportedMediaTypes();

    T read(Class<? extends T> var1, HttpInputMessage var2) throws IOException, HttpMessageNotReadableException;

    void write(T var1, @Nullable MediaType var2, HttpOutputMessage var3) throws IOException, HttpMessageNotWritableException;
}

注:该接口专用于转换Http消息

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值