目录
一、概述
SpringMVC是基于MVC思想实现的web开发框架。可以用来替代Servlet的使用。
SpringMVC的优点:
1)简化Servlet的繁琐操作;
2)基于组件设计。ViewResolver urlmapper
3)springmvc支持不同视图技术,jsp、html、freemarkder等等
4)很方便与ajax进行数据交互。jackson List Map等等
二、运行原理
- 当用户发起请求的时候,首先该请求会被前端控制器(DispatcherServlet)拦截;
- 前端控制器会调用HandlerMapping组件根据请求路径生成一个Handler对象,并返回给前端控制器;
- 前端控制器调用HandlerAdapter组件执行Handler;
- Handler返回一个ModelAndView给前端控制器;
- 前端控制器获取到ModelAndView对象后,就会调用ViewResolver组件根据viewName把对应的视图页面加载出来。加载出来后进行数据渲染,渲染完成最后把页面的内容发送给浏览器显示。
三、SpringMVC组件
3.1 HandlerMapping组件
SimpleUrlHandlerMapping:该处理器是根据请求URL来匹配Bean的id属性。
BeanNameUrlHandlerMapping:该处理器根据请求名来查找匹配的Bean。
ControllerClassNameHandlerMapping:该处理器是根据请求名和Controller的类名进行匹配。请求名就是Controller类名,然后把Controller去掉的名字。例如:HelloController -> /hello*。
3.2 Handler组件
UrlFilenameViewController:把请求名直接转换成视图名,并返回该视图。
ParameterizableViewController:该控制器总是返回一个预定义的视图。
ServletForwardingController:把请求转发给一个Servlet来处理。
MultiActionController:该处理器允许在一个Controller中处理多个请求。
3.3 Resolver组件
InternalResourceViewResolver:把JSP解析成View对象。
PropertiesMethodNameResolver:根据指定的请求URL适配指定的方法。
InternalPathMethodNameResolver:根据请求的URL自动适配相应的方法。
StandardServletMultipartResolver:文件上传解析器
四、入门示例
第一步:
下载jar包:Spring
或者使用Maven下载依赖包
<dependencies>
<!--Spring依赖包-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.9.RELEASE</version>
</dependency>
<!--Spring-web包-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.0.9.RELEASE</version>
</dependency>
<!--Spring-webMVC包-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.9.RELEASE</version>
</dependency>
<!-- servlet依赖的jar包 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<!-- jsp依赖jar包 -->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.1</version>
</dependency>
<!--jstl标签依赖的jar包 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
第二步:
配置tomcat服务器,具体操作见:
IDEA之配置和使用Tomcat
第三步:
在web.xml配置核心控制器
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<!-- 配置Spring的核心控制器 -->
<servlet>
<servlet-name>SpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
第四步:
创建一个类,实现Controller接口,并重写handleRequest方法
public class HelloController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
System.out.println("进入到Hello控制器中");
ModelAndView mv = new ModelAndView();
mv.setViewName("hello"); // 设置视图名
return mv;
}
}
第五步:
在WEB-INF目录下新建SpringMVC配置文件
配置文件名称格式为“控制器名(web.xml中配置的核心控制器名字)-servlet.xml”
配置文件内容如下:
<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:aop="http://www.springframework.org/schema/aop"
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/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--配置控制器类-->
<bean id="hello" class="com.tung.HelloWorld.controller.HelloController"/>
<!-- 定义URL匹配器 -->
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="sayHello.do">hello</prop>
</props>
</property>
</bean>
<!-- 配置结果解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
第六步:
在WEB-INF/jsp目录下新建一个jsp文件,文件内容如下:
<h2>Hello World!</h2>
第七步:
启动Tomcat服务器,然后在浏览器上输入地址http://localhost:8080/sayHello.do
五、SpringMVC注解
5.1 常用注解
注解名 | 作用范围 | 功能 |
---|---|---|
@Controller | 在类上使用 | 标注该类是一个控制器类 |
@RequestMapping | 可以在类上使用,也可以在方法上使用 | 指定请求的url路径 |
@RequestParam | 在形参中使用 | 用于指定参数名 |
@PathVariable | 在形参中使用 | 处理请求url中的占位参数 |
@ResponseBody | 在方法上使用 | 把方法的返回值内容输出到页面上 |
@SessionAttributes | 在类上使用 | 把model中指定名字或类型的属性绑定到session |
@ModelAttribute | 在形参中使用 | 从session中获取数据,并且绑定到指定参数中。 |
5.2 环境准备
在src目录下创建Spring的配置文件applicationContext.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"
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">
<!-- 启动注解功能 -->
<mvc:annotation-driven/>
<!-- 启用包扫描功能 -->
<context:component-scan base-package="com.tung.HelloWorld.controller"/>
</beans>
六、中文乱码问题
提交表单数据时,浏览器会使用页面编码UTF-8进行编码,而服务器使用默认的字符集(iso-8859-1)进行解码。因为编码和解码使用了不同的字符集,才导致了获取的参数出现中文乱码的问题。
一般有两种办法解决中文乱码问题:
6.1 手动解决
对数据进行字符集转换
name = new String(name.getBytes("iso-8859-1"), "utf-8");
6.2 全局处理
在web.xml文件中配置CharacterEncodingFilter过滤器,该过滤器用于处理所有请求的中文乱码问题。
<!-- 处理中文乱码的过滤器 -->
<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>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
注意:在实际开发中,应该使用全局的方式来处理请求的中文乱码。
使用过滤器可能导致web.xml报红,那是因为我是用maven创建的,默认使用的是Servlet2.3模板,最后将头部改成Servlet3.1的就好了
<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">
6.3 响应中有中文乱码
如果响应内容包含中文,那么可以在@RequestMapping注解中使用produces属性来指定响应数据的编码格式。
@RequestMapping(value = "/{id}/del.do",method = RequestMethod.GET,produces = {"text/html;charset=utf-8"})
七、请求路径的优先级
@Controller
@RequestMapping("/hello")
public class hello{
@RequestMapping("/test.do")
public String test1(){
return "test1...";
}
@RequestMapping("/*.do")
public String test2(){
return "test2...";
}
@RequestMapping("/test*.do")
public String test3(){
return "test3...";
}
}
当访问路径http://localhost:8080/hello/test.do时,匹配顺序为:*test.do > test.*.do> .do;
匹配成功则不会继续匹配。
八、参数传递
springmvc使用model对象来传递数据。例如:
@RequestMapping(value = "/sayHi")
public String sayHi(Model model){
// 使用model传递数据
model.addAttribute("name", "aabbcc");
// 返回视图名
return "hello";
}
上面方法返回视图名,对应着hello.jsp页面。页面内容如下:
<%--
Created by IntelliJ IDEA.
User: ss
Date: 2021/2/18
Time: 16:09
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %><html>
<head>
<title>Title</title>
</head>
<body>
<h1>欢迎${name}回来!</h1>
</body>
</html>
效果如下:
九、方法返回值
控制器方法可以返回不同类型的数据。除了ModelAndView类型以外,还可以是String类型,代表视图名。例如:
@RequestMapping(value = "/sayHi")
public String sayHi(){
// 返回视图名
return "hello";
}
如果需要请求重定向到其他页面,那么返回的字符串需要以“redirect:/”开头(只能够重定向到该项目下的其他资源)
@RequestMapping(value = "/index")
public String toIndex(){
// 返回视图名
return "redirect:/index";
}
想重定向到站外资源
return new ModelAndView(new RedirectView("http://www.baidu.com"));
如果model中包含数据,那么这些数据就会添加到重定向URL的后面;
返回结果类型也可以是集合类型、void或null。如果返回结果是集合、void、null,那么请求路径的名字作为视图名被解析。例如:资源路径为/test.do,则会跳转到/test.jsp;
十、日期类型处理
从页面提交表单时,表单上的日期数据与控制器中的Date参数并不一样,需要进行特殊处理;
10.1 @DateTimeFormat
使用@DateTimeFormat指定转换格式
@RequestMapping(value = "/getDate")
@ResponseBody
public String GetData(@DateTimeFormat(pattern = "yyyy-MM-dd") @RequestParam("date1") Date date){
System.out.println(date);
return "<h1>数据传递成功!</h1>";
}
10.2 控制器中初始化
在控制器中使用绑定初始化方法,每次进入控制器对日期数据进行格式化
//绑定初始化方法处理日期格式
@InitBinder
public void init(WebDataBinder binder){
System.out.println("执行Init方法...");
//设置日期格式
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
binder.registerCustomEditor(Date.class,new CustomDateEditor(sdf,true));
}
10.3 全局日期类型转换器
定义一个日期转换器类,该类实现Converter接口
//全局日期类型转换器
public class DateConverTer implements Converter<String,Date> {
@Override
public Date convert(String date) {
//设置日期格式
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
try{
return sdf.parse(date);
}catch (ParseException e){
e.printStackTrace();
}
return null;
}
}
在Spring的配置文件applicationContext.xml配置转换器
<!--配置转换器-->
<bean id="con" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="converters">
<list>
<bean class="com.tung.HelloWorld.converter.DateConverTer"/>
</list>
</property>
</bean>
注意:得在启动注解功能的标签中设置conversion-service为转换器的id(下图中的"con")
<!-- 启动注解功能 -->
<mvc:annotation-driven conversion-service="con"/>
十一、异常处理
在项目开发的过程中,我们难免会遇到不可避免或不可预知的异常需要处理。每个异常都要处理的话,系统代码耦合度太高,为了提供维护效率,我们需要统一进行异常处理。
下面介绍三种异常处理方式:
11.1 自带的异常处理器
在Spring的配置文件applicationContext.xml中配置异常处理器
<!-- 配置异常处理器 -->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<!--
配置默认错误处理页
value:视图的名称
-->
<property name="defaultErrorView" value="error"/>
<!-- 对指定异常类型进行处理 -->
<property name="exceptionMappings">
<props>
<!-- key代表异常类型,value代表视图名 -->
<prop key="java.lang.RuntimeException">error</prop>
</props>
</property>
</bean>
11.2 异常处理器
创建一个异常处理类,实现HandlerExceptionResolver接口
public class MyExceptionHandler implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
ModelAndView mv = new ModelAndView();
mv.setViewName("error");
//输出异常信息
e.printStackTrace();
return mv;
}
}
在配置文件中配置该类
<!-- 配置异常处理类-->
<bean class="com.tung.HelloWorld.errorHandler.MyExceptionHandler"/>
11.3 @ExceptionHandler
在控制器类中定义一个异常处理的方法,并且使用@ExceptionHandler注解标注该方法
@ExceptionHandler
public String handleException(HttpServletRequest request,Exception ex){
return "error";
}
方法中的两个参数:
request:当前发生异常的请求;
ex:异常对象