特点:
- Spring家族的原生项目,是Spring的一个子项目,与IOC等容器无缝对接
- 基于原生的Servlet,通过前端控制器DispatcherServlet,对请求和响应进行统一处理
- 表述层各细分领域需要解决的问题全方位覆盖,提供全面的解决方案
- 代码清晰简洁,大幅度提升开发效率
- 内部组件化程度高,可插拔式组件即插即用
- 性能卓越,适合现代大型、超大型互联网项目需求
Maven工程SpringMVC依赖
//web工程打包方式
<packaging>war</packaging>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>x.x.x</version>
</dependency>
web.xml配置文件
- 注入DispattcherServlet前端控制器
- 设置Spring配置文件路径
- 设置服务启动级别
- 路径映射
-
/所匹配的请求可以是/login或.html或.js或.css方式的请求路径
-
/不能匹配.jsp请求路径的请求
-
- 监听器
- 过滤器
- CharacterEncodingFilter 字符编码
- HiddenHttpMethodFilter URL请求方式
- 表单提交
- 请求方式必须POST
- 请求参数必须为_method(隐式表单标签)
-
<input type="hidden" name="_method" value="PUT" />
<?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>springMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:SpringMVC.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!--字符编码过滤器,解决中文乱码-->
<filter>
<filter-name>encodingFilter</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>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--请求方式过滤器,开启PUT/DELETE请求-->
<filter>
<filter-name>HiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HiddenHttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
SpringMVC配置文件
- 开启注解扫描组件
- 配置静态资源处理
- 注册mvc注解驱动
- 配置视图解析器
- InternalResourceViewResolver:jsp页面使用
- ThymeleafViewResolver
InternalResourceViewResolver SpringMVC原生视图
<?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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--静态资源扫描-->
<context:component-scan base-package="com.atguigu.controller"></context:component-scan>
<!--静态资源扫描-->
<mvc:default-servlet-handler/>
<!--注解驱动-->
<mvc:annotation-driven/>
<!--视图解析器-->
<bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--前缀-->
<property name="prefix" value="/WEB-INF/templates/"></property>
<!--后缀-->
<property name="suffix" value=".jsp"></property>
</bean>
</beans>
ThymeleafViewResolver 视图模版解析器
<?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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 自动扫描包 -->
<context:component-scan base-package="com.atguigu.mvc.controller"/>
<!-- 配置Thymeleaf视图解析器 -->
<bean id="viewResolver" class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
<property name="order" value="1"/>
<property name="characterEncoding" value="UTF-8"/>
<property name="templateEngine">
<bean class="org.thymeleaf.spring5.SpringTemplateEngine">
<property name="templateResolver">
<bean class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">
<!-- 视图前缀 -->
<property name="prefix" value="/WEB-INF/templates/"/>
<!-- 视图后缀 -->
<property name="suffix" value=".html"/>
<property name="templateMode" value="HTML5"/>
<property name="characterEncoding" value="UTF-8" />
</bean>
</property>
</bean>
</property>
</bean>
<!--
处理静态资源,例如html、js、css、jpg
若只设置该标签,则只能访问静态资源,其他请求则无法访问
此时必须设置<mvc:annotation-driven/>解决问题
-->
<mvc:default-servlet-handler/>
<!-- 开启mvc注解驱动 -->
<mvc:annotation-driven>
<mvc:message-converters>
<!-- 处理JSON响应中文内容乱码 -->
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="defaultCharset" value="UTF-8" />
<property name="supportedMediaTypes">
<list>
<value>text/html</value>
<value>application/json</value>
</list>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
</beans>
请求控制器
对前端控制器发送的请求进行统一处理,对不同的请求创建对应的方法的过程;即创建一个类,每个请求创建对应的方法处理,称为请求控制器。每一个方法称为控制器方法
@Conttroller
public class Controller{}
@RequestMapping请求映射注解
特点:
- 注解的值唯一
- 类:多用于不同模块功能开发
- 方法:具体请求路径
value属性
属性值必须设置,可以使用数组,只要有一个属性值匹配就可以访问
ant风格
- ?:表示任意单个字符
- *:表示任意0个或多个字符
- **:表示一层或多层目录
- 格式:/**/xxx
restful风格
- 格式:/{占位符}
- 控制器方法形参:@PathVariable("占位符")
- @PathVariable:将占位符所表示的数据赋值给控制器方法的形参
@RequestMapping("/test/{id}")
public String test(@PathVariable("id") int id){}
method属性
- RequestMethod.GET/RequestMethod.POST/RequestMethod.PUT/RequestMethod.DELETE
- 派生注解:GetMapping/PostMapping
请求路径满足value属性值,不满足method属性,页面报错405
params属性
- params:请求参数中必须携带params请求参数
- !params:请求参数中必须不携带params请求参数
- params=value:请求参数中必须携带params请求参数,且参数值等于value
- params!=value:请求参数中必须携带params请求参数,且参数值不等于value
headers属性
- headers:请求参数中必须携带headers请求头信息
- !headers:请求参数中必须不携带headers请求头信息
- headers=value:请求参数中必须携带headers请求头信息,且等于value
- headers!=value:请求参数中必须携带headers请求头信息,且不等于value
请求路径满足value属性值和method属性值,但是不满足params属性值或者headers属性值,页面报错400
SpringMVC请求参数获取
- ServletAPI
- request.getParameter()
- 控制器方法形参
- @RequestParam
- 请求参数和控制器方法的形参建立映射关系
- value:指定为形参赋值的请求参数的参数名
- required:设置是否必须传递此请求参数
- true:必须传请求参数,若value未传值,defaultValue值未设置,页面报错400
- false:不是必须传值,若未传值,形参值为null
- true:必须传请求参数,若value未传值,defaultValue值未设置,页面报错400
- defaultValue:无论required值是true或false,value属性值为空或者未传输时,使用默认值为形参赋值
- @RequestHeader
- 请求头信息和控制器方法的形参建立映射关系
- value
- required
- defaultValue
- @CookieValue
- cookie数据和控制器方法的形参建立映射关系
- value
- required
- defaultValue
- 控制器方法实体类形参(form表单)
- 请求参数的参数名和实体类的属性名一致,请求参数自动为此属性赋值
数据处理及跳转(数据回显)
ModelAndView
@RequestMapping("/test")
public ModelAndView test(){
ModelAndView mav = new ModelAndView();
mav.addObject("msg","hello world");
mav.serViewName("test");
return mav;
}
Model
@RequestMapping("/test")
public String test(String name,Model model){
model.addAttribute("name",name);
return "sucees";
}
Map
@RequestMapping("/test")
public String test(Map<String,Object> map){
map.put("name","name");
return "sucees";
}
ModelMap
@RequestMapping("/test")
public String test(String name,ModelMap model){
model.addAttribute("name",name);
return "sucees";
}
Session(session域)
@RequestMapping("/test")
public String test(HttpSession session){
session.setAttribute("session","Hello World");
return "success";
}
Application(整个项目)
@RequestMapping("/test")
public String test(HttpSession session){
ServletContext application = session.getServletContext();
application.setAttribute("session","hello world");
return "success";
}
页面跳转方式
- 转发:forward
@RequestMapping("/test")
public String test(){
return "forward:/success";
}
- 重定向:redirect
@RequestMapping("/test")
public String test(){
return "redirect:/success";
}
HttpMessageConverter报文信息转换器
将请求的报文转换为java对象,或者将java对象转换为响应报文
@RequestBody
- Post请求获取请求体
- 控制器方法形参前添加@RequestBody
@RequestMapping("/test")
public String test(@RequestBody String req){
System.out.println(req);
return "success";
}
RequestEntity
- 封装请求报文的一种类型
- 在控制器方法的形参设置该类型形参 RequestEntity<String>
- getHeaders():获取请求头
- getBody():获取请求体
@RequestMapping("/test")
public String test(RequestEntity<String> req){
System.out.println(req.getHeaders()+req.getBody());
return "success";
}
@ResponseBody
- 控制器方法添加@ResponseBody
- 该方法的返回值类型直接作为响应报文的响应体响应到浏览器
@RequestMapping("/test")
@ResponseBody
public String test(){
//success字符串直接响应到浏览器
return "success";
}
ResponseEntity
- 用于控制器方法的返回值类型
- 常用于文件的上传下载功能
@RestController
- 复合注解,@Controller/@ResponseBody
- 标识在请求控制器类上,为当前类添加@Controller注解,为类下所有方法添加@ResponseBody注解
Json数据交互
{}保存对象数据,[ ] 保存数组数据
Jackson
- 导jackson.jar包
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>x.x.x</version>
</dependency>
- 添加mvc注解驱动
<mvc:annotation-driven />
- 将java对象数据交由控制器方法的@ResponseBody注解处理,自动转换为json字符串
FastJson
- 导入FastJson包
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>x.x.x</version>
</dependency>
- JSON Java对象 转 JSON字符串
- JSONArray JSON字符串 转 Java对象
- JSONObject Java对象 转 JSON对象
JSON数据中文乱码
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg value="UTF-8"/>
</bean>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper">
<bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
<property name="failOnEmptyBeans" value="false"/>
</bean>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
文件上传与下载
上传功能
- 导入上传依赖jar包
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>x.x.x</version>
</dependency>
- xml配置文件解析器
- id必须为multipartResolver
<!--必须通过文件解析器的解析才能将文件转换为MultipartFile对象-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"></bean>
- 上传控制器方法
@RequestMapping("/Up")
public String testUp(MultipartFile photo, HttpSession session) throws IOException {
//获取上传的文件的文件名
String fileName = photo.getOriginalFilename();
//处理文件重名问题
String hzName = fileName.substring(fileName.lastIndexOf("."));
fileName = UUID.randomUUID().toString() + hzName;
//获取服务器中photo目录的路径
ServletContext servletContext = session.getServletContext();
String photoPath = servletContext.getRealPath("photo");
File file = new File(photoPath);
if(!file.exists()){
file.mkdir();
}
String finalPath = photoPath + File.separator + fileName;
//实现上传功能
photo.transferTo(new File(finalPath));
return "success";
}
下载功能实现
@RequestMapping("/Download")
public ResponseEntity<byte[]> testResponseEntity(HttpSession session) throws IOException {
//获取ServletContext对象
ServletContext servletContext = session.getServletContext();
//获取服务器中文件的真实路径
String realPath = servletContext.getRealPath("/static/img/1.jpg");
//创建输入流
InputStream is = new FileInputStream(realPath);
//创建字节数组
byte[] bytes = new byte[is.available()];
//将流读到字节数组中
is.read(bytes);
//创建HttpHeaders对象设置响应头信息
MultiValueMap<String, String> headers = new HttpHeaders();
//设置要下载方式以及下载文件的名字
headers.add("Content-Disposition", "attachment;filename=1.jpg");
//设置响应状态码
HttpStatus statusCode = HttpStatus.OK;
//创建ResponseEntity对象
ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(bytes, headers, statusCode);
//关闭输入流
is.close();
return responseEntity;
}
拦截器
- 创建一个类,继承HandlerInterceptor接口,重写接口的3个方法
- preHandle
- postHandle
- AfterComplation
- SpringMVC.xml配置拦截器(对所有请求进行拦截)
方法 一
<mvc:interceptors>
<bean class="拦截器全限定类名路径"></bean>
</mvc:interceptors>
方法二
<mvc:interceptors>
<!--ref需要开启扫描注解,类名添加注解@Component-->
<ref bean="类名">
</mvc:interceptors>
方法三
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**" />
<!-排除不拦截的请求路径-->
<mvc:exclude-mapping path="/" />
<ref bean="拦截器类名"></ref>
</mvc:interceptor>
</mvc:interceptors>
异常处理器
两个接口实现类
- DefaultHandlerExceptionResolver:Spring默认异常处理器
- SimpleMappingExceptionResolver
配置文件
<!--配置异常处理-->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<!--设置异常跳转的页面 error视图名称-->
<prop key="异常全路径名">error</prop>
</props>
</property>
<!--设置将异常信息共享在请求域中的键-->
<property name="exceptionAttribute" value="ex"></property>
</bean>
注解配置
@ControllerAdvice:标识在控制器类上,将当前类标识为异常处理组件,@Component的扩展注解组件
@ExceptionHandler():标识控制器方法能处理的异常
Exception:当前请求中出现的异常对象
@ControllerAdvice
public class ExceptionController {
@ExceptionHandler(value = {异常名.class,NullPointerException.class})
public String testException(Exception ex, Model model){
model.addAttribute("ex",ex);
return "error";
}
}
注解配置SpringMVC方式
配置类(web.xml)
AbstractAnnotationConfigDispatcherServletInitializer
public class SpringConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
/**
* Spring配置类
* @return
*/
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[]{Spring.class};
}
/**
* SpringMVC配置类
* @return
*/
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{SpringMVC.class};
}
/**
* DispatcherServlet的映射规则,即 url-pattern
* @return
*/
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
/**
* 过滤器
* @return
*/
@Override
protected Filter[] getServletFilters() {
CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
characterEncodingFilter.setEncoding("utf-8");
characterEncodingFilter.setForceEncoding(true);
HiddenHttpMethodFilter hiddenHttpMethodFilter = new HiddenHttpMethodFilter();
return new Filter[]{characterEncodingFilter,hiddenHttpMethodFilter};
}
}
配置类(SpringMVC.xml)
@Configuration
//扫描组件
@ComponentScan("com.atguigu.mvc.controller")
//开启MVC注解驱动
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
//使用默认的servlet处理静态资源
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
//配置文件上传解析器
@Bean
public CommonsMultipartResolver multipartResolver(){
return new CommonsMultipartResolver();
}
//配置拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
FirstInterceptor firstInterceptor = new FirstInterceptor();
registry.addInterceptor(firstInterceptor).addPathPatterns("/**");
}
//配置视图控制
/*@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("index");
}*/
//配置异常映射
/*@Override
public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
SimpleMappingExceptionResolver exceptionResolver = new SimpleMappingExceptionResolver();
Properties prop = new Properties();
prop.setProperty("java.lang.ArithmeticException", "error");
//设置异常映射
exceptionResolver.setExceptionMappings(prop);
//设置共享异常信息的键
exceptionResolver.setExceptionAttribute("ex");
resolvers.add(exceptionResolver);
}*/
//配置生成模板解析器
@Bean
public ITemplateResolver templateResolver() {
WebApplicationContext webApplicationContext = ContextLoader.getCurrentWebApplicationContext();
// ServletContextTemplateResolver需要一个ServletContext作为构造参数,可通过WebApplicationContext 的方法获得
ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(
webApplicationContext.getServletContext());
templateResolver.setPrefix("/WEB-INF/templates/");
templateResolver.setSuffix(".html");
templateResolver.setCharacterEncoding("UTF-8");
templateResolver.setTemplateMode(TemplateMode.HTML);
return templateResolver;
}
//生成模板引擎并为模板引擎注入模板解析器
@Bean
public SpringTemplateEngine templateEngine(ITemplateResolver templateResolver) {
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(templateResolver);
return templateEngine;
}
//生成视图解析器并未解析器注入模板引擎
@Bean
public ViewResolver viewResolver(SpringTemplateEngine templateEngine) {
ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
viewResolver.setCharacterEncoding("UTF-8");
viewResolver.setTemplateEngine(templateEngine);
return viewResolver;
}
}