详细的描述了SpringMVC中的请求与响应
SpringMVC概述
SpringMVC是一种基于Java实现MVC模型的轻量级web框架
优点
- 使用简单,开发便捷(相比于Servlet)
- 灵活性强
样例
样例代码
- 使用SpringMVC技术需要先导入SpringMIVC坐标与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功能)
// 2.定义Controller// 2.1 使用Controller定义Bean@Controllerpublic class UserController { // 2.2 设置当前操作的访问路径 @RequestMapping("/save") // 2.3 设置当前操作的返回值类型 @ResponseBody public String save(){ System.out.println("user save..."); return "{'moudle' : 'springmvc'}"; }}- 初始化SpringMVC环境(同Spring环境),设定SpringMVC加载对应的bean
// 3.创建springmvc的配置文件,加载controller对应的Bean@Configuration@ComponentScan("com.wang.controller")public class SpringMvcConfig {}- 初始化Servlet容器,加载SpringMVC环境,并设置SpringMVC技术处理的请求
// 4.定义一个Servlet容器启动的配置类,在里面加载spring的配置public class ServletContainerInitConfig extends AbstractDispatcherServletInitializer {
//加载springmvc容器配置 protected WebApplicationContext createServletApplicationContext() { AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext(); ctx.register(SpringMvcConfig.class); return ctx; }
//设置哪些请求归属springmvc处理 protected String[] getServletMappings() { return new String[]{"/"}; }
//加载spring容器配置 protected WebApplicationContext createRootApplicationContext() { AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext(); ctx.register(SpringConfig.class); return ctx; }}上述案例中用到的注解说明:
- @Controller
类注解,放置于SpringMVC控制器定义上方,作用为设定SpringMVC的核心控制器Bean
- @RequestMapping
方法注解,放置于SpringMVC控制器方法上方,作用为设定当前控制器方法的请求访问路径
- @ResponseBody
方法注解,放置于SpringMVC控制器方法上方,作用为设置当前控制器方法的响应内容为当前返回值,无需解析
- @ComponentScan
属性1:excludeFilters:排除扫描路径中加载的bean,需要指定类别(type)与具体项(classes)
属性2:includeFilters:加载指定的bean,需要指定类别(type)与具体项(classes)
SpringMVC入门程序开发总结(1+N)
- 一次性工作
- 创建工程,设置服务器,加载工程
- 导入坐标
- 创建web容器启动类,加载SpringMVC配置,并设置SpringMVC请求拦截路径
- SpringMvc核心配置类(设置配置类,扫描controller包,加载Controller控制器bean)
- 多次工作
- 定义处理请求的控制器类
- 定义处理请求的控制器方法,并配置映射路径(@RequestMapping)与返回json数据(@ResponseBody)
工作流程
启动服务器初始化过程
- 服务器启动,执行ServletcontainersInitConfig类,初始化web容器
- 执行createServletApplicationcontext方法,创建了webApplicationContext对象
- 加载SpringMvcConfig
- 执行@ComponentScan加载对应的bean
- 加载UserController,每个@RequestMapping的名称对应一个具体的方法
- 执行getServletMappings方法,定义所有的请求都通过springMVC
单次请求过程
- 发送请求localhost/save
- web容器发现所有请求都经过SpringMVC,将请求交给SpringMVC处理
- 解析请求路径/save
- 由/save匹配执行对应的方法save()
- 执行save()
- 检测到有@ResponseBody直接将save()方法的返回值作为响应求体返回给请求方
问题
因为功能不同,如何避免Spring错误的加载到SpringMVC的bean?
加载Spring控制的bean的时候排除掉SpringMVC控制的bean
SpringMIVC相关bean(表现层bean)
Spring控制的bean
- 业务bean (Service)
- 功能bean (DataSource等)
SpringMVC相关bean加载控制
- SpringMVC加载的bean对应的包均在com.xxx.controller包内
Spring相关bean加载控制
- 方式一:Spring加载的bean设定扫描范围为com.xxx,排除掉controller包内的bean
- 方式二: Spring加载的bean设定扫描范围为精准范围,例如service包、dao包等
- 方式三:不区分Spring与SpringMVC的环境,加载到同一个环境中
方式一如下:
@ComponentScan(value = "com.wang", excludeFilters = @ComponentScan.Filter( type = FilterType.ANNOTATION, classes = Controller.class ))方式二如下:
@ComponentScan({"com.wang.service", "com.wang.dao"})注意:简化开发代码如下:
public class ServletContainerInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override protected Class<?>[] getRootConfigClasses() { return new Class[]{SpringConfig.class}; }
@Override protected Class<?>[] getServletConfigClasses() { return new Class[]{SpringMvcConfig.class}; }
@Override protected String[] getServletMappings() { return new String[]{"/"}; }}请求
设置请求的映射路径
团队多人开发,每人设置不同的请求路径,冲突问题如何解决?
设置模块名作为请求路径前缀
@RequestMapping(“/xxx”)
当写在类上方时,即为统计设置请求路径的前缀,类方法中的@RequestMapping会自动加上前缀
PostMan发送get请求和post请求
get请求
普通参数:url地址传参,地址参数名与形参变量名相同,定义形参即可接收参数
post请求
普通参数:form表单post请求传参,表单参数名与形参变量名相同,定义形参即可接收参数
post请求中文乱码问题:
为web容器添加过滤器并指定字符集,Spring-web包中提供了专用的字符过滤器
//乱码处理@overrideprotected Filter[] getServletFilters(){ CharacterEncodingFilter filter = new CharacterEncodingFilter(); filter.setEncoding("UTF-8"); return new Filter[](filter);}参数种类
若传入的属性名与实体类中的属性名一致,则会自动放入实体类中
样例代码:
//请求参数@Controllerpublic class UserController {
//普通参数:请求参数与形参名称对应即可完成参数传递 @RequestMapping("/commonParam") @ResponseBody public String commonParam(String name ,int age){ System.out.println("普通参数传递 name ==> "+name); System.out.println("普通参数传递 age ==> "+age); return "{'module':'common param'}"; }
//普通参数:请求参数名与形参名不同时,使用@RequestParam注解关联请求参数名称与形参名称之间的关系 @RequestMapping("/commonParamDifferentName") @ResponseBody public String commonParamDifferentName(@RequestParam("name") String userName , int age){ System.out.println("普通参数传递 userName ==> "+userName); System.out.println("普通参数传递 age ==> "+age); return "{'module':'common param different name'}"; }
//POJO参数:请求参数与形参对象中的属性对应即可完成参数传递 @RequestMapping("/pojoParam") @ResponseBody public String pojoParam(User user){ System.out.println("pojo参数传递 user ==> "+user); return "{'module':'pojo param'}"; }
//嵌套POJO参数:嵌套属性按照层次结构设定名称即可完成参数传递 @RequestMapping("/pojoContainPojoParam") @ResponseBody public String pojoContainPojoParam(User user){ System.out.println("pojo嵌套pojo参数传递 user ==> "+user); return "{'module':'pojo contain pojo param'}"; }
//数组参数:同名请求参数可以直接映射到对应名称的形参数组对象中 @RequestMapping("/arrayParam") @ResponseBody public String arrayParam(String[] likes){ System.out.println("数组参数传递 likes ==> "+ Arrays.toString(likes)); return "{'module':'array param'}"; }
//集合参数:同名请求参数可以使用@RequestParam注解映射到对应名称的集合对象中作为数据 @RequestMapping("/listParam") @ResponseBody public String listParam(@RequestParam List<String> likes){ System.out.println("集合参数传递 likes ==> "+ likes); return "{'module':'list param'}"; }
//集合参数:json格式 //1.开启json数据格式的自动转换,在配置类中开启@EnableWebMvc //2.使用@RequestBody注解将外部传递的json数组数据映射到形参的集合对象中作为数据 @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'}"; }
//POJO参数:json格式 //1.开启json数据格式的自动转换,在配置类中开启@EnableWebMvc //2.使用@RequestBody注解将外部传递的json数据映射到形参的实体类对象中,要求属性名称一一对应 @RequestMapping("/pojoParamForJson") @ResponseBody public String pojoParamForJson(@RequestBody User user){ System.out.println("pojo(json)参数传递 user ==> "+user); return "{'module':'pojo for json param'}"; }
//集合参数:json格式 //1.开启json数据格式的自动转换,在配置类中开启@EnableWebMvc //2.使用@RequestBody注解将外部传递的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'}"; }
//日期参数 //使用@DateTimeFormat注解设置日期类型数据格式,默认格式yyyy/MM/dd @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'}"; }}总结
普通的形参
若形参与请求参数名称相同,则会自动绑定
@RequestParam
可以绑定请求参数与处理器方法形参之间的关系
参数:required:是否为必传参数 defaultValue:参数默认值
Pojo参数
请求参数名与形参对象属性名相同,定义PO30类型形参即可接收参数
嵌套的Pojo参数
请求参数名与形参对象属性名相同,按照对象层次结构关系即可接收嵌套POJo属性参数
数组参数
请求参数名与形参对象属性名相同且请求参数为多个,定义数组类型形参即可接收参数
集合保存普通参数
请求参数名与形参集合对象名相同且请求参数为多个,@RequestParam绑定参数关系
json 数据参数
四个步骤:
- pom.xml中添加json坐标
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.9.0</version></dependency>- 主配置类中加入注解
@EnableWebMvc
开启由json对象装换位对象的功能
- postman中传入参数
- 在参数前面加上@RequestBody
- json数组
["game","music","hobby"]- json对象(Pojo)
{ "name":"wang", "age":15, "address":{ "province":"beijing", "city":"beijing" }}- json数组(Pojo)
[ {"name":"wang","age":9}, {"name":"nine","age":99}]@RequestBody与@RequestParam区别
- 区别
- @RequestParam用于接收url地址传参,表单传参【application/x-www-form-urlencoded】
- @RequestBody用于接收json数据【application/json】
- 应用
- 后期开发中,发送json格式数据为主,@RequestBody应用较广
- 如果发送非json格式数据,选用@Requestparam接收请求参数
日期格式参数
@DateTimeFormat(patter=“yyyy-MM-dd”)
指定日期的格式
类型转换器
- Convert接口
public interface Converter<S, T> { @Nullable T convert(S var1);}响应
- 响应页面
- 响应数据
- 文本数据
- json数据
样例代码:
@Controllerpublic class UserController {
//响应页面/跳转页面 //返回值为String类型,设置返回值为页面名称,即可实现页面跳转 @RequestMapping("/toJumpPage") public String toJumpPage(){ System.out.println("跳转页面"); return "page.jsp"; }
//响应文本数据 //返回值为String类型,设置返回值为任意字符串信息,即可实现返回指定字符串信息,需要依赖@ResponseBody注解 @RequestMapping("/toText") @ResponseBody public String toText(){ System.out.println("返回纯文本数据"); return "response text"; }
//响应POJO对象 //返回值为实体类对象,设置返回值为实体类类型,即可实现返回对应对象的json数据,需要依赖@ResponseBody注解和@EnableWebMvc注解 @RequestMapping("/toJsonPOJO") @ResponseBody public User toJsonPOJO(){ System.out.println("返回json对象数据"); User user = new User(); user.setName("itcast"); user.setAge(15); return user; }
//响应POJO集合对象 //返回值为集合对象,设置返回值为集合类型,即可实现返回对应集合的json数组数据,需要依赖@ResponseBody注解和@EnableWebMvc注解 @RequestMapping("/toJsonList") @ResponseBody public List<User> toJsonList(){ System.out.println("返回json集合数据"); User user1 = new User(); user1.setName("Tom"); user1.setAge(15);
User user2 = new User(); user2.setName("Jerry"); user2.setAge(12);
List<User> userList = new ArrayList<User>(); userList.add(user1); userList.add(user2);
return userList; }}@ResponseBody
方法注解,SpringMVC控制器方法定义上方,设置当前控制器方法响应内容为当前返回值,无需解析
内部是由类型转换器 HttpMessageConverter 接口发挥作用