SpringMVC学习笔记
1、概述
- 基于java实现的实现mvc模型的轻量级web框架
- SpringMVC是一种表现层的框架技术,用于web层的功能开发,是对Servlet进行的封装
- 主要的作用是接收请求和数据,响应结果,所以如何处理请求和响应是SpringMVC的重点
之前的开发将后端服务器Servlet拆分成三层,分别是
web
、service
和dao
;web层主要由servlet来处理,负责页面请求和数据的收集以及响应结果给前端;service层主要负责业务逻辑的处理;dao层主要负责数据的增删改查操作;servlet处理请求和数据的时候,存在的问题是一个servlet只能处理一个请求 之后针对web层进行了优化,采用MVC设计模式,将其设计为
controller
、view
和Model
;controller负责请求和数据的接收,接收后将其转发给service进行业务处理;service根据需要会调用dao对数据进行增删改查;dao把数据处理完后将结果交给service,service再交给controller;controller根据需求组装成Model和View,Model和View组合起来生成页面转发给前端浏览器(jsp模式) 随着互联网的发展,上面的模式因为是同步调用,性能慢慢的跟不上需求,异步调用慢慢的走到了前台,后端不需要返回view视图;前端如果通过异步调用的方式进行交互,后台就需要将返回的数据转换成json格式进行返回
web controller
view Model
service --> service
dao dao
HTML contorller
CSS <---json--<--model--- service
VUE -----异步请求----> dao
ElementUI
2、依赖说明
2.1 Spring开发MVC:servlet+spring-webmvc+tomcat7
servlet
<!--servlet-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
spring-webmvc
<!--spring-webmvc-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
tomcat7
<!--tomcat7-->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version>
<configuration>
<port>80</port>
<path>/</path>
</configuration>
</plugin>
2.2 SpringBoot开发MVC
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.0</version>
</parent>
<groupId>com.itheima</groupId>
<artifactId>springboot_01_quickstart</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<java.version>8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
3、配置说明
3.1 Spring开发MVC
web3.0 的配置类
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};
}
}
servlet的配置类
public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer {
protected WebApplicationContext createServletApplicationContext() {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(SpringMvcConfig.class);
return ctx;
}
protected String[] getServletMappings() {
return new String[]{"/"};
}
protected WebApplicationContext createRootApplicationContext() {
return null;
}
}
SpringMVC的配置类
@Configuration
@ComponentScan("com.itheima.controller")
//开启json数据类型自动转换
@EnableWebMvc
public class SpringMvcConfig {
}
3.2 SpringBoot开发MVC
引入对应起步依赖即可
3.3 中文乱码问题
- GET请求中文乱码
如果我们传递的参数中有中文:
http://localhost/commonParam?name=张三&age=18
;接收到的参数会出现中文乱码问题。Tomcat8.5以后的版本已经处理了中文乱码的问题,但是IDEA中的Tomcat插件目前只到Tomcat7,所以需要修改pom.xml来解决GET请求中文乱码问题
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version>
<configuration>
<port>80</port><!--tomcat端口号-->
<path>/</path> <!--虚拟目录-->
<uriEncoding>UTF-8</uriEncoding><!--访问路径编解码字符集-->
</configuration>
</plugin>
- POST请求中文乱码
接收参数控制台打印,会发现有中文乱码问题。
通过配置过滤器解决:spring-web包/CharacterEncodingFilter
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};
}
}
4、注解说明
@ComponentScan
- 类定义上方,设置spring配置类扫描路径,用于加载使用注解格式定义的bean
- excludeFilters=排除扫描路径中加载的bean,需要指定类别(type)和具体项(classes);includeFilters=加载指定的bean,需要指定类别(type)和具体项(classes)
@EnableWebMvc
- SpringMVC配置类注解,开启SpringMVC多项辅助功能
@Controller
- SpringMVC控制器类定义上方,设定SpringMVC的核心控制器bean
@RequestMapping
- SpringMVC控制器类或方法定义上方,设置当前控制器方法请求访问路径
- value(默认),请求访问路径
@DateTimeFormat
- SpringMVC控制器方法形参前面,设置事件类型参数的格式
- pattern:指定日期时间格式字符串;"yyyy-MM-dd","yyyy/MM/dd HH:mm:ss"
- 原理
@FunctionalInterface
public interface Converter<S,T>{
@Nullable
T convert(S source);
}
有很多实现类做转换StringToInteger,StringToData
@EnableWebMvc
可以按照类型匹配对应的类型转换器
@ResponseBody
- 写在方法或类上;写在类上,该类的所有方法都有该注解功能
- 设置当前控制器返回值作为响应体
- 相关属性:
- pattern:指定日期时间格式字符串
- 方法的返回值为字符串,会将其作为文本内容直接响应给前端;方法的返回值为对象,会将对象转换成JSON响应给前端
- 内部通过
Converter
接口的实现类完成类型转换,Converter
接口可以实现实体类POJO转json、集合转json
还可以写在SpringMVC控制器方法形参定义前面,将请求中请求体所包含的数据传递给请求参数,此注解一个处理器方法只能使用一次
- 原理
HttpMessageconverter接口
专用转换http的消息
public interface HttpMessageconverter<T>{
boolean canRead(class<?>clazz,@Nullable MediaType mediaType);
boolean canWrite(class<?>clazz,@Nullable MediaType mediaType);
List<MediaType>getSupportedMediaTypes();
T read(class<?extends T> clazz,HttpInputMessage inputMessage)
throws IOException,HttpMessageNotReadableException;
void write(T t, @Nullable MediaType contentType, HttpoutputMessage outputMessage)
throws IOException,HttpMessageNotWritableException;
}
@RequestBody
- SpringMVC控制器方法形参定义前面,将请求中请求体所包含的数据传递给请求参数,此注解一个处理器方法只能使用一次
@RequestParam
- SpringMVC控制器方法形参定义前面。绑定请求参数与处理器方法形参间的关系
- required:是否为必传参数;defaultValue:参数默认值,不指定
defaultValue
属性,可以接受可选的请求参数。如果请求中没有提供该参数,方法参数将为null
。
关于接收参数,我们学过三个注解@RequestBody
、@RequestParam
、@PathVariable
,这三个注解之间的区别和应用分别是什么?
- 区别
- @RequestParam用于接收url地址传参或表单传参【application/x-www-form-urlencoded】
- @RequestBody用于接收json数据【application/json】
- @PathVariable用于接收路径参数,使用{参数名称}描述路径参数
- 应用
- 后期开发中,发送请求参数超过1个时,以json格式为主,@RequestBody应用较广
- 如果发送非json格式数据,选用@RequestParam接收请求参数
- 采用RESTful进行开发,当参数数量较少时,例如1个,可以采用@PathVariable接收请求路径变量,通常用于传递id值
5、请求传递参数
5.1 普通参数
普通的参数,相同名称的能自动映射,通过@RequestParam映射
单个参数:localhost/commonParam?param=xxx
@Controller
@ResponseBody
public Class UserController {
@RequestMapping(value = "/commonParam" , method = RequestMethod.GET)
public String getCommonParam(String param) {
System.out.println("普通参数传递 param ==> "+param);
return "{'module':'commonParam'}";
}
}
多个参数:localhost/commonParam?param=xxx¶m2=xxx
@Controller
@ResponseBody
public Class UserController {
@RequestMapping("/commonParam")
public String getCommonParam(String param,String param2) {
System.out.println("普通参数传递 param ==> "+param);
System.out.println("普通参数传递 param2 ==> "+param2);
return "{'module':'commonParam'}";
}
}
参数不一致:localhost/commonParamDifferentName?name=张三&age=18
@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'}";
}
5.2 实体类参数
简单数据类型一般处理的是参数个数比较少的请求,如果参数比较多,可以使用实体类封装数据
请求参数名与形参对象属性名相同,定义实体类形参即可接收参数
请求参数key的名称要和实体类中属性的名称一致,否则无法封装。
localhost/commonParamDifferentName?name=张三&age=18
请求参数名与形参对象属性名相同,按照对象层次结构关系即可接收嵌套POJO属性参数:localhost/commonParamDifferentName?name=张三&age=18&address.province=beijing
@RequestMapping("/pojoParam")
@ResponseBody
public String pojoParam(User user){
return "{'module':'pojo param'}";
}
5.3 数组类型参数
请求参数名与形参对象属性名相同且请求参数为多个,定义数组类型即可接收参数
同名请求参数可以直接映射到对应名称的形参数组对象中
localhost/param?likes=game&likes=music
@RequestMapping("/arrayParam")
@ResponseBody
public String arrayParam(String[] likes){
System.out.println(Arrays.toString(likes));
return "{'module':'array param'}";
}
5.4 集合类型参数
同名请求参数可以使用@RequestParam注解映射到对应名称的集合对象中作为数据
SpringMVC将List看做是一个POJO对象来处理,将其创建一个对象并准备把前端的数据封装到对象中,但是List是一个接口无法创建对象,使用@RequestParam注解
集合保存普通参数:请求参数名与形参集合对象名相同且请求参数为多个,@RequestParam绑定参数关系
对于简单数据类型使用数组会比集合更简单些。
localhost/param?likes=game&likes=music
@RequestMapping("/listParam")
@ResponseBody
public String listParam(@RequestParam List<String> likes){
System.out.println(likes);
return "{'module':'list param'}";
}
5.5 日期类型参数
localhost/dataParam?date=2088/08/08&date1=2088-08-08&date2=2088/08/08 8:08:08
@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'}";
}
5.6 接收JSON数据类型【重点】
导入jackson依赖;开启SpringMVC注解驱动,在配置类上添加@EnableWebMvc注解,开启json数据类型自动转换
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
@Configuration
@ComponentScan("com.itheima.controller")
//开启json数据类型自动转换
@EnableWebMvc
public class SpringMvcConfig {
}
JSON集合:["value1","value2","value3",...]
使用@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'}";
}
JSON对象数据:
{
"name":"itcast",
"age":15,
"address":{
"province":"beijing",
"city":"beijing"
}
}
@RequestMapping("/pojoParamForJson")
@ResponseBody
public String pojoParamForJson(@RequestBody User user){
System.out.println(user);
return "{'module':'pojo for json param'}";
}
JSON对象数组:[{key1:value1,...},{key2:value2,...}]
[
{"name":"itcast","age":15},
{"name":"itheima","age":12}
]
@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'}";
}
6、响应数据/页面
用户查询,新增,修改,删除的请求等,SpringMVC接收到请求或数据后,经过一定的处理,响应给前端,现在主流的是异步调用,所以主要是响应json数据;
也可以响应页面或文本数据
6.1 响应JSON数据
设置返回值为实体类对象,可以实现返回该对象的json数据
@EnableWebMvc,jackson依赖
@ResponseBody
@Controller
public class UserController {
@RequestMapping("/toJsonPOJO")
@ResponseBody
public User toJsonPOJO(){
User user = new User();
user.setName("lm");
user.setAge(18);
return user;
}
}
@Controller
public class UserController {
@RequestMapping("/toJsonList")
@ResponseBody
public List<User> toJsonList(){
User user1 = new User();
user1.setName("lm");
user1.setAge(20);
User user2 = new User();
user2.setName("lw");
user2.setAge(18);
List<User> userList = new ArrayList<User>();
userList.add(user1);
userList.add(user2);
return userList;
}
}
6.2 响应页面[了解]
- 在Spring MVC中,返回字符串表示要转发或重定向到名为返回字符串的视图。Spring MVC 将会尝试解析这个字符串并找到对应的视图实现,然后渲染为最终的响应页面。
JSP(Java Server Pages)是一种用于创建动态网页的技术。
.jsp
文件是一种文本文件,其中包含HTML以及Java代码片段(或表达式),它们在服务器端被解析和执行,然后生成HTML响应发送给客户端浏览器。所以,JSP 文件实际上是服务器端代码,但最终在客户端浏览器中显示为HTML。
返回名为
page.jsp
的视图:当在Spring MVC中返回字符串"page.jsp"
时,Spring MVC 将查找名为page.jsp
的JSP文件,并将其解析为HTML以响应客户端的请求。方法上不能加@ResponseBody,否则会直接将page.jsp当字符串返回前端;方法需要返回String
@Controller
public class UserController {
@RequestMapping("/toJumpPage")
public String toJumpPage(){
return "page.jsp";
}
}
6.3 返回文本数据[了解]
- 如果省略@ResponseBody,会把text当成视图名称去查找,如果没有会报404错误
@Controller
public class UserController {
@RequestMapping("/toText")
@ResponseBody
public String toText(){
return "text";
}
}
7、SSM整合【mini_springmvc文件】
项目构建说明
- 创建meven工程,导入相关依赖
- 配置:
- Spring:SpringConfig
- Mybatis:MybatisConfig、jdbcConfig、jdbc.properties
- SpringMVC:ServletConfig、SpringMvcConfig
- 功能模块:
- dao(接口+自动代理)
- service(接口+实现类)JUnit测试
- controller,PostMan测试