Spring MVC 总结
Spring MVC 总结
Spring MVC 概述
为 WEB 项目提供的 MVC 分层框架
水平角度: Spring MVC 是 Spring 生态圈中的一个功能模块。两者是包含与被包含的关系;
垂直角度: Spring MVC 是建立在 Spring 核心基础功能之上的一个实用性的 WEB MVC 框架,是 Spring 的延伸和扩展。
MVC 的分离思想:
把整个应用程序中和用户进行交互的功能代码归纳在一起,这部分代码整体称为 V (View 或叫视图层)
把专门用来进行数据传递或数据逻辑处理的功能代码归纳在一起,称其为 M(Model 或叫l模型层)
C (控制器)就是 V 和 M 之间的桥梁
两个上下文对象
2 个 WebApplicationContext 对象:
- WebApplicationContext 对象用来创建 Spring MVC 相关的组件,称其为 Web 上下文对象
- RootApplicationContext 创建程序中其它的具体功能组件(如逻辑组件、数据层访问组件…),称其为 Root (根)上下文对象
一个支持事务,另一个不支持
DispatcherServlet 为中央控制器或前端控制器
在整个项目运作之前先让 DispatcherServlet 组件开始工作,DispatcherServlet 除了充当门神外,还会创建一个与自己有关联的 WebApplicationContext
工厂对象,即 Web 上下文对象;
Spring 另提供有名为 ContextLoaderListener
的监听器组件,它可以监听程序的启动过程,并在程序启动时创建另一个 WebApplicationContext
工厂对象,即 Root 上下文对象
AbstractAnnotationConfigDispatcherServletInitializer
: 基于注解的初始化 DispatcherServlet 的抽象组件,简单说就是一个 WEB 初始化组件,用来替代 web.xml 的功能
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer{
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { RootConfig.class};
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] { WebConfig.class};
}
//接受所有请求
@Override
protected String[] getServletMappings() {
return new String[] {"/"};
}
}
//web 上下文对象的配置类
@Configuration
@ComponentScan(basePackages = { "com.cpucode.web" }, excludeFilters = {
@Filter(type = FilterType.ANNOTATION, value = EnableWebMvc.class) })
public class RootConfig {
}
// Root 上下文对象的配置类
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = { "com.cpucode.web.action" })
public class WebConfig {
}
- @Configuration 注解:说明这个类是配置类;配置类用来替代 XML 配置文件
- @EnableWebMvc 注解: 启动 Spring MVC 相关功能
- @ComponentScan 注解: 指定上下文对象各自负责的组件所在包
核心组件
- 前端控制器: 类似于超市的入口
- 用户控制器: 类似于不同类型的货品架,为用户提供具体的商品买卖
- 映射器: 类似于超市里的导购员。请问,我要的这个牌子的辣椒酱在哪里,哦,在这里
- 适配器: 统一控制器,让其有一致对外的接口
- 视图解析器: 找到视图,并负责渲染视图
前端控制器
- 中央控制器 ( 前端控制器 ) : 由 Spring MVC 框架提供,对所有请求进行分流;
- 用户控制器 ( 响应控制器 ) : 由开发者实现,用来响应用户的具体请求。如登录请求、注册请求
前端控制器(DispatcherServlet)是 Spring MVC 中最核心的组件,相当于整个程序中的行政、调度中心。其它的组件都是它的附庸,为前端控制器提供相关的服务
DispatcherServlet 必须在 Spring MVC 项目启动时被创建
请求分流
所有请求都会汇流给 DispatcherServlet 组件。再由 DispatcherServlet 分流到具体的用户控制器
-
安全性: 前台可以对来访人员的身份进行初步认定和筛选。确保只能通过一个入口进入程序
-
标准化: 每一个请求都会以相同的方式进行分流处理。统一协调,标准化项目,可以高度简化处理流程
调度中心
一次请求、响应的完成,需要多个组件通力合作。如何协调各个组件的工作,保证请求、响应过程有条不紊的进行,则需要一个指挥者或说一个核心灵魂组件
DispatcherServlet
就是每一次请求、响应过程中的组织者、调度者
DispatcherServlet 本质就是一个和 Spring MVC 程序一起启动的 Servlet
用户控制器
用户控制处理器(用户控制器 \ 控制器 \ 处理器)提供具体的响应用户请求的逻辑。用户控制器虽然由用户自定义编写,但也需要直接或间接遵循 Spring MVC 的控制器编写规范
编写控制器
public class HelloAction implements org.springframework.web.servlet.mvc.Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
System.out.println("Bean URL ");
return null;
}
}
映射控制器
原生 Servlet 开发中,需要在 web.xml 中注册、映射 Servlet 后浏览器才能请求到
在类前面 @Controller 注解 : 通知 Spring MVC 的上下文对象(WebApplicationContext), 控制器的创建交给你
@Controller
public class HelloAction {
//省略……
}
控制器的方法前面添加 @RequestMapping 注解。使用此注解可提供一个逻辑名向用户映射此方法
@RequestMapping("/hello")
public String hello() {
System.out.pirntln("hello");
return "hello";
}
映射器
检查用户的请求路径中是否存在对应的控制器组件
开发者没有显示配置映射器,Spring MVC 会启动默认的映射器组件
DispatcherServlet 所在包的根目录下有名为 DispatcherServlet.properties
的文件,已经配置了很多默认组件信息
@Bean 注解映射: 打开项目中的 WebConfig 配置类
@Bean(name = "/hello")
public HelloAction hello() {
return new HelloAction();
}
“hello” 前面一定要加上 “/”
使用 @Bean 注解的方式映射控制器,则用户控制器需要实现 org.springframework.web.servlet.mvc.Controller
接口, 意味着必须是一个标准的控制器
@Bean 的作用就是告诉 Spring MVC:你要创建它,其名字被当成一个访问控制器的 URL
BeanNameUrlHandlerMapping
映射器的功能就是查找有没有哪一个 Bean 的名字和用户请求的路径相匹配
RequestMappingHandlerMapping
映射器就是查找由 @RequestMapping 注解映射的控制器
适配器
适配器组件,其本质就是运用适配器设计模式,匹配不兼容的接口规范
-
SimpleControllerHandlerAdapter: 简单的控制器处理器适配器,支持实现了 Controller 接口的控制器
-
HttpRequestHandlerAdapter:http 请求处理器适配器,要求编写的控制器时实现 HttpRequestHandler 接口。此类控制器可以很方便的获取请求包中的相关信息
-
RequestMappingHandlerAdapter: 注解处理器适配器,适配使用了注解的用户控制器
视图解析器
视图解析器的功能
视图解析器,则会把这个字符串当成一个视图的逻辑名,并映射到真正的物理视图
视图解析器和映射器的有相似之处 :
-
映射器是入口时根据请求控制器逻辑名找到物理控制器
-
视图解析器是出口时根据视图逻辑名找到物理视图
InternalResourceViewResolver
作为视图解析器, 提供对 JSP 视图的支持
默认提供的、还是开发者自行定义的视图解析器,都必须实现 ViewResolver 接口
public interface ViewResolver {
@Nullable
View resolveViewName(String viewName, Locale locale) throws Exception;
}
配置视图解析器
WebConfig 配置类 :
@Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver inResolver=new InternalResourceViewResolver();
inResolver.setPrefix("/WEB-INF/jsp/");
inResolver.setSuffix(".jsp");
return inResolver;
}
- @Bean 注解表示此对象由 Spring 容器创建
- inResolver.setPrefix ("/WEB-INF/jsp/") 表示 JSP 页面视图所在物理位置
- inResolver.setSuffix (".jsp") 表示 JSP 视图的后缀
静态资源
WebConfig 配置类,让其实现 WebMvcConfigurer 接口
public class WebConfig implements WebMvcConfigurer{
}
重写 configureDefaultServletHandling() 方法,启动 Servlet 的 default Servlet 来处理静态资源
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
总结
-
浏览器的请求到达前端控制器(DispatcherServlet)
-
前端控制器解析出请求路径后询问映射器,咱们是否提供的有用户需要的用户控制器,映射器把查询结果返回给前端控制器
-
适配器的作用就是统一不同类型的用户控制器(也体现了 Spring MVC 中用户控制器的多样性和灵活性)
-
用户控制器开始工作(具体的响应逻辑)
-
用户控制器返回视图逻辑名和视图中所需要的数据(ModelAndView)
-
前端控制器询问视图解析器,你能够根据逻辑名找到物理视图吗?视图解析器开始工作并找到物理视图
-
前端控制器渲染物理视图和数据,生成浏览器能够识别的数据格式
-
响应浏览器,并在浏览器中显示最终请求结果
映射与数据解析
地址请求映射
请求地址映射 : 每一次请求都会交给用户控制器响应。为了保证用户能请求到用户控制器,则需要 Spring MVC 向外提供用户控制器对外的请求接口
@RequestMapping 注解的作用:把用户控制器以 URL 逻辑名的方式向外映射,用于由外向内的请求调用。
解析请求包中的信息,查找是否存在相匹配的控制器,这个工作由映射器组件完成。
@RequestMapping 的位置
放置在类前面也可以放在方法前面
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping(value = "/register")
public String register() {
return “user/register”;
}
}
使用表达式限定请求
映射描述具有多样性:
- 支持标准的 URL 格式
- 支持 Ant 风格
Ant 风格指在 URL 中支持 通配符的语法结构描述
- ?: 匹配任何单字符
- * : 匹配 0 个或者任意数量的字符
- ** : 匹配 0 个或者更多的目录
- {xxx} 占位符的 URL
限定请求的方法
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface RequestMapping {
String name() default "";
@AliasFor("path")
String[] value() default {};
@AliasFor("value")
String[] path() default {};
RequestMethod[] method() default {};
String[] params() default {};
String[] consumes() default {};
String[] produces() default {};
}
- method():可限定请求的方法;
- params():可以限定请求的参数
常用的请求方法 :
- GET: 一般用于查询请求,具有幂等性,多次相同的请求会返回相同的结果,所以可以使用浏览器缓存。不会影响系统的整体性能
- POST: 一般用于数据保存请求。不具有幂等性,多次操作会产生新的资源
- DELETE: 一般用于删除资源请求,可以多次删除
- PUT: 一般用于更新数据请求,也具有幂等性,无论更新多次性,结果都一样
@RequestMapping(value="/test",method=RequestMethod.POST)
public String test(){
return "user/test1";
}
RequestMethod 是一个枚举类型
public enum RequestMethod {
GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE
}
限定请求参数
限定请求参数,Spring MVC 会检查请求包中是否包含符合要求的请求参数
@RequestMapping(value="/test", params="userId")
public String test(){
//...
}
- params=“userId”: 指挥响应请求包中包含有名为 userId 参数的请求
- params="!userId" : 如果请求包中有名为 userId 的请求参数,则不响应,否则响应
- params=“userId!=1”: 对响应的请求有更多的要求,除了请求包中必须包含 userId 参数外,其值必须是 1
- params={“userId=1”,“userName”}: 响应的条件是,请求包中必须包含名为 userId 和 userName 这两个参数,且 userId 参数的值必须为 1
限定头信息
限定头信息,指 Spring MVC 可以通过 HTTP 请求包中的消息头信息进行过滤
@RequestMapping(value="/test", headers="content-type=text/*")
public String test(){
//...
}
test() 方法只会响应请求包中的内容类型为 text/* 的请求
绑定请求包中的数据
注解解析请求包中的数据 :
- @RequestParam
- @CookieValue
- @RequestHeader
- @PathVariable
HTTP 协议的一种数据格式包 :
- 请求行: 包括请求方法、请求的资源地址(URL) 、HTTP 协议版本号;
- 消息头: 消息头是传送给服务器的信息,以 key:value 的格式描述;
- 实体部分或报文体: 以 key=value 的数据格式保存客户端传递给应用程序的数据。
@RequestParam
自动绑定请求包中的请求参数中的值
请求参数在请求包中的 2 个位置:
- 用 ? 的方式附加在 URL 后面。如 http://:/saveUser?name=abc 。name 就是请求参数,abc 是值
- name=abc 的方式存储在请求包的报文体中(实体部分)
以 POST 方法请求时,数据将存储在实体部分
@RequestMapping(value="/saveUser")
public String save(@RequestParam("userName") String userName,
@RequestParam("password") password){
}
@RequestParam(“参数名”) 中的 “参数名” 和请求包中的参数名的命名相同
@RequestParam 注解中有 3 个常用的属性:
-
value() : 指定要解析的请求包中的参数名
-
required() : 表示请求包中是否必须存在由 value() 指定的参数名,默认值是 true。如果没有此参数则会抛出异常
-
defaultValue() : 表示如果不能正确获取到指定参数的值时,则提供一个默认值。设置该参数时,自动将 required 设为 false
@RequestMapping(value="/saveUser")
public String save(@RequestParam(value = "userName",
defaultValue="mk",
required = false) String userName,){
}
@CookieValue
@CookieValue 用来自动绑定请求包中的 Cookie 值
Cookie 所能保存的数据量有限且只能是字符类型
@RequestMapping(value="/sessionId")
public String getSessionId(@CookieValue("JSESSIONID") String sessionId){
}
注入 Cookie 中所携带的 JSESSIONID 的值
@RequestHeader
请求包中有很多消息头信息,都是以 key:value 的格式存在
@RequestMapping(value="/header")
public String getHeader(@RequestHeader("Accept-Language") String accpetLanguage){
//...
}
accpetLanguage 参数会被注入请求包中 key 名为 Accept-Language 的消息头值
@RequestHeader 注解中的方法 :
@AliasFor("name")
String value() default "";
String name() default "";
boolean required() default true;
String defaultValue() default ValueConstants.DEFAULT_NONE;
@PathVariable
获取 URL 中变量的值
{userId} 就是变量占位符
@RequestMapping("/user/{userId}")
public String getUserById(@PathVariable("userId") String userId){
}
required 属性,表示是否强制 URL 中有变量的存在
boolean required() default true;
总结
- @RequestParam :请求参数中的值
- @CookieValue: Cookie 的值
- @RequestHeader 请求头的值
- @PathVariable :请求变量的值
绑定表单数据
对象 / 表单
表单的方式提交数据有一个优点,可以把逻辑上具有内在联系的多个数据同时发送给服务器
提交数据最终会交给服务器端的用户控制器完成
控制器中的处理流程应该分 3 步走:
- 从请求包中解析出客户端提交过来的注册数据
- 处理注册数据。核心业务逻辑就是添加数据到数据库中
- 根据处理结果进行页面跳转
以 OOP 方式绑定数据
public class User {
private String userName;
private String userPassword;
//……
}
@RequestMapping("/register",method = RequestMethod.POST)
public String register(User user) {
System.out.println(user);
return null;
}
表单中数据以 key=value&key=value
的方式提交,此处的 key 实质是表单控件的名称
Spring MVC 能自动解析这个数据,然后自动注入到对象的同名属性中
对象级联
OOP 代码中经常会出现类似于 A 对象引用 B 对象,B 对象引用 C 对象的现象
Spring MVC 支持对象级联自动数据绑定 , 多层级的对象级联
表单验证
JSR : 数据验证是对数据进行逻辑处理之前需要进行的一个很重要环节,如果不合要求的数据进入逻辑处理环节后,会导致程序的崩溃
验证用户提交的表单数据的合法性 :
- 客户端验证: 表单提交之前,通过客户端的 JS 脚本对表单中预提交的数据进行验证
- 服务器端验证: 数据提交到服务器后,由服务器端的的代码进行验证
Bean 类型的属性前面 :
-
@Null: 被注解的属性的值必须为空
-
@NotNull: 被注解的属性的值可以不为空
-
@Min(value): 注解数字类型的属性,其值大于等于指定的值
-
@Max(value): 注解数字类型的属性,其值小于等于指定值
-
@Size(max, min): 注解的属性值的大小必须是在给定的范围内(包括边界数字)
-
@Past: 注解日期类型属性,必须是一个过去的日期
-
@Future: 注解日期类型属性,必须是一个将来的日期
-
@Pattern(regexp): 使用正则表达式验证属性的值
-
@Length(min, max): 属性值的长度在给定的范围之内(包括边界数字)
public class Teacher {
@NotNull(message = "姓名不能为空")
private String name;
@Min(value = 22,message = "年龄不能小于 22 岁")
private Integer age;
//...
}
@Valid 注解表示在绑定数据之后对数据进行验证
BindingResult 组件用来保存验证过程中的错误信息
@Controller
@RequestMapping("/teacher")
public class TeacherAction {
@RequestMapping(value = "/save",method = RequestMethod.POST)
public String register(@Valid Teacher teacher,BindingResult result) {
if (result.hasErrors()) {
return "fail";
}
return "success";
}
}
原生 Servlet
HttpServletRequest: 用来处理请求包
HttpServletResponse: 用来处理响应包
HttpSession: 会话对象
ServletConfig: 配置对象
ServletContext: Servlet 上下文对象
Servlet API 代理类
Spring MVC 在它的 org.springframework.web.context.request
包中提供的有 WebRequest 接口,此接口可以用来代理原生 HttpServletRequest 的功能
使用 IO 流
WEB 程序整体上是 B / S 结构,本质上是基于底层网络的程序,是 C / S 结构体系的升级
网络编程的几个基本要素:
- 服务器端建立监听端口
- 客户端向监听端口发起网络连接
- 连接成功后建立起双向的网络流传输通道
- 彼此之间通过网络流通道进行数据交流
Spring MVC 既可以把原生的 Servlet API 对象注入到控制器的方法中,也可以把更底层的 IO 流对象注入到控制器方法中
注入 InputStream
@RequestMapping(value = "/testApi04",method = RequestMethod.POST)
public void hello(InputStream inputStream) throws IOException {
byte[] buff=new byte[128];
int read= inputStream.read(buff);
System.out.println(new String(buff,0,read));
}
控制器方法的映射机制有只接受 POST 方法的限制,如果是 GET 方法的请求包,直接使用 InputStream 对象无法获取到请求包中的数据。
GET 方法的请求数据是附加在 URL 上的,InputStream 只能读取实体部分的数据
注入 OutputStream
OutputStream 对象读取指定文件中的内容后直接响应给浏览器
@RequestMapping(value = "/testApi05")
public void hello(OutputStream outputStream) throws IOException {
Resource res = new ClassPathResource("/test.txt");
FileCopyUtils.copy(res.getInputStream(), outputStream);
}
XML 方式
2 个上下文对象分别依赖于 DispatcherServlet 和 ContextLoaderListener 组件完成创建。
-
DispatcherServlet : 整个程序的调度中心(本质就是一个 Servlet),Spring MVC 程序启动时必须要初始化完成对 DispatcherServlet 组件的创建。此组件还会创建一个与自己有关联的 WebApplication 工厂对象,即 Web 上下文对象
-
ContextLoaderListener : 由 Spring 提供的监听器组件,它可以监听程序的启动过程,并在程序启动时创建另一个 WebApplication 工厂对象,即 Root 上下文对象
- web.xml: 理论上,在新建 Spring MVC WEB 项目时, WEB-INF 目录中会自动创建这个文件。如果不存在,就需要创建一个
- spring-mvc.xml: 由开发者新建,一般放在项目的 src/main/resources 目录下面
- application.xml: 由开发者新建,放在项目的 src/main/resources 目录下面
web.xml
在 web.xml 中配置 DispatcherServlet 组件相关的信息
<!-- 配置 Spring MVC 的核心组件 DispatcherServlet -->
<servlet>
<servlet-name>springMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
contextConfigLocation 是 DispatcherServlet 的属性,用于指定与 DispatcherServlet 创建的上下文对象有关的配置文件的位置。此处为 spring-mvc.xml 文件位置
在 web.xml 中配置 ContextLoaderListener 监听器组件相关信息
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:application.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
配置临听器时,也需要为临听器创建的上下文对象指定配置文件的位置,此处指 application.xml 文件的位置
spring-mvc.xml
spring-mvc.xml 用来配置与 Spring MVC 相关的组件信息,用来提供给 web 上下文对象进行组件维护
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 启动注解支持 -->
<mvc:annotation-driven/>
<!--静态资源交给 tomcat default servelt 处理-->
<mvc:default-servlet-handler />
<!--扫描组件位置-->
<context:component-scan
base-package="com.cpucode.web.action"></context:component-scan>
<!-- 视图解析器 -->
<mvc:view-resolvers>
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/jsp"></property>
<property name="suffix" value=".jsp"></property>
</bean>
</mvc:view-resolvers>
</beans>
-
mvc:annotation-driven: 启动注解支持,完全使用 XML 进行 Spring MVC 项目维护,并不是很方便。即使在使用 XML 时,建议还是结合注解一起使用,这也是 Spring MVC 官方建议的
-
context:component-scan: 指定哪些组件由 Spring MVC 的上下文对象负责。除了 Spring MVC 内部组件外,再就是用户控制器
-
mvc:view-resolvers: 配置具体的视图解析器
application.xml
application.xml 是 Spring 上下文容器所关联的配置文件,可称其为全局上下文对象的关联配置文件
<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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config></context:annotation-config>
<context:component-scan
base-package="com.cpucode.web">
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Controller" />
</context:component-scan>
</beans>
- context:annotation-config: 启动注解支持,建议需要全局上下文对象创建、维护的对象使用注解的方式
- context:component-scan: 扫描位置,需要排除开 Spring MVC 容器对象扫描的位置
数据模型
数据模型 : Spring MVC 提供的在特定作用域内封装数据的组件
请求作用域
WEB 程序的应用层使用的是 HTTP 协议,HTTP 协议有一个特点,无状态
无状态指上一次请求与下一次请求之间是隔离的,没有内在的联系
原生 Servlet 提供了 3 个作用域 :
-
请求作用域: 使用 HttpServletRequest 组件存储的数据可以在每一次的请求周期内存在。 请求结束,数据也将消失
-
会话作用域: 使用 HttpSession 组件保存的数据能在整个会话生命周期内存在。如购物车就可以保存在会话作用域中
-
应用程序作用域: 使用 ServletContext 组件保存的数据在整个应用程序生命周期之内存在
Spring MVC 中,把数据保存在请求作用域 , 方案 :
- 直接使用 HttpServletRequest 组件
- 使用 Spriing MVC 提供的高级数据模型组件
原生 HttpServletRequest
@RequestMapping("/login")
public String login(User user,HttpServletRequest request) {
if("cpucode".equals(user.getUserName()) && "123".equals(user.getUserPassword())) {
//请求作用域
request.setAttribute("loginUser", user);
return "index";
}
return "fail";
}
- user 参数: 以 OOP 的方式绑定请求包中传过来的数据;
- request 参数: 注入原生 HttpServletRequest 组件。登录者的信息保存在 HttpServletRequest 对象中
HttpServletRequest 组件具有服务器端数据存储功能,本质是内部维护有一个 map 对象。HttpServletRequest 的生命周期较短,从请求开始到请求结束。所以,其保存的数据也只能在整个请求范围内有效
Spring MVC 模型组件
只要 Spring MVC 引用出 HttpServletRequest 内置的 map 对象
@RequestMapping(value="/login",method=RequestMethod.POST)
public String login(User user,Map map) {
if("mk".equals(user.getUserName()) && "123".equals(user.getUserPassword())) {
map.put("loginUser", user);
return "index";
}
return "fail";
}
map 参数 : 通知 Spring MVC ,把某个作用域中的 map 对象引用出来
Spring MVC 引用出来的是请求作用域也就是 HttpServletRequest
的内置 map 对象
数据模型
Spring MVC 中的数据模型组件 :
- Model
- ModelMap
- ModelAndView
数据模型应该有 2 层含义:
- WEB 程序中封装数据的组件
- 此模型对象会有自己特定作用域
请求作用域 : 间接使用 HttpServletRequest 对象
会话作用域 : 间接使用 HttpSession 对象
Model
Model 是一个接口类型,Model 接口中提供了标准的保存数据的方法
将 Model 设为控制器方法的参数便可 , Model 是一个接口类型,Spring MVC 注入一个具体的实例对象
@RequestMapping(value="/login",method=RequestMethod.POST)
public String login01(User user,Model map) {
if("cpucode".equals(user.getUserName()) && "123".equals(user.getUserPassword())) {
map.addAttribute("loginUser", user);
return "index";
}
return "fail";
}
ModelMap
用 Map 存储数据的模型 , 一个链表实现的 Map
public class ModelMap extends LinkedHashMap<String, Object> {
}
@RequestMapping(value="/login",method=RequestMethod.POST)
public String login01(User user,ModelMap map) {
if("cpucode".equals(user.getUserName()) && "123".equals(user.getUserPassword())) {
map.addAttribute("loginUser", user);
return "index";
}
return "fail";
}
ModelAndView
ModelAndView 其实就是封装了 ModelMap 外加一个用来保存视图相关信息的 view 对象 , 把数据模型和视图拼在了一起,便于一次性交给前端控制器处理
public class ModelAndView {
@Nullable
private Object view;
@Nullable
private ModelMap model;
//……
}
用法 :
@RequestMapping(value="/login",method=RequestMethod.POST)
public ModelAndView login01(User user) {
ModelAndView mv=new ModelAndView();
if("cpucode".equals(user.getUserName()) && "123".equals(user.getUserPassword())) {
mv.addObject("loginUser", user);
mv.setViewName("index");
return mv;
}
mv.setViewName("fail");
return mv;
}
会话作用域
Map、Model 、ModelMap、ModelAndView ,默认情况下,保存的数据都是请求作用域级别的
@Controller
@RequestMapping("/user")
@SessionAttributes("loginUser")
public class UserAction {
@RequestMapping(value = "/login", method=RequestMethod.POST)
public ModelAndView login01(User user) {
ModelAndView mv = new ModelAndView();
if("cpucode".equals(user.getUserName()) && "123".equals(user.getUserPassword())) {
mv.addObject("loginUser", user);
mv.setViewName("index");
return mv;
}
mv.setViewName("fail");
return mv;
}
}
@SessionAttributes(“loginUser”) 中的属性名 loginUser 必须保持 和 mv.addObject(“loginUser”, user) 中的 loginUser 名一样
Spring MVC 即把数据保存到请求作用域中、也保存到会话作用域中
总结
- 使用 Map 做数据模型时, Spring MVC 注入的是一个 LinkedHashMap 实例
- ModelMap 是 LinkedHashMap 的子类,本质还是 LinkedHashMap,只是封装了 put 方法,让其显得高级一点
- Model 是接口,Spring MVC 注入的也是 LinkedHashMap 实例
视图技术
JSON 序列化
@ResponseBody
前后端分离结构 : 把一部分数据逻辑交给前端处理
后端一般选择以 JSON 的格式向前端进行数据传递
返回字符串
@Controller
@RequestMapping("/json")
public class JsonAction {
@RequestMapping("/test01")
@ResponseBody
public String testJson() {
return "Hello";
}
}
-
没有 @ResponseBody 注解:Spring MVC 会把返回值 “hello” 理解为视图逻辑名,通过视图解析器找到视图物理位置
-
@ResponseBody 注解: Spring MVC 会把返回值直接写入响应包后交给浏览器。意味着不需要视图解析器的参与
返回对象
@RequestMapping("/test02")
@ResponseBody
public User testJson01() {
return new User("cpucode", "123");
}
Spring MVC 和 JSON
WebConfig 类文件
@Bean
public MappingJackson2HttpMessageConverter mappConverter() {
MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter=new MappingJackson2HttpMessageConverter();
return mappingJackson2HttpMessageConverter;
}
MappingJackson2HttpMessageConverter 就是一个消息转换器,其作用就是把数据映射成 JSON 格式
jackson 插件完成具体的 JSON 格式序列化
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.10.0</version>
</dependency>
视图技术
视图技术:
- 模板
- 模板解析引擎
模板
动态页面模板 :
- HTML、CSS 等 : 为模板中的数据提供版式和样式
- 强逻辑性语言: 提供数据逻辑能力,可以自动更新模板中的数据
模板解析引擎
动态页面模板需要被渲染成纯 HTML 静态页面后才能发送给浏览器,这个渲染过程就是依靠模板解析引擎实现
主流视图技术
主流视图技术 :
- Jsp: Jsp 模板是 J2EE 官方指定的,所以其模板引擎可由遵循 J2EE 规范的服务器实现,如 tomcat
- Freemarker: Freemarker 因 Struts MVC 风靡一时。其模板需要自己提供的模板引擎解析
- Thymeleaf: Thymeleaf 应该算是后起之秀,更适应现代化开发理念和习惯
Spring MVC 视图解析器
Spring MVC 执行流程
@Controller 和 @RequestMapping 注解
Spring MVC 传递参数
Spring MVC 重定向和转发
@Autowired 和 @Service 注解
@ModelAttribute 注解
Spring MVC 拦截器
Spring MVC 异常处理
Spring MVC REST 风格
了解 Restful 相关的内容
Spring MVC 文件上传
Spring MVC 文件下载
常规应用
中文乱码问题
中文乱码的解决方式可以自定义过滤器,也可以使用 Spring MVC 自带的过滤器
整合
相关文章
- Http请求中Content-Type讲解以及在Spring MVC中的应用
- ssm(Spring+Spring mvc+mybatis)mybatis配置文件——mybatis-config.xml
- ssh(Spring+Spring mvc+hibernate)——hibernate.cfg.xml
- Spring MVC 实现文件的上传和下载
- spring mvc: rss(xml)输出
- spring mvc:常用标签库(文本框,密码框,文本域,复选框,单选按钮,下拉框隐藏于,上传文件等)
- spring mvc: 密码框
- spring mvc : 中文传值(post/get)中文乱码
- 20-spring学习-Spring MVC基本操作
- spring MVC上传图片
- Spring Boot——2分钟构建spring web mvc REST风格HelloWorld
- Spring MVC入门示例教程--表单处理
- Spring MVC使用webSocket保持长连接
- Spring MVC注解Controller源码流程解析--HandlerAdapter执行流程--上
- Spring 自动装配模式之构造函数装配方式
- Spring MVC 页面渲染( render view )
- Atitit.spring体系结构大总结 1. Spel表达式解析1 2. Srping mvc1 3. Ioc4 3.1. ApplicationContext在BeanFactory的基础
- 自定义 spring mvc 拦截器(近期项目需求实现)
- Eclipse 插件之Spring IDE
- Spring AOP
- Spring Boot Test单元测试——Junit4、Junit5区别与@ExtendWith不识别生效问题解析
- Spring MVC 学习总结(九)——Spring MVC实现RESTful与JSON(Spring MVC为前端提供服务)
- Spring MVC 学习总结(五)——校验与文件上传
- Spring MVC 学习总结(四)——视图与综合示例
- Spring MVC 3 深入总结
- Spring MVC 3 深入总结
- Spring MVC 3 深入总结
- 008-spring cloud gateway-路由谓词RoutePredicate、RoutePredicateFactory
- Spring Boot批量服务
- Spring MVC生成XML
- Spring Security---用户名密码登录流程源码解析
- MVC 和web MVC ,SpringMVC和Spring web MVC的关系与区别?
- Spring MVC文件上传
- Spring MVC数据绑定和表单标签的应用(附带实例)
- 慕课9、消息驱动的微服务-Spring Cloud Alibaba RocketMQ