一、认识Spring MVC
1.Spring MVC是Spring框架中用于web应用开发的一个模块,是Spring提供的一个基于MVC模式的优秀的web开发框架,本质上相当于Servlet。在MVC设计模式中,Spring MVC作为控制器(Controller)来建立模型与视图的数据交互。
2.在SpringMVC框架中,Controller框架替代Servlet来负担控制器的职责,Controller接受请求,并调用相应的Model进行处理,处理器完成业务处理后返回处理结果。Controller调用相应的View并对处理结果进行视图渲染,最终传送相应消息到客户端。
二、SpringMVC框架的体系结构
- 客户端发出HTTP请求,Web应用服务器接受此请求。若匹配DispatcherServlet的请求映射路径(在web.xml中指定),则Web容器将该请求转交给DispatherSerlvet处理。
- DispatherSerlvet接受到请求后,将根据请求的信息(包括URL、请求参数、HTTP方法等)及HandlerMapiing的配置(在web.xml中配置的)找到处理请求的处理器
- 当DispatherServlet根据HandlerMapping找到对应当前请求的Handler之后,通过HandlerAdpater对Handler进行封装,再以统一的适配器调用Handler。HandlerAdpater可以理解为具体使用Handler来干活的人,HanlderAdpater接口里一共有三个方法,如图所示。
1. supports(Object Hanlder)方法:判断是否可以使用某个Handler
2. handler方法:具体使用Handler处理请求
3. getLastModified方法: 获取资源的Last-Modified
- 在请求信息到达真正调用Handler的处理方法之前的这段时间内,Spring MVC还完成了很多工作,它会将请求信息以一定的方法转换并绑定到请求方法的入参中,对于入参的对象会进行数据转换、数据格式化以及数据校验等其他操作。这些做完之后才真正的调用Handler的处理方法进行相应的业务逻辑处理。
- 处理器完成业务逻辑处理之后返回一个ModelAndView对象给DispatcherSerlvet,ModelAndView对象包含了逻辑视图名和模型数据信息。
- ModelAndView对象中包含的是“逻辑视图名”,而非真正的试图对象。DispatcherServlet会通过ViewResolver将逻辑视图名解析为真正的视图对象View。负责数据展示的视图可以有很多种比如JSP、XML、JSON,可以对此灵活配置。
- 当得到真正的视图对象View后,DispatherServlet会使用ModelAndView对象中的模型数据对View进行视图渲染。
- 最后客户端获得响应消息,可以是html页面,也可以是xml或Json格式的数据等。
三、搭建环境
- 首先创建一个Maven的web骨架项目
- 然后在pom.xml引入相关的依赖
<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.5.RELEASE</version>
</dependency>
- 添加web.xml中关于SpringMVC的配置
<servlet>
<servlet-name>dispatcherServlet</servlet-name> <!-- servlet-name 可以自定义 -->
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 需要用 DispatcherServlet 对象来读取 SpringMVC 自己的配置文件 -->
<!-- init-param 用来帮助读取 SpringMVC 自己的配置文件 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
<!-- classpath 指的就是 main/resources 根目录,寻找 SpringMVC 的 xml 文件 -->
</init-param>
<load-on-startup>1</load-on-startup>
<!--配置标记容器在启动的时候就加载此DispatherSerlvet-->
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern> <!-- 拦截所有请求,直接写 / 即可 -->
</servlet-mapping>
- 在resources下添加springmvc.xml配置文件
<!-- 自动扫描:在 main/java 文件中写的所有类,都需要先扫描进 IoC 中进行管理 -->
<context:component-scan base-package="com.text"></context:component-scan>
<!-- 配置视图解析器:将逻辑视图解析为物理视图 -->
<!-- 比如说一个方法返回 "index" 这个字符串,现在想将这个字符串与 index.jsp 配置起来 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/view/"></property>
<!-- / 表示 webapp 文件夹的根目录,配置 index 的前缀,变为 "/index" -->
<property name="suffix" value=".jsp"></property>
<!-- .jsp 表示文件的后缀,配置 /index 的后缀,变为 "/index.jsp" -->
</bean>
<!-- 开启Spring对MVC注解的支持 -->
<mvc:annotation-driven />
<mvc:annotation-driven /> 配置该标签会自动注册DefaultAnnotationHandlerMapping(处理器映射)与AnnotationMethodHandlerAdapter(处理器适配器)这两个bean。Spring MVC需要通过这两个bean来完成对@Controller和@RequestMapping等注解的支持,从而找到URL与handler method的关系并给予关联。换句话说,完成在Spring容器中这两个bean的注册时Spring MVC为@Controller分发请求的必要支持
- 在WEB-INF文件夹下创建名为view的文件夹,用来存放jsp视图。创建一个hello.jsp
- 编写Controller
@Controller
public class FirstController {
@RequestMapping("/hello")
public String hello(){
return "hello";
}
}
7.启动服务器,输入 http://localhost:8080/项目名/hello
四、请求参数的绑定及常用注解
1. 请求参数的绑定说明
1.1 绑定机制
表单提交数据都是key=value形式的,如username=root
SpringMVC的参数绑定过程是把表单提交的请求参数,作为控制器中方法的参数进行绑定的
1.2 支持的数据类型
基本数据类型和字符串数据类型
实体类性(JavaBean)
集合数据类型(List、Map)
表单提交的name属性名称必须与参数中的名称保持一致
如果是实体类则实体类的属性要与表单提交的name属性名称保持一致
解决请求参数中文乱码的问题 在web.xml中配置如下:
<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>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
2.常用的注解
-
@Controller
在SpringMVC中,controller主要负责处理前端控制器(DispatcherServlet )发过来的请求,经过业务逻辑层处理之后封装层一个model,并将其返回给view进行展示。@controller注解通常用于类上,方法返回字符串可以指定逻辑视图的名称 -
@RestMapping
@RequestMapping 是一个用来处理请求地址映射的注解,它可以用于类上,也可以用于方法上。用于类上的注解会将一个特定请求或者请求模式映射到一个控制器之上,表示类中的所有响应请求的方法都是以该地址作为父路径;方法的级别上注解表示进一步指定到处理方法的映射关系。
常用的三个属性
value 属性:指定请求的实际地址,但只写一个属性时value 可以省略不写;
method 属性:指定请求的类型,主要有 GET、PUT、POST、DELETE,默认为 GET。
produces 属性:指定返回内容类型,如 produces = “application/json; charset=UTF-8”。
@Controller
@RequestMapping("/hello")
public class FirstController {
@RequestMapping(value = "/get", method = RequestMethod.GET,produces = "application/json; charset=UTF-8")
public String firstTest() {
return "hello";
}
}
此时访问路径为http://localhost:8080/hello/get
- @RequestBody
@RequestBody的作用是获取请求提的内容将json格式转化为java对象,该注解只能用于POST请求
required属性: 是否必须有请求体,默认是true。
@PostMapping("/user")
public String SecondController(@RequestBody User user) {
System.out.println("获取到的username为:" + user.getUsername());
System.out.println("获取到的password为:" + user.getPassword());
return "hello";
}
- @RequestParam
该注解是把请求的指定名称的参数传递给Controller的形参并赋值
value属性 :请求参数中的名称
required:请求参数中是否必须提供此参数,默认是true
@GetMapping("/user")
public String testRequstParam(@RequestParam("id") Integer UserId) { //注解名称可以和形参名称不一样 但注解名称必须和请求参数保持一致
System.out.println("获取到的id为:" + UserId);
return "hello";
}
- @PathVariable
该注解用于获取请求路径的占位符参数,如url为http://localhost:8080/user/get/{id}, {id}就是占位符
该注解支持Restful风格
@GetMapping("/user/{id}")
public String testPathVariable(@PathVariable("id") Integer id) {
System.out.println("获取到的id为:" + id);
return "hello";
}
请求路径为http://localhost:8080/user/1
则controller就会接受到1这个参数值
- @ResponseBody
该注解可以将返回值转换为Json,如果返回值是String或者其他基本数据类型则不满足key-value形式,不能转换为json,则返回字符串。可以用在类上也可以用在方法上,用在类上则该类的所有Controller都是返回json类型数据。
@GetMapping("/user")
@ResponseBody
public String testResponseBody() {
return "hello"; //此时返回值不再交给视图解析器 而是直接返回字符串数据
}
- @RestController
该注解是ResponseBody和Controller的结合