一、快速入门
- xml方式:
- 导入坐标
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.7.RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<port>80</port>
<path>/</path>
</configuration>
</plugin>
</plugins>
</build>
- 在web.xml里配置前端控制器
<!--SpringMVC的前端控制器-->
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--加载第四步的spring-mvc.xml文件-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
- 创建controller
package com.ylf.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller // 把UserController放在spring容器
public class UserController {
@RequestMapping("/index") // 请求映射
public String save() {
System.out.println("save running...");
return "index.jsp"; // 跳转的jsp地址
}
}
4.创建spring-mvc.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"
xsi:schemaLocation="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">
<!--controller包扫描-->
<context:component-scan base-package="com.ylf.controller"></context:component-scan>
</beans>
- 注解方式(推荐):
- 导入坐标同上
- 创建SpringMvcConfig配置类
package com.ylf.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("com.ylf.controller")
public class SpringMvcConfig {}
- 创建ServletContainersIntiConfig配置类
package com.ylf.config;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.support.AbstractDispatcherServletInitializer;
public class ServletContainersIntiConfig
extends AbstractAnnotationConfigDispatcherServletInitializer {
//加载Spring容器
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] {SpringConfig.class};
}
// 加载SpringMvc容器
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] {SpringMvcConfig.class};
}
// 所有请求都归SpringMvc处理
@Override
protected String[] getServletMappings() {
return new String[] {"/"};
}
}
- 创建controller
package com.ylf.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class UserController {
@RequestMapping("/save")
@ResponseBody
public String save() {
return "{'info':'xxx'}";
}
}
二、SpringMVC执行流程
-
工作原理图
image.png -
springmvc工作流程
1、 用户向服务端发送一次请求,这个请求会先到前端控制器DispatcherServlet(也叫中央控制器)。
2、DispatcherServlet接收到请求后会调用HandlerMapping处理器映射器。由此得知,该请求该由哪个Controller来处理(并未调用Controller,只是得知)
3、DispatcherServlet调用HandlerAdapter处理器适配器,告诉处理器适配器应该要去执行哪个Controller
4、HandlerAdapter处理器适配器去执行Controller并得到ModelAndView(数据和视图),并层层返回给DispatcherServlet
5、DispatcherServlet将ModelAndView交给ViewReslover视图解析器解析,然后返回真正的视图。
6、DispatcherServlet将模型数据填充到视图中
7、DispatcherServlet将结果响应给用户 -
组件说明
- DispatcherServlet:前端控制器,也称为中央控制器,它是整个请求响应的控制中心,组件的调用由它统一调度。
- HandlerMapping:处理器映射器,它根据用户访问的 URL 映射到对应的后端处理器 Handler。也就是说它知道处理用户请求的后端处理器,但是它并不执行后端处理器,而是将处理器告诉给中央处理器。
- HandlerAdapter:处理器适配器,它调用后端处理器中的方法,返回逻辑视图 ModelAndView 对象。
- ViewResolver:视图解析器,将 ModelAndView 逻辑视图解析为具体的视图(如 JSP)。
- Handler:后端处理器,对用户具体请求进行处理,也就是我们编写的 Controller 类。
三、注解解析
- @RequestMapping:
作用:用于建立请求url和处理请求方法之间的对应关系
位置:类上,请求访问url的第一级访问目录,此处不写就相当于应用的根目录。方法上,请求url的第二级访问目录,与类上使用@RequestMapping标注的一级目录组成访问目录如/user/xxx
属性:
value,用于指定请求的url,它和path的属性一样。
mathod,用于指定请求的方式,比如:method=RequestMethod.POST。
params,用于指定限制请求参数的条件,它支持简单的表达式,要求请求参数的key和value必须和配置的一样。
四、bean加载控制
为了避免spring加载到本应该由SpringMVC加载的内容
SpringMVCConfig
//根据注解排除,controller
@ComponentScan(
value = "com.ylf",
excludeFilters =
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Controller.class))
或者直接精确包扫描
五、数据响应和数据请求
- 乱码处理:
在ServletContainersIntiConfig配置类
//乱码处理
@Override
protected Filter[] getServletFilters() {
final CharacterEncodingFilter filter = new CharacterEncodingFilter();
filter.setEncoding("utf-8");
return new Filter[]{filter};
}
- 参数传递
// 普通参数
@RequestMapping("/save")
@ResponseBody
public String save(String name) {
System.out.println(name);
return "{'info':'ok'}";
}
// pojo参数
@RequestMapping("/add")
@ResponseBody
public String add(User user) {
System.out.println(user);
return "{'info':'ok'}";
}
// 数组参数
@RequestMapping("/arrayParam")
@ResponseBody
public String arrayParam(String[] likes) {
System.out.println(likes);
return "{'info':'ok'}";
}
// 集合参数
@RequestMapping("/listParam")
@ResponseBody
public String arrayParam(@RequestParam ArrayList<String> likes) {
System.out.println(likes);
return "{'info':'ok'}";
}
- json参数传递
- 第一步导入坐标
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
- 在SpringMvcConfig加上
@EnableWebMvc
public class SpringMvcConfig {}
- 获得参数
// json参数
@RequestMapping("/jsonParam")
@ResponseBody
public String jsonParam(@RequestBody User user) {
System.out.println(user);
return "{'info':'ok'}";
}
// json参数
@RequestMapping("/jsonListParam")
@ResponseBody
public String jsonListParam(@RequestBody List<User> user) {
System.out.println(user);
return "{'info':'ok'}";
}
// 日期参数
@RequestMapping("/dateParam")
@ResponseBody
public String dateParam(@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date date) {
System.out.println(date);
return "{'info':'ok'}";
}
- 数据响应
// 返回json对象
@RequestMapping("/toJson")
@ResponseBody
public User toJson(){
final User user = new User();
user.setId(1);
user.setName("张三");
return user;
}
// 返回json集合对象
@RequestMapping("/toListJson")
@ResponseBody
public List<User> toListJson(){
final User user1 = new User();
user1.setId(1);
user1.setName("张三");
final User user2 = new User();
user2.setId(1);
user2.setName("李四");
final List<User> users = new ArrayList<User>();
users.add(user1);
users.add(user2);
return users;
}
- rest风格
// @RestController等于@Controller和@ResponseBody
@RestController
@RequestMapping("/users")
public class UserController {
// 普通参数
@RequestMapping(value = "/{id}",method = RequestMethod.POST)
public String save(@PathVariable Integer id) {
System.out.println(id);
return "{'message':'ok'}";
}
}
// @PostMapping 相当于@RequestMapping(method = RequestMethod.POST)
@PostMapping
public String save(){
return "{'message':'ok'}";
}
// @DeleteMapping 相当于@RequestMapping(value = "/{id}",method = RequestMethod.Delete)
@DeleteMapping("/{id}")
public String delete(){
return "{'message':'ok'}";
}
- 拦截器
- 创建controller.interceptor.ProjectInterceptor
package com.ylf.controller.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ProjectInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
return true;
}
@Override
public void postHandle(
HttpServletRequest request,
HttpServletResponse response,
Object handler,
ModelAndView modelAndView)
throws Exception {
System.out.println("postHandle");
}
@Override
public void afterCompletion(
HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
System.out.println("afterCompletion");
}
}
- 创建config.SpringMvcSupport
package com.ylf.config;
import com.ylf.controller.interceptor.ProjectInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
@Configuration
public class SpringMvcSupport extends WebMvcConfigurationSupport {
@Autowired private ProjectInterceptor projectInterceptor;
/**
* SpringMVC不去拦截pages页面
*
* @param registry
*/
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");
}
/**
* 拦截/students下的所有请求
*
* @param registry
*/
@Override
protected void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(projectInterceptor).addPathPatterns("/students");
}
}
- 在SpringMvc下加载SpringMvcSupport
@Configuration
@ComponentScan({"com.ylf.controller", "com.ylf.config"})
@EnableWebMvc
public class SpringMvcConfig {}
- 或者直接在SpringMvcConfig下实现WebMvcConfigurer接口,这样就不用去创建新的配置类
package com.ylf.config;
import com.ylf.controller.interceptor.ProjectInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
@ComponentScan({"com.ylf.controller"})
@EnableWebMvc
public class SpringMvcConfig implements WebMvcConfigurer {
@Autowired private ProjectInterceptor projectInterceptor;
/**
* 拦截/students下的所有请求
*
* @param registry
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(projectInterceptor).addPathPatterns("/students/*");
}
/**
* SpringMVC不去拦截pages页面
*
* @param registry
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");
}
}
网友评论