一、概念
SpringMVC是Spring家族中的一个MVC框架,专门用来做web开发,底层是servlet。
二、回顾Servlet
1.实现一个Servlet,重写doGet和doPost等方法
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String method = req.getParameter("method");
if(method.equals("add")){
req.getSession().setAttribute("msg", "执行了add方法");
}
if(method.equals("delete")){
req.getSession().setAttribute("msg", "执行了delete方法");
}
req.getRequestDispatcher("/WEB-INF/jsp/test.jsp").forward(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
2.在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_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.xiang.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
3.写一个视图层
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
$END$
</body>
</html>
4.pom依赖(下面都需要)
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.xiang</groupId>
<artifactId>springmvc_demo</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
<module>springmvc-01-servlet</module>
<module>springmvc-02</module>
<module>springmvc-annotation</module>
</modules>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.6.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
</project>
三、为什么使用SpringMVC
特点:
- 轻量级,简单易学
- 高效,基于请求响应的MVC的框架
- spring家族,无缝集成spring
- 约定优于配置
- 功能强大,RESTFUL、数据验证、格式化、本地化
流程图:
- DispatcherServlet接收所有请求
- DispatcherServlet调用HandlerMapping,根据url获取对应Handler
- HandlerExecution表示具体的Handler,根据url查找控制器Controller
- HandlerExecution将解析后的信息传递给DispatcherServlet,如控制器映射等
- HandlerAdapter表示处理器适配器,按特定规则执行Handler
- Handler让具体Controller执行
- Controller执行完毕后,将ModelAndView返回给HandlerAdapter
- HandlerAdapter将视图模型信息返回给DispatcherServlet
- DispatcherServlet调用视图解析器来解析逻辑视图
- ViewResolver将解析后的物理视图名称返回给DispatcherServlet
- DispatcherServlet调用物理视图,并将Model传入
- View渲染并将视图呈现给用户
四、完整(复杂)版配置流程
1.在web.xml配置DispatcherServlet拦截所有请求,并配置spring-servlet.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_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>springMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<!-- 设置spring xml文件路径 -->
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-servlet.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<!-- / 会拦截所有请求,但不包括jsp文件 -->
<!-- /* 会拦截所有请求,包括jsp文件 -->
<servlet-name>springMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
2.声明配置Bean(spring-servlet.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--请求映射器-->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
<!--适配器-->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
<!--视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="resourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!--注册Controller-->
<bean id="/hello" class="com.xiang.mvc.HelloController"/>
</beans>
3.创建实际Controller
public class HelloController implements Controller {
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("hello");
modelAndView.addObject("msg","this is controller");
return modelAndView;
}
}
4.创建视图层(hello.jsp)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
${msg}
</body>
</html>
五、注解版开发
1.创建web工程
2.添加lib
3.配置DispatcherServlet(web.xml)
同上
4.声明配置Bean(spring-servlet.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:mvc="http://www.springframework.org/schema/mvc"
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/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<mvc:default-servlet-handler />
<mvc:annotation-driven />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="resourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
<context:component-scan base-package="com.xiang.mvc" />
</beans>
5.注解版Controller
@Controller
public class HelloController {
@RequestMapping("/hello")
public String hello(Model model){
model.addAttribute("msg", "this is annotation controller");
return "hello";
}
}
6.视图层(hello.jsp)
同上
六、零散知识点
1.请求转发与重定向
请求转发:内部服务器
重定向:浏览器重新发起请求
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class ForwardAndRedirect {
@RequestMapping("/test1")
public String forward(Model model){
model.addAttribute("msg", "this is forward");
return "forward:test2";
}
@RequestMapping("/test2")
public String forward2(Model model){
return "hello";
}
@RequestMapping("/test3")
public String redirect1(Model model){
model.addAttribute("msg", "this is forward");
return "redirect:test4";
}
@RequestMapping("/test4")
public String redirect(Model model){
return "hello";
}
}
2.乱码问题
1.首先保证tomcat编码为UTF-8
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" URIEncoding="UTF-8" />
2.设置编码过滤器
<?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">
<!--略...-->
<!--编码过滤器-->
<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>
</web-app>
3.JSON
JavaScript Object Notation(JS对象标记),一种轻量级的数据交换格式。
①Demo
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Json Demo</title>
</head>
<body>
<script type="text/javascript">
const user = {
name: "xiang",
age: "18"
};
console.log(user);
console.log("============");
const userJson = JSON.stringify(user);
console.log(userJson);
console.log("============");
const user2 = JSON.parse(userJson);
console.log(user2);
</script>
Hello
</body>
</html>
②Jackson
引入包
<dependencies>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.10.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.6</version>
</dependency>
</dependencies>
注入bean
<?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:mvc="http://www.springframework.org/schema/mvc"
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/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<mvc:default-servlet-handler />
<mvc:annotation-driven />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="resourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
<context:component-scan base-package="com.xiang.mvc" />
<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>
</beans>
controller
@RestController
public class JsonDemoController {
@GetMapping("/json1")
public String json1() throws JsonProcessingException {
User user = new User("希昂", 18);
ObjectMapper objectMapper = new ObjectMapper();
String result = objectMapper.writeValueAsString(user);
return result;
}
@GetMapping("/json2")
public String json2() throws JsonProcessingException {
List<User> list = new ArrayList<User>();
User user1 = new User("希昂", 18);
User user2 = new User("希昂2", 18);
list.add(user1);
list.add(user2);
ObjectMapper objectMapper = new ObjectMapper();
String result = objectMapper.writeValueAsString(list);
return result;
}
@GetMapping("/json3")
public String json3() throws JsonProcessingException {
Date date = new Date();
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
String result = objectMapper.writeValueAsString(date);
return result;
}
}
③FastJson
<dependency>
<groupId>com.ailibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.60</version>
</dependency>
七、拦截器
SpringMVC拦截器,类似于Serlvet开发中的过滤器Filter,用于对处理器进行预处理和后置处理,可以利用拦截器实现某些功能。
核心思想:AOP
只针对控制控制器方法,不会对jsp等静态资源生效。
1.自定义拦截器
继承HandleInteceptor
public class MyInterceptor implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle...");
return false;
}
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle...");
}
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion...");
}
}
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.xiang.mvc.config.MyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>