Spring MVC
Spring MVC介绍
MVC是什么
Spring MVC
- Spring MVC是Spring体系的轻量级WEB MVC框架
- Spring MVC的核心Controller控制器,用于处理请求,产生响应
- Spring MVC基于Spring IoC容器运行,所有对象被IoC管理
Spring 5.X版本变化
- Spring 5.x最低要求JDK8与J2EE 7(Servlet 3.1/Tomcat 8.5+)
- Spring 5.x支持JDK8/9,可以使用新特性
- Spring 5.x最重要的新特性支持响应式编程
Spring MVC环境配置
- Maven依赖spring-webmvc
- web.xml配置DispatcherServlet
- 配置applicationContext的mvc标记
- 开发Controller控制器
简单示例:
applicationContext.xml:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mv="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 标签作用 在Spring IOC初始化过程中,自动创建并管理com.imooc.springmvc及子包 拥有以下注解的对象 @Repository @Service @Controller @Component --> <context:component-scan base-package="com.imooc.springmvc"/> <!--启用Spring MVC的注解开发模式--> <mvc:annotation-driven/> <!--将图片/JS/CSS等静态资源排除在外,可提高执行效率--> <mvc:default-servlet-handler/> </beans>
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_3_1.xsd" version="3.1"> <!--DispatchServlet--> <servlet> <servlet-name>springmvc</servlet-name> <!-- DispatcherServlet是Spring MVC最核心的对象 DispatcherServlet用于拦截Http请求, 并根据请求的URL调用与之对应的Controller方法,来完成Http请求的处理 --> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!--applicationContext.xml--> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </init-param> <!-- 在Web应用启动时自动创建Spring IOC容器, 并初始化DispatcherServlet --> <load-on-startup>0</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <!--"/" 代表拦截所有请求--> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
TestController.java
package com.imooc.springmvc.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; /** * @author Rex * @create 2021-01-08 16:59 */ @Controller public class TestController { @GetMapping("/t") @ResponseBody //直接向响应输出字符串数据,不跳转页面 public String test(){ return "HELLO WORLD"; } }
结果:
Spring MVC数据绑定
URL Mapping
- URL Mapping指将URL与Controller方法绑定
- 通过将URL与方法绑定,SpringMVC便可通过Tomcat对外暴露服务
URL Mapping注解
- @RequestMapping - 通用绑定
- @GetMapping - 绑定Get请求
- @PostMapping - 绑定Post请求
接受请求参数的常用做法
- 使用Controller方法参数接受(@RequestParam)
- 使用Java Bean接受数据
接受表单复合数据
- 利用数组或者List接受请求中给的复合数据
- 利用@RequestParam为参数设置默认值
- 使用Map对象接受请求参数及注意事项
关联对象赋值
日期类型转换
-
@DateTimeFormat
-
自定义转换器
MyDateConverter.java
package com.imooc.springmvc.converter; import org.springframework.core.convert.converter.Converter; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; /** * @author Rex * @create 2021-01-09 10:34 */ public class MyDateConverter implements Converter<String, Date> { @Override public Date convert(String s) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); try { Date d = sdf.parse(s); return d; } catch (ParseException e) { return null; } } }
applicationContext.xml
<mvc:annotation-driven conversion-service="conversionService"/> <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"> <property name="converters"> <set> <bean class="com.imooc.springmvc.converter.MyDateConverter"/> </set> </property> </bean>
tip: @DateTimeFormat和自定义转换器最好不要同时使用,spring会优先使用自定义转换器
解决中文乱码问题
Web应用的中文乱码由来
- Tomcat默认使用字符集ISO-8859-1,属于西欧字符集
- 解决乱码的核心思路是将ISO-8859-1转换为UTF-8
- Controller中请求与响应都需要设置UTF-8字符集
中文乱码的配置
-
Get请求乱码-server.xml增加URIEncoding属性
-
Post请求乱码-web.xml配置CharacterEncodingFilter
-
Response响应乱码-Spring配置StringHttpMessageConverter
示例代码:
web.xml
<filter> <filter-name>characterFilter</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>characterFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
applicationContext.xml
<mvc:annotation-driven conversion-service="conversionService"> <mvc:message-converters> <bean class="org.springframework.http.converter.StringHttpMessageConverter"> <property name="supportedMediaTypes"> <list> <!--response.setContentType("text/html; charset=utf-8")--> <value>text/html;charset=utf-8</value> </list> </property> </bean> </mvc:message-converters> </mvc:annotation-driven>
响应输出
响应中产生结果
- @ResponseBody - 产生响应文本
- ModelAndView - 利用模板引擎渲染输出
@ResponseBody
- @ResponseBody直接产生响应体的数据,过程中不产生任何视图
- @ResponseBody可产生标准字符串/JSON/XML等格式数据
- @ResponseBody被StringHttpMessageConverty所影响
ModelAndView概述
- ModelAndView是指“模型(数据)与视图(界面)”对象
- 通过ModelAndView可将数据对象与模板引擎进行绑定
- SpringMVC中默认的View是JSP,也可以配置其他模板引擎
使用示例:
URLMappingController.java
@GetMapping("/view") public ModelAndView showView(Integer userId){ ModelAndView mav = new ModelAndView("/view.jsp"); User user = new User(); if (userId == 1){ user.setUsername("lily"); }else if(userId == 2){ user.setUsername("smith"); }else if(userId == 3){ user.setUsername("lina"); } mav.addObject("u", user); return mav; }
view.jsp
<%-- Created by IntelliJ IDEA. User: CubeMonkey Date: 2021/1/9 Time: 11:27 Email:2192231938@qq.com To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>View</title> </head> <body> <h1>I'm view page</h1><hr/> <h2>Username:${u.username}</h2> </body> </html>
ModelAndView方法
- mav.addObject()方法设置的属性默认存放在当前请求中
- 默认ModelAndView使用请求转发(forward)至页面
- 重定向使用new ModelAndView(“redirect:/index,jsp”)
String+ModelMap 实现ModelAndView(常见)
示例代码:
//String 与 ModelMap
//Controller方法返回String的情况
//1. 方法被@ResponseBody描述,SpringMVC直接响应String字符串本身
//2. 方法不存在@ResponseBody,则SpringMVC处理String指代的视图(页面)
@GetMapping("/xxxx")
@ResponseBody
public String showView1(Integer userId, ModelMap modelMap){
String view = "/view.jsp";
User user = new User();
if (userId == 1){
user.setUsername("lily");
}else if(userId == 2){
user.setUsername("smith");
}else if(userId == 3){
user.setUsername("lina");
}
modelMap.addAttribute("u", user);
return view;
}
SpringMVC整合Freemarker
-
pom.xml引入依赖
<dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>2.3.30</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>5.3.2</version> </dependency>
-
启用Freemarker模板引擎(FreeMarkerViewResolver)
<bean id="ViewReslover" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver"> <!--向客户端输出内容的时候设置的字符集--> <property name="contentType" value="text/html;charset=utf-8"/> <property name="suffix" value=".ftl"/> </bean>
-
配置Freemarker参数(FreemarkerConfigurer)
<bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer"> <property name="templateLoaderPath" value="/WEB-INF/ftl"/> <property name="freemarkerSettings"> <props> <!--为产生结果的时候的字符集--> <prop key="defaultEnocding">UTF-8</prop> </props> </property> </bean>
-
使用Freemarker
test.ftl
<h1>${u.username}</h1>
FreemarkerController.java
package com.imooc.springmvc.controller; import com.imooc.springmvc.entity.User; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; /** * @author Rex * @create 2021-01-09 14:25 */ @Controller @RequestMapping("/fm") public class FreemarkerController { @GetMapping("/test") public ModelAndView showTest(){ ModelAndView mav = new ModelAndView("/test"); User user = new User(); user.setUsername("andy"); mav.addObject("u", user); return mav; } }