文章目录
一、简介
SpringMVC是Spring提供的一个轻量级Web框架,它实现了Web MVC设计模式,且使用起来功能和性能更加优异。
SpringMVC有如下特点:
- 是Spring框架的一部分,可以方便地利用Spring所提供的其他功能;
- 灵活性强,易于与其它框架集成;
- 提供了一个前端控制器DispatcherServlet,使开发人员无需额外开发控制器对象;
- 可自动绑定用户输入,并能正确地转换数据类型;
- 内置了常见的校验器,可以校验用户输入。如果校验不能通过,就会复位到输入表单;
- 支持国际化,可以根据用户区域显示多国语言
- 支持多种识图技术
- 使用基于xml的配置文件,在编辑后,不需要重新编译应用程序。
二、简单的使用
1、导入常用jar包
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.13</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.3.13</version>
</dependency>
注:使用IDEA编译器,如果导包后不在这里进行设置,将会出现404错误,记住使用IDEA创建SpringMVC项目,必须每次都进行导包!!!!!
2、配置前端控制器
在web.xml中配置SpringMVC的前端控制器DispatcherServlet
<?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">
<!-- 注册DispatcherServlet : 是SpringMVC的核心,请求分发器,前端控制器-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--关联一个SpringMVC的配置文件,如果我们不设置init-param元素,
那么应用程序就会到WEB-INF目录下寻找servletname-servlet.xml的文件,
在这里就是springmvc-servlet.xml-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc-config.xml</param-value>
</init-param>
<!--设置启动级别为1,即服务器一启动,就运行这个Servlet-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<!-- '/'匹配所有的请求: 不包括*.jsp -->
<!-- '/*'匹配所有的请求:包括*.jsp-->
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
3、创建Controller类
//先导入controller接口
public class MyController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
//ModelAndView 模型和视图
ModelAndView mv = new ModelAndView();
//封装对象,放在ModelAndView中
mv.addObject("msg", "Hello World");//msg为前端jsp页面中接受ModelAndView对象的id
//封装要跳转的视图,放在ModelAndView中
mv.setViewName("/WEB-INF/jsp/hello.jsp"); // 跳转的页面路径/WEB-INF/jsp/hello.jsp
return mv;
}
}
4、创建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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--配置处理器Handle,name用于跳转页面-->
<bean name="/hello" class="controller.MyController"/>
<!--处理器映射器,将处理器Handle的name作为url进行查找-->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
<!--处理器适配器,配置对处理器中handleRequest()方法的调用-->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
<!--视图解析器,我们可以配置它的属性,减少我们后端代码中的编写-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"/>
</beans>
5、创建视图view页面
在WEB-INF目录下创建jsp子目录,在子目录下创建hello.jsp文件,我们使用EL表达式接受后端对象
<html>
<head>
<title>Title</title>
</head>
<body>
${msg}
</body>
</html>
6、配置tomcat服务器,并发布
我们来分析一下SpringMVC程序的执行流程:
1、用户通过浏览器向服务器发送请求,请求被SpringMVC的前端控制器DispatcherServlet拦截
2、DispatcherServlet拦截请求后,会调用HandlerMapping处理器映射器
3、处理器映射器根据请求URL找到具体的处理器,生成处理器对象及处理器拦截器(如果有就生成)一并返回给DispatcherServlet
4、DispatcherServlet会通过返回信息选择合适的HandleAdapter(处理器适配器)
5、HandlerAdapter会调用并执行Handler(处理器),这里的处理器就是程序中编写Controller类,也被称为后端控制器
6、Controller执行完成后,会返回一个ModelAndView对象,该对象中包含视图名或包含模型与视图名
7、HandlerAdapter将ModelAndView对象返回给DispatcherServlet
8、DispatcherServlet会根据ModelAndView对象选择一个合适的ViewResolver(视图解析器)
9、ViewResolver解析后,会向DispatcherServlet中返回一个具体的View(视图)
10、DispatcherServlet对View进行渲染(将模型视图填充至视图中)
11、视图渲染结果后会返回给客户端浏览器中显示
执行过程中,DispatcherServlet、HandlerMapping、HandlerAdapter和ViewResolver对象的工作是在框架内部执行,开发人员并不需要关心这些对象内部的实现过程,只需要配置前端控制器(DispatcherServlet),完成Controller中的业务处理,并在视图中(View)中展示响应信息即可。
三、使用注解
1、Controller注解类型
Controller注解类型用于指示Spring类的实例是一个控制器,其注解形式为@Controller,该注解在使用时不需要实现Controller接口,只需要将@Controller注解加入到控制器类上,然后通过Spring的扫描机制找到标注了该注解的控制器即可
示例用法:
@Controller
public class MyController {
......
}
为了保证Spring能够找到控制器类,还需要在SpringMVC的配置文件中添加响应的扫描配置信息
- 在配置文件的声明中引入spring-context
- 使用< context:component-scan>元素指定需要扫描的类包
<?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
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--自动扫描包,让指定包下的注解生效,由IOC容器统一管理-->
<context:component-scan base-package="controller"/>
<!--mvc的默认servlet处理器-->
<mvc:default-servlet-handler/>
<!--mvc的注解驱动-->
<mvc:annotation-driven/>
<!--视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
在<context:component-scan >元素的属性base-package指定了需要扫描的类包为controller。在运行时,该类包及其子包下的所有标注了注解的类都会被Spring所处理,与实现了Controller接口的方式相比,使用注解的方式显然更简单。
同时,Controller接口的实现类只能处理一个单一的请求动作,而基于注解的控制器可以同时处理多个请求动作,在使用上更灵活。因此,在开发中,通常都会使用基于注解的方式
需要导包
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.3.13</version>
</dependency>
2、RequestMapping注解类型
①、@RequestMapping注解的使用
Srping通过@Controller注解找到相应的控制器类后,还需要知道控制器内部对每一个请求是如何处理的,这就需要使用RequestMapping注解类型。RequestMapping用于映射一个请求或一个方法,其注解形式为@RequestMapping,可以使用该注解标注在一个方法或者一个类上
(1)、标注在方法上
当标注在方法上时,该方法将成为一个请求处理方法,它会在程序接收到相应的URL请求时被调用
示例:
@Controller
public class MyController {
//实际访问地址为:localhost:8080/controller
@RequestMapping(value = "controller")
public String hello(Model model) {
model.addAttribute("msg","Hello World");
return "controller";
}
}
(2)、标注在类上
当标注在一个类上时,该类中所有方法都将映射为相对于类级别的请求,表示该控制器所处理的所有请求都被映射到value属性值所指定的路径下
@Controller
@RequestMapping(value = "mycontroller")
public class MyController {
//实际访问地址:localhost:8080/mycontroller/controller
@RequestMapping(value = "controller")
public String hello(Model model) {
model.addAttribute("msg","Hello World");
return "controller";
}
}
②、@RequestMapping注解的属性
@RequestMapping注解除了可以指定value属性外,还可以指定一些其他属性
属性名 | 类型 | 描述 |
---|---|---|
name | String | 可选属性,用于为映射地址指定别名 |
value | String[] | 可选属性,同时也是默认属性,用于映射一个请求和一种方法,可以标注在一个方法或一个类上 |
method | RequestMethod[] | 可选属性,用于指定该方法用于处理那种类型的请求方式,其请求方式包括GET,POST,HEAD,OPTIONS,PUT,PATCH,DELETE和TRACE,例如,method=RequestMethod.GET表示只支持GET请求,如果需要支持多个请求方式,就需要通过“{}”写成数组的形式,并且多个请求直接是有英文逗号分隔的 |
params | String[] | 可选属性,用于指定Request中必须包含某些参数的值,才可以通过其标注的方法处理 |
headers | String[] | 可选属性,用于指定Request中必须包含某些指定的header的值,才可以通过其标注的方法处理 |
consumes | String[] | 可选属性,用于指定处理请求的提交内容类型(Content-Type),比如application/json,text/html等 |
produces | String[] | 可选属性,用于指定返回的内容类型,返回的内容类型必须是request请求头(Accept)中所包含的类型 |
在上表中,所有的属性都是可选的,但是默认属性是value,当value是唯一属性时,可以省略属性名,例如下面两种标注意义相同
@RequestMapping(value="controller")
@RequestMapping("controller")
③、组合注解
简化了Http方法的映射
- @GetMapping:匹配GET方式的请求
- @PostMapping:匹配POST方式的请求
- @PutMapping:匹配PUT方式的请求
- @DeleteMapping:匹配DELETE方式的请求
- @PatchMapping:匹配PATCH方式的请求
以GetMapping为例,下面两种注解意义相同
@RequestMapping(value="controller",method=RequestMethod.GET)
public String MyController(String id){
......
}
@GetMapping(value="controller")
public String MyController(String id){
......
}
④、请求处理方式的参数类型和返回类型
参数类型:
- HttpServletRequest
- HttpServletResponse
- HttpSession
- WebRequest
- NativeWebRequest
- Locale
- Zoneld
- Reader/InputStream
- Writer/OutputStream
- HttpMehod
- Principal
- @PathVariable、@MatrixVariable、@RequestParam、@RequestHeader、@RequestBody、@RequestPart、@SessionAttribute、@RequestAttribute注解
- HttpEntity<?>
- Model/ModelMap
- RedirectAttributes
- BindingResult
- SessionStatus
- UrlComponentsBuilder
返回类型
- ModelAndView
- Model
- Map
- View
- String
- void
- HttpEntity<?>或ResponseEntity<?>
- Callable<?>
- DeferredResult<?>
在上述列举的返回类型中,常见的返回类型为ModelAndView、String、void。
其中,ModelAndView类型中可以添加Model数据,并指定视图;
String类型的返回值可以跳转视图,但不能携带数据;
而void类型主要在异步请求时使用,它只返回数据,不跳转视图。
由于ModelAndView类型未能实现数据与视图直接的解耦,因此在开发是,方法的返回类型通常都会用String,既然String类型的返回值不能携带数据,那么在方法中如何将数据代入到视图页面呢?这就用到了上面所讲解的Model参数类型,通过该参数类型即可添加需要在视图中显示的属性。
返回String类型方法的示例代码如下:
@RequestMapping(value = "test")
public String hello(HttpServletRequest req,HttpServletResponse res,Model model) throws Exception {
model.addAttribute("msg","Hello World");
return "test";//需要在视图解析器中设置才可以这样写,返回的WEB-INF/jsp/test.jsp页面
}
上述的代码中添加了Model类型的参数,通过该参数实例的addAttribute()方法即可添加所需数据,String类型出了可以返回上述代码的视图页面外,还可以进行复位向和请求转发
(1)、redirect复位向
例如:
@RequestMapping(value = "test")
public String hello(HttpServletRequest req,HttpServletResponse res,Model model) throws Exception {
model.addAttribute("msg","Hello World");
return "redirect:test";//需要在视图解析器中设置才可以这样写,返回的WEB-INF/jsp/test.jsp页面
}
(2)、forward请求转发
例如:
@RequestMapping(value = "test")
public String hello(HttpServletRequest req,HttpServletResponse res,Model model) throws Exception {
model.addAttribute("msg","Hello World");
return "forward:test";//需要在视图解析器中设置才可以这样写,返回的WEB-INF/jsp/test.jsp页面
}
3、ViewResolver(视图解析器)
SpringMVC中的试图解析器负责解析视图,可以在springmvc-config.xml配置文件中定义一个ViewResolver来配置视图解析器
<!--视图解析器,id可写可不写-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
<!--设置前缀-->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!--设置后缀-->
<property name="suffix" value=".jsp"/>
</bean>
配置好以后,我们在后端代码中,可以直接返回jsp中的页面,不需要再写/WEB-INF/jsp/*.jsp,只需要写 * 即可