目录
SpringMVC概述
SpringMVC快速入门
第一步:创建Maven工程,并导入相关的依赖
第二步:创建控制器类
第三步:初始化SpringMVC环境
第四步:创建Tomcat的Servlet容器配置类
第五步:导入tomcat插件,并设置war方式打包
第六步:启动
测试
注意:需要在main目录下面新建一个webapp目录
请求路径优化
指定请求方法
请求参数处理
六种常规类型
第一种:普通请求参数
第二种:pojo类型请求参数
第三种:数组类型请求参数
第四种:List集合类型
第五种:map集合类型
日期请求参数传递
文件类型参数传递
1.先导入依赖
2.编写文件解析器,并交给SringMVC管理(第三方bean)使用注解@Bean
JSON类型参数传递
第一步:导入解析json对象的依赖
第二步:让SpringMVC开启辅助功能,如日期类型转换,json类型转换
第三步:编写Controller类,并使用注解@RequestBody,一个方法只能使用一次(解析前端传来的json对象)
编辑 数组类型的pojo类型
处理中文请求乱码问题
1.GET请求乱码问题
2.解决POST请求乱码
响应数据
响应一个页面
响应JSON对象,也要使用@Response注解
响应JSON对象数组
RESful风格
SpringMVC概述
MVC(Model View Controller),一种用于创建web应用程序的表现层的模式
1.Model(模型):数据模型,用于封装数据
2.View(视图):页面视图,用于展示数据
- jsp
- html
3.Controller(控制器):处理用户交互的调度器,用于根据用户需求处理程序逻辑
SpringMVC快速入门
第一步:创建Maven工程,并导入相关的依赖
springMVC的依赖
<!-- springMVC的依赖--><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.2.10.RELEASE</version></dependency>
servlet-api
注意:需要指定作用范围
<dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>3.1.0</version> <!-- 需要指定作用范围--><scope>provided</scope></dependency>
我们可以发现springMVC的依赖包括了spring-context的依赖
第二步:创建控制器类
/* 1.需要交给spring管理 2.定义处理请求的方法 3.设置当前方法的访问路径 4.设置返回数据类型为String*/ @Controller public class UserController {@RequestMapping("/save")@ResponseBodypublic String save(){System.out.println("user save");return "springMVC";} }
创建控制器类也需要四步:
第一步:需要交给spring管理,即添加@Controller注解
第二步:定义处理请求的方法-->public String save()
第三步:设置当前方法的访问路径-->使用注解@RequestMapping("/save")
第四步:设置返回数据类型为String-->使用注解@ResponseBody
第三步:初始化SpringMVC环境
这是一个设置扫描范围的配置类(主配置类)
@Configuration @ComponentScan("com.hhh") public class SpringMvcConfig { }
第四步:创建Tomcat的Servlet容器配置类
public class ServletContainerInitConfig extends AbstractDispatcherServletInitializer {//创建SpringMVC容器(spring容器)@Overrideprotected WebApplicationContext createServletApplicationContext() {//ApplicationContext ctx =new AnnotationConfigApplicationContext();//加载配置类,创建SpringMVC容器AnnotationConfigWebApplicationContext ctx =new AnnotationConfigWebApplicationContext();ctx.register(SpringMvcConfig.class);return ctx;}//设置哪些请求交给springMVC管理@Overrideprotected String[] getServletMappings() {//这里设置了所有请求都交给SpringMVC管理return new String[]{"/"};}//创建Spring容器@Overrideprotected WebApplicationContext createRootApplicationContext() {return null;} }
第五步:导入tomcat插件,并设置war方式打包
<build><plugins><plugin><groupId>org.apache.tomcat.maven</groupId><artifactId>tomcat7-maven-plugin</artifactId><version>2.1</version><configuration><!-- 指定端口 --><port>8080</port><!-- 请求路径 --><path>/</path> <!-- <!–这个名称需要,在maven插件中显示应用名称–>--> <!-- <server>tomcat7</server>--></configuration></plugin></plugins></build>
<packaging>war</packaging>
完整pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.hhh</groupId><artifactId>spring_day6_MVC</artifactId><version>1.0-SNAPSHOT</version><packaging>war</packaging><properties><maven.compiler.source>21</maven.compiler.source><maven.compiler.target>21</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>3.1.0</version> <!-- 需要指定作用范围--><scope>provided</scope></dependency> <!-- springMVC的依赖--><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.2.10.RELEASE</version></dependency></dependencies><build><plugins><plugin><groupId>org.apache.tomcat.maven</groupId><artifactId>tomcat7-maven-plugin</artifactId><version>2.1</version><configuration><!-- 指定端口 --><port>8080</port><!-- 请求路径 --><path>/</path> <!-- <!–这个名称需要,在maven插件中显示应用名称–>--> <!-- <server>tomcat7</server>--></configuration></plugin></plugins></build></project>
第六步:启动
点击加号,选择maven,然后再Run里填写tomcat7:run,最后点击apply
结果:
测试
启动成功
注意:需要在main目录下面新建一个webapp目录
请求路径优化
添加一个新的类
@Controller public class BookController {@RequestMapping("/save")@ResponseBodypublic String save(){System.out.println("book save");return "bookSpringMVC";} }
请求路径与之前的一样,会报错
所以这样添加目录
但是这样子每个方法都要添加一级目录,比较麻烦,所以我们可以在这个类上使用注解@RequestMapping注解
@Controller @RequestMapping("/book") public class BookController {@RequestMapping("/save")@ResponseBodypublic String save(){System.out.println("book save");return "bookSpringMVC";} }
@Controller @RequestMapping("/user") public class UserController {@RequestMapping("/save")@ResponseBodypublic String save(){System.out.println("user save");return "springMVC";} }
测试:
指定请求方法
现在我们使用的式@RequestMapping注解,这个注解支持GET,POST请求,但是我们要指定请求方法要怎么做呢?
@Controller @RequestMapping("/book") public class BookController {@RequestMapping(value = "/save",method = RequestMethod.GET)//这样子只能使用GET请求@ResponseBodypublic String save(){System.out.println("book save");return "bookSpringMVC";} }
请求参数处理
六种常规类型
第一种:普通请求参数
请求参数的key值与方法的形参名一致
后端:
@Controller public class ParamController {//普通类型参数@RequestMapping("/commonParam")@ResponseBodypublic String commonParam(@RequestParam("name") String username, Integer age){//请求参数名和变量名一致即可System.out.println("username="+username);System.out.println("age="+age);return "CommonParam";}}
使用postman向后端发送请求
如果前端请求参数名字与后端形参名不一致时,使用@RequestParam注解。
SpringMVC会自动把String类型的age转换成Integer类型
第二种:pojo类型请求参数
pojo类的成员变量名字与前端的key值一致
User类
public class User {private String name;private Integer age;private Address address;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 Address getAddress() {return address;}public void setAddress(Address address) {this.address = address;}@Overridepublic String toString() {return "User{" +"name='" + name + '\'' +", age=" + age +", address=" + address +'}';} }
Address类型
public class Address {private String province;private String city;public String getProvince() {return province;}public void setProvince(String province) {this.province = province;}public String getCity() {return city;}public void setCity(String city) {this.city = city;}@Overridepublic String toString() {return "Address{" +"province='" + province + '\'' +", city='" + city + '\'' +'}';} }
后端:
@Controller public class ParamController {//pojo嵌套类型@RequestMapping("/pojoContainPojoParam")@ResponseBodypublic String pojoContainPojoParam(User user){System.out.println(user);return "pojoContainPojoParam";}
前端:
可以发现如果成员变量也是pojo类型,就要使用成员变量名.成员变量名的方法
结果:
原理:SpringMVC会使用构造器实例化出一个pojo类对象,即User对象(new User()),然后使用User类里的setXxx()方法进行赋值,如果没有构造器会报错,没有set方法那么这个成员变量就为空null值
如果使用注解@RequestParam
就会报错:
因为@RequestParam是直接把请求参数与形参进行绑定,并直接赋值,这样一来User类型对象并没有实例化,所以就会报错
第三种:数组类型请求参数
前端使用多个相同名字的key值与形参变量名一致
@Controller public class ParamController {//数组类型@RequestMapping("/arrayParam")@ResponseBodypublic String arrayParam(String[]list){System.out.println(Arrays.toString(list));return "arrayParam";}}
前端:
结果:
第四种:List集合类型
@Controller public class ParamController {//集合类型@RequestMapping("/listParam")@ResponseBodypublic String listParam(@RequestParam List<String>list){//因为List不是简单类型,所以springMVC会直接把List看成pojo类型,然后会实例化list,但是List集合没有构造器,就会报错//所以添加@RequestParam注解,这样一来spring会直接给list赋值,而不是实例化去使用set()方法System.out.println(list);return "listParam";}}
前端:
可以发现我们后端的形参中使用了@RequestParam注解,因为这个注解的作用就是绑定形参变量,直接进行赋值,因为List集合不是简单类型,所以SpringMVC会把List集合看出pojo类型,会先实例化List集合再进行set方法赋值,但是List集合并没有构造器,因此不加@RequestParam注解就会报错:
第五种:map集合类型
@Controller public class ParamController {//map集合类型@RequestMapping("/mapParam")@ResponseBodypublic String mapParam(@RequestParam Map<String,String> map){//@RequestParam把请求参数与形参绑定,直接赋值//System.out.println(map);map.forEach((key,value)-> System.out.println(key+"->"+value));return "mapParam";} }
前端:
结果:
日期请求参数传递
@Controller public class DateController {@RequestMapping("/dateParam")@ResponseBodypublic String dateParam(Date date){System.out.println(date);return "dateParam";} }
前端:
结果:
可以发现时期使用的是/来间隔,如果使用-来间隔,会报错:
不能把String类型转换成Date类型,所以我们要使用注解@DateTimeFormat的pattern属性来指定日期类型格式
@Controller public class DateController {@RequestMapping("/dateParam")@ResponseBodypublic String dateParam(Date date,@DateTimeFormat(pattern = "yyyy-MM-dd") Date date1){System.out.println(date);System.out.println(date1);return "dateParam";} }
如果要运行成功,还需要再主配置类中添加@EnableWebMvc,让SpringMVC开启辅助功能
@Configuration @ComponentScan("com.hhh") @EnableWebMvc//让SpringMVC开启辅助功能 public class SpringMvcConfig { }
结果:
文件类型参数传递
1.先导入依赖
<!-- 文件解析的依赖--><dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>1.3.3</version></dependency>
2.编写文件解析器,并交给SringMVC管理(第三方bean)使用注解@Bean
@Configuration @ComponentScan("com.hhh") @EnableWebMvc//让SpringMVC开启辅助功能 public class SpringMvcConfig {//配置文件解析器,并交给SpringMVC管理@Bean("multipartResolver")//这个解析器类型的Bean id必须是multipartResolver,源码是通过id名来获取bean的public MultipartResolver multipartResolver(){CommonsMultipartResolver commonsMultipartResolver=new CommonsMultipartResolver();commonsMultipartResolver.setMaxUploadSize(1024*1024);//单位是字节(byte)//设置文件最大为1MBreturn commonsMultipartResolver;} }
注意:这个解析器类型的Bean id必须是multipartResolver,源码是通过id名来获取这个类型的bean
后端
@Controller public class FileController {@RequestMapping("/fileParam")@ResponseBodypublic String fileParam(MultipartFile file) throws IOException {if(!file.isEmpty()){file.transferTo(new File("D://test.txt"));//把文件另存为}return "fileParam";} }
前端
请求方法只能选择post,文件类型要选择form-data,其他类型选择的是右边那个长的
结果:
D盘出现该文件,成功
JSON类型参数传递
第一步:导入解析json对象的依赖
<!-- 解析json的依赖--><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.9.0</version></dependency>
第二步:让SpringMVC开启辅助功能,如日期类型转换,json类型转换
@Configuration @ComponentScan("com.hhh") @EnableWebMvc//让SpringMVC开启辅助功能,如日期类型转换,json类型转换 public class SpringMvcConfig {//配置文件解析器,并交给SpringMVC管理@Bean("multipartResolver")//这个解析器类型的Bean id必须是multipartResolver,源码是通过id名来获取bean的public MultipartResolver multipartResolver(){CommonsMultipartResolver commonsMultipartResolver=new CommonsMultipartResolver();commonsMultipartResolver.setMaxUploadSize(1024*1024);//单位是字节(byte)//设置文件最大为1MBreturn commonsMultipartResolver;} }
第三步:编写Controller类,并使用注解@RequestBody,一个方法只能使用一次(解析前端传来的json对象)
@Controller public class JsonController {@RequestMapping("/pojoParamForJson")@ResponseBodypublic String pojoParamForJson(@RequestBody User user){System.out.println(user);return "pojoParamForJson";} }
前端
结果:
数组类型的pojo类型
@RequestMapping("/arrayPojoParam")@ResponseBodypublic String arrayPojoParam(@RequestBody List<User>list){System.out.println(list);return "arrayPojoParam";}
前端
数组使用[]
结果
处理中文请求乱码问题
1.GET请求乱码问题
<build><plugins><plugin><groupId>org.apache.tomcat.maven</groupId><artifactId>tomcat7-maven-plugin</artifactId><version>2.1</version><configuration><!-- 指定端口 --><port>8080</port><!-- 请求路径 --><path>/</path> <!-- <!–这个名称需要,在maven插件中显示应用名称–>--> <!-- <server>tomcat7</server>--><uriEncoding>utf-8</uriEncoding></configuration></plugin></plugins></build>
添加<uriEncoding>utf-8</uriEncoding>
2.解决POST请求乱码
为web容器添加过滤器并指定字符集
public class ServletContainerInitConfig extends AbstractDispatcherServletInitializer {//创建SpringMVC容器(spring容器)@Overrideprotected WebApplicationContext createServletApplicationContext() {//ApplicationContext ctx =new AnnotationConfigApplicationContext();//加载配置类,创建SpringMVC容器AnnotationConfigWebApplicationContext ctx =new AnnotationConfigWebApplicationContext();ctx.register(SpringMvcConfig.class);return ctx;}//设置哪些请求交给springMVC管理@Overrideprotected String[] getServletMappings() {//这里设置了所有请求给SpringMVC管理return new String[]{"/"};}//创建Spring容器@Overrideprotected WebApplicationContext createRootApplicationContext() {return null;}//设置参数编码为utf-8,解决post请求乱码@Overrideprotected Filter[] getServletFilters() {CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();characterEncodingFilter.setEncoding("UTF-8");return new Filter[]{characterEncodingFilter};} }
添加
//设置参数编码为utf-8,解决post请求乱码
@Override
protected Filter[] getServletFilters() {
CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
characterEncodingFilter.setEncoding("UTF-8");
return new Filter[]{characterEncodingFilter};
}
响应数据
响应一个页面
创建一个jsp文件
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head><title>Title</title> </head> <body> <div>hello</div> </body> </html>
@Controller public class ResponseController {//不加@ResponseBody就会去找页面名为page.jsp的页面@RequestMapping("/toPage")public String toPage(){System.out.println("toPage");return "page.jsp";} }
如果加了@ResponseBody
@RequestMapping("/toText")@ResponseBodypublic String toText(){System.out.println("toText");return "page.jsp";}
返回的就是字符串本身
所以@Response注解(使用在方法上)的作用就是设置当前控制器的返回值作为响应体。
不加这个注解就会去找对应名字的页面,并返回给前端
响应JSON对象,也要使用@Response注解
返回类型是对象
@Controller public class ResponseController {@RequestMapping("/toJson")@ResponseBodypublic User toJson(){User user = new User();user.setName("hhh");user.setAge(19);Address address = new Address();address.setProvince("河北");address.setCity("石家庄");user.setAddress(address);return user;}}
响应JSON对象数组
@Controller public class ResponseController {@RequestMapping("/toJsonArray")@ResponseBodypublic List<User> toJsonArray(){User user1 = new User();user1.setName("hhh");user1.setAge(19);Address address = new Address();address.setProvince("河北");address.setCity("石家庄");user1.setAddress(address);User user2 = new User();user2.setName("aaa");user2.setAge(19);Address address2 = new Address();address2.setProvince("河北");address2.setCity("石家庄");user2.setAddress(address2);List<User>list=new ArrayList<>();Collections.addAll(list,user1,user2);return list;}}
注意:跟解析请求JSON对象一样,也要导入json解析所需要的依赖,也需要使用注解@EnableWebMvc//让SpringMVC开启辅助功能,如日期类型转换,json类型转换
RESful风格
@Controller public class UserController {//新增,保存操作@RequestMapping(value = "/users",method = RequestMethod.POST)@ResponseBodypublic String save(){return "save";}//修改,更新@RequestMapping(value = "/users",method = RequestMethod.PUT)@ResponseBodypublic String update(){return "update";}//查询全部@RequestMapping(value = "/users",method = RequestMethod.GET)@ResponseBodypublic String getAll(){return "getAll";}//查询某一个@RequestMapping(value = "/users/{id}",method = RequestMethod.GET)@ResponseBodypublic String getById(@PathVariable("id") Integer id){//通过请求路径获取值,而不是通过请求参数System.out.println("id="+id);return "getById";}//删除某一个@RequestMapping(value = "/users/{id}",method = RequestMethod.DELETE)@ResponseBodypublic String delete(@PathVariable("id") Integer id){System.out.println("id="+id);return "delete";} }
我们可以发现每个@RequestMapping都要写/users,比较麻烦,我们可以直接在类上使用注解 @RequestMapping
每个方法都要写@Response比较麻烦,我们可以直接在类上使用注解 @ResponseBody
@Controller @RequestMapping("/users") @ResponseBody public class UserController {//新增,保存操作@RequestMapping(method = RequestMethod.POST)public String save(){return "save";}//修改,更新@RequestMapping(method = RequestMethod.PUT)public String update(){return "update";}//查询全部@RequestMapping(method = RequestMethod.GET)public String getAll(){return "getAll";}//查询某一个@RequestMapping(value = "/{id}",method = RequestMethod.GET)public String getById(@PathVariable("id") Integer id){//通过请求路径获取值,而不是通过请求参数System.out.println("id="+id);return "getById";}//删除某一个@RequestMapping(value = "/{id}",method = RequestMethod.DELETE)public String delete(@PathVariable("id") Integer id){System.out.println("id="+id);return "delete";} }
然后我们还发现每个@RequsetMapping都要写一个method属性来指定请求方法,比较麻烦,所以,Post请求就使用@PostMapping,以此类推
@ResponseBody和@Controller这两个注解放在一起可以使用@RestController注解来替代
//@Controller //@ResponseBody @RestController @RequestMapping("/users") public class UserController {//新增,保存操作//@RequestMapping(method = RequestMethod.POST)@PostMappingpublic String save(){return "save";}//修改,更新//@RequestMapping(method = RequestMethod.PUT)@PutMappingpublic String update(){return "update";}//查询全部// @RequestMapping(method = RequestMethod.GET)@GetMappingpublic String getAll(){return "getAll";}//查询某一个//@RequestMapping(value = "/{id}",method = RequestMethod.GET)@GetMapping("/{id}")public String getById(@PathVariable("id") Integer id){//通过请求路径获取值,而不是通过请求参数System.out.println("id="+id);return "getById";}//删除某一个//@RequestMapping(value = "/{id}",method = RequestMethod.DELETE)@DeleteMapping("/{id}")public String delete(@PathVariable("id") Integer id){System.out.println("id="+id);return "delete";} }
@Configuration public class SpringWebSupport extends WebMvcConfigurationSupport {//设置静态资源不走SpringMvc控制器@Overrideprotected void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");registry.addResourceHandler("/css/**").addResourceLocations("/css/");} }