目录
1 MVC设计模式介绍
model
controller
view
可参考之前的文章介绍
2 SpringMVC简介
Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面。Spring 框架提供了构建 Web 应用程序的全功能 MVC 模块。使用 Spring 可插入的 MVC 架构,从而在使用Spring进行WEB开发时,可以选择使用Spring的Spring MVC框架或集成其他MVC开发框架,如Struts1(现在一般不用),Struts 2(一般老项目使用)等
3 请求流程
1.用户发送请求至前端控制器DispatcherServlet
2.DispatcherServlet收到请求调用HandlerMapping处理器映射器。
3.处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
4.DispatcherServlet通过HandlerAdapter处理器适配器调用处理器
5.执行处理器(Controller,也叫后端控制器)。
6.Controller执行完成返回ModelAndView
7.HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet
8.DispatcherServlet将ModelAndView传给ViewReslover视图解析器
9.ViewReslover解析后返回具体View
10.DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)。
11.DispatcherServlet响应用户
以上流程是以DispatcherServlet为核心轴,并且DispatcherServlet就是一个Servlet
4 实现方式
4.1 xml实现(不常用)
4.1.1 创建项目并引入依赖
<?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.example</groupId>
<artifactId>demo</artifactId>
<version>1.0-SNAPSHOT</version>
<name>demo</name>
<packaging>war</packaging>
<properties>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>1.8</maven.compiler.source>
<junit.version>5.7.0</junit.version>
<spring.version>5.2.5.RELEASE</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<!--Spring核心基础依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- 增加了切面 -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.5</version>
</dependency>
<!-- spring jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<!--spring mvc-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<!--日志相关-->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!--测试相关-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.3.0</version>
</plugin>
</plugins>
</build>
</project>
4.1.2 配置web.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>basic</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>basic</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
4.1.3 创建basic-servlet.xml文件
该文件名必须是servlet名字-servlet.xml
文件位置要和web.xml同级
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd">
<!-- 处理映射器配置-->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
<!-- 创建映射,配置映射器,name必须是 / 打头-->
<bean name="/w" class="com.tledu.spring_mvc01.controller.HelloController"/>
<!-- 视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
4.1.4 编写controller层
public class HelloController extends AbstractController {
@Override
protected ModelAndView handleRequestInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
System.out.println("hello world!!!");
return new ModelAndView("hello");
}
}
4.1.5 编写jsp页面
视图解析器这里,我们指定了文件的目录和后缀
当controller返回了welcome的时候 就会去找WEB-INF/jsp/welcome.jsp
需要创建对应的jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Test</title>
</head>
<body>
<h1>hello spring mvc</h1>
</body>
</html>
4.1.6 运行测试
4.2 注解实现
4.2.1 编写配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd">
<context:component-scan base-package="com.tledu.spring_mvc02"/>
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes" value="text/plain;charset=UTF-8"/>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
<!--视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
4.2.2 配置包扫描
在controller层的类上@controller注解
@Controller
public class HelloController {
4.2.3 配置地址与controller的映射关系
在controller层的类上@RequestMapping("")注解
@Controller
@RequestMapping("/hello")
public class HelloController {
4.2.4 配置地址和方法的映射关系
在方法上加@RequestMapping("")注解
@RequestMapping("/add")
public String delete(){
return "user/add";
}
4.2.5 返回一个字符串
这个字符串就是view-name,必须与jsp的目录和文件名一致
5 常用的注解
@Controller 使用Controller注解之后,在方法上可以通过return的jsp或者html页面的名字,通过视图解析器,就能跳转到指定页面
@ResponseBody 如果方法需要返回JSON或者XML或者自定义内容到页面中去,就需要再方法上加上ResponseBody,这个时候,返回的数据就会不被视图解析器所解析
@RestController RestController注解相当于Controller和ResponseBody一起使用,如果该类中的所有方法都不需要视图解析器解析,就可以在类上加上这个注解
@RequestMapping 会将http请求映射到MVC和Controller控制器的处理方法上,可以处理所有的request请求
@GetMapping RequestMapping复合注解,专门处理get请求
@PostMapping RequestMapping复合注解,专门处理post请求
@PutMapping RequestMapping复合注解,专门处理put请求
@DeleteMapping RequestMapping复合注解,专门处理delete请求
@RequestParam 主要用于接收前后端key不一致的时候,使用@RequestParm来指定获取
@RequestBody 主要用于接收前端通过 请求体 传递给后端的JSON字符串中的数据,GET方式无请求体,所以使用@RequestBody的时候不能使用GET方式,而应该使用POST形式
6 控制器类和参数绑定
6.1 RequestMapping详解
6.1.1 作用
建立请求URL和处理方法之间的对应关系
6.1.2 使用位置
作用在类上:第一级的访问目录
作用在方法上:第二级的访问目录
细节:路径可以不编写 / 表示应用的根目录开始
细节:${ pageContext.request.contextPath }也可以省略不写,但是路径上不能写 /
6.1.3 参数
path 指定请求路径的url
value value属性和path属性是一样的
method 指定该方法的请求方式
GetMapping
PostMapping
PutMapping
DeleteMapping
params 指定限制请求参数的条件
headers 发送的请求中必须包含的请求头
6.2 MVC中的参数绑定
6.2.1 绑定机制
1.表单提交的数据都是k=v格式的username=haha&password=123
2.SpringMVC的参数绑定过程是把表单提交的请求参数,作为控制器中方法的参数进行绑定的
3.要求:提交表单的name和参数的名称是相同的
6.2.2 支持的数据类型
1.基本数据类型和字符串类型
2.实体类型(JavaBean)
3.集合数据类型(List、map集合等)
6.2.3 注意事项
如果是基本数据类型和字符串类型
提交表单的name和参数的名称是相同的
区分大小写
如果名称不相同可以通过@RequestParam(“user”),指定参数名字
如果参数是必传的@RequestParam(required = true)
如果是实体类型
提交表单的name和JavaBean中的属性名称需要一致
如果一个JavaBean类中包含其他的引用类型,那么表单的name属性需要编写成:对象.属性 例如:address.name
如果是集合数据类型
表单提提交
list:多个同名属性设置list
获取通过json的方式进行提交
需要设置注解@RequestBody
7 中文乱码问题
在web.xml中配置Spring提供的过滤器类
<!--编码格式过滤器-->
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<!-- 设置过滤器中的属性值 -->
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<!-- 启动过滤器 -->
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<!-- 过滤所有请求 -->
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
8 自定义类型转换器
表单提交的任何数据类型全部都是字符串类型,但是后台定义Integer类型,数据也可以封装上,说明Spring框架内部会默认进行数据类型转换。
如果想自定义数据类型转换,可以实现Converter的接口
8.1 编写相关类
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import org.springframework.core.convert.converter.Converter;
import java.util.Date;
/**
* @author simple
*/
public class DateConvert implements Converter<String, Date> {
@Override
public Date convert(String s) {
// if (s == null) {
// return null;
// }
// // 日期格式化
// SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
// try {
// return sdf.parse(s);
// } catch (ParseException e) {
// e.printStackTrace();
// throw new RuntimeException("日期格式化错误");
// }
if (StrUtil.isBlank(s)) {
return null;
}
return DateUtil.parse(s, "yyyy-MM-dd HH:mm:ss");
}
}
注释的内容是普通的实现
未注释的内容是通过hutool实现的,相关语法可以百度查看
8.2 编写xml配置文件
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="com.tledu.spring_mvc02.convert.DateConvert"/>
</set>
</property>
</bean>
<mvc:annotation-driven conversion-service="conversionService"/>
此外,json里日期参数格式化可以使用@JsonFormat(pattern = “yyyy/MM/dd”)注解进行配置
9 在控制器中如何获取ServletAPI对象
9.1 第一种方法
只需要在控制器的方法参数定义HttpServletRequest和HttpServletResponse对象 ,mvc会帮我们自动注入和封装
9.2 第二种方法
通过@Autowired
@Autowired
private HttpServletRequest request;
10 多个url映射到同一个方法上
@RequestMapping({"/hello","/h","/hi"})
public String hello(String username,Model model) {
model.addAttribute("username", "Hello : "+username);
return "hello";
}