SpringMVC
MVC:
- Model
- View
- Controller
概述
Spring Web MVC是建立在Servlet API上的原始Web框架,从一开始就包含在Spring框架中。正式名称 "Spring Web MVC" 来自其源模块的名称spring-webmvc,但它更常被称为 "Spring MVC"
SpringMVC主要执行请求的处理,底层实际上是Servlet
SpringMVC是约定大于配置的
对于Servlet,它的一个重要作用就是请求转发和重定向
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 请求为/test?method=参数具体值,根据不同的参数转发到不同的页面
String method =req.getParameter("method");
if(method.equals("add")){
req.getSession().setAttribute("msg","调用add");
}else if (method.equals("delete")){
req.getSession().setAttribute("msg","调用delete");
}
req.getRequestDispatcher("add.jsp").forward(req,resp);
}
}
每一个请求都对应一个Servlet,而Servlet又将面向用户,这样就会造成用户面向数量不菲的Servlet
所以ServletMVC提供了DispatcherServlet,作为请求的调度器,将不同的请求交付给对应的处理器(Controller)
使用SpringMVC所需要的依赖:
<!--spring-web-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
<!--spring-webmvc-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
<!--spring-jdbc-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
<!--spring注解-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
DispatcherServlet
DispatcherServlet是SpringMVC的一个中央Servlet,它的作用是将请求分发到不同的处理器
它是已经被实现的类,直接使用即可
<!--注册DispatcherServlet-->
<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-servlet.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
url-pattern为/,代表所有请求都会走一遍DispatcherServlet
/ 代表所有不为/xxx.jsp的请求,/*包括.jsp请求
DispatcherServlet就相当于Controller,他要配合一下几个对象来去处理Model和View:
- HandlerMapping:处理器映射器
- HandlerAdapter:处理器适配器
- ViewResolver:视图解析器
SpringMVC的执行流程
1.查找请求
当用户执行一次请求后,DispatcherServlet就会接收到该请求,DispatcherServlet首先调用HandlerMapping,来找到该请求的Handler(处理器)
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
<!--id即为请求名-->
<bean id="/hello" class="HelloController"/>
BeanNameUrlHandlerMapping是已经被实现的用于查找请求对应Handler的类,直接使用即可
BeanNameUrlHandlerMapping查找的范围是bean,bean的id为请求名,class是对应的Handler,找到对应的Handler后,将Handler返回给DispatcherServlet
2.执行请求
DispatcherServlet接收到请求对应的Handler,将Handler交给HandlerAdapter,用适配器执行Handler
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
SimpleControllerHandlerAdapter为处理器适配器,用于调用执行Handler
此外,Handler实际上是一个实现了Controller接口的类
public class HelloController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
ModelAndView mv = new ModelAndView();
//可以向ModelAndView对象里添加参数,类似于setAttribute
mv.addObject("msg", "Hello World");
//设置请求要访问的view的名字
mv.setViewName("hello");
return mv;
}
}
调用DispatcherServlet传入的Handler,将其返回的ModelAndView对象再返回给DispatcherServlet
3.执行转发
DispatcherServlet接收到ModelAndView对象,使用ViewResolver来解析该对象
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--前缀-->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!--后缀-->
<property name="suffix" value=".jsp"/>
</bean>
InternalResourceViewResolver解析ModelAndView对象,在Handler里通过setViewName已经设置了即将访问的页面名,在这里来设置它的具体路径
在InternalResourceViewResolver对象的bean里有前缀和后缀两个属性,这两个属性将会附加在setViewName所设置的值上。例如上面我们设置的为hello,最终得到的就是 /WEB-INF/jsp/hello.jsp ,也就是将要访问的View的路径
这个路径就相当于一个具体的View,将其返回给DispatcherServlet
最终DispatcherServlet将具体的View进行渲染,然后响应给用户
整个流程我们的业务代码只有两部分:编写Handler和注册Handler的bean,大部分步骤都是DispatcherServlet自动执行的
注解实现
使用注解配置将进一步简化上面的步骤
首先在web.xml配置DispatcherServlet,步骤同上
然后配置springmvc-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:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c" xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://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"/>
<!--使SpringMVC不处理静态资源,避免请求HTML,css资源时被处理-->
<mvc:default-servlet-handler/>
<!--支持mvc注解驱动,该驱动配置了HandlerMapping和HandlerAdapter对象,不用再去配置他们的bean
注解采用@ResquestMapping来完成映射关系
在此之前,需要在上下文注册DefaultAnnotationHandlerMapping和一个AnnotationMethodHandlerAdapter实例
这两个实例分别在类级别和方法级别处理
annotation-driven标签会帮助我们自动完成这两个实例的配置
-->
<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>
然后使用注解来配置HelloController,主要使用以下注解:
- @Controller:标识为Controller,和实现Controller接口作用相同
- @RequestMapping:请求映射
//@Controller:标识为Controller,和实现Controller接口作用相同
@Controller
//请求映射
//@RequestMapping("/hello")
public class HelloController {
//@RequestMapping如果同时写在了类和方法上,代表需要经过类上的请求再进行方法上的请求才能到这里
//以此为例,如果类上有@RequestMapping,请求为/hello/h1,会执行此处的Controller
//一般写方法上的即可,如果有一组类型相似的请求,可以这样做
@RequestMapping("/h1")
public String sayHello(Model model) {
//向Model对象里附加数据
model.addAttribute("message", "Hello World");
//return的值被ViewResolver解析
return "hello";
}
}
RESTful风格
RESTful是一种资源定位和资源操作的格式,不是一种标准或协议
传统方式操作资源,是通过不同的参数来请求,方法也一般只使用Get和Post
例如我要进行增删改查四个操作:
- 增:localhost/item/add.action?id=1,GET
- 删:localhost/item/delete.action,POST
- 改:localhost/item/update.action,POST
- 查:localhost/item/query.action?id=1,GET
RESTful操作资源是通过不同的请求方式来确定的,使得同样的请求地址可以由不同的功能
- 增:localhost/item/1,POST
- 删:localhost/item,DELETE
- 改:localhost/item,PUT
- 查:localhost/item/1,GET
比如这个Controller:
@Controller
public class RESTController {
@RequestMapping("/add")
public String test(int a, int b, Model model){
int res=a+b;
model.addAttribute("msg","result="+res);
return "test";
}
}
我要走add请求,就必须要附带着a,b的值,否则就会报错
http 😕/localhost:8080/add?a=1&b=2
可以使用@PathVariable注解,该注解支持从url中获取参数@Controller
public class RESTController {
//通过@PathVariable注解获取到的参数可以用于请求映射上
@RequestMapping("/add/{a1}/{b}")
//可以为参数设置别名,默认为变量名
public String test(@PathVariable("a1") int a,@PathVariable int b, Model model){
int res=a+b;
model.addAttribute("msg","result="+res);
return "test";
}
}对于RequestMapping,可以设置其Method
SpringMVC提供了枚举类RequestMethod,包含了若干方法
public enum RequestMethod {
GET,
HEAD,
POST,
PUT,
PATCH,
DELETE,
OPTIONS,
TRACE;
private RequestMethod() {
}
}
@Controller
public class RESTController {
//name为请求路径,method为方法,默认为GET
@RequestMapping(value="/add/{a1}/{b}",method = RequestMethod.DELETE)
public String test(@PathVariable("a1") int a,@PathVariable int b, Model model){
int res=a+b;
model.addAttribute("msg","result="+res);
return "test";
}
}
也可以将@RequestMapping注解替换为@GetMapping注解,代表使用Get方法
同样的,也有@PostMapping,@DeleteMapping等注解
@Controller
public class RESTController {
@GetMapping("/add/{a}/{b}")
public String test(@PathVariable int a,@PathVariable int b, Model model){
int res=a+b;
model.addAttribute("msg","GETresult="+res);
return "test";
}
//同样的路径,通过不同的方法返回不同的结果
@PostMapping("/add/{a}/{b}")
public String test2(@PathVariable int a,@PathVariable int b, Model model){
int res=a+b;
model.addAttribute("msg","POSTresult="+res);
return "test";
}
}
转发和重定向
没用,了解即可
SpringMVC除了通过视图解析器来进行转发,还可以通过一些字段来实现转发或重定向
@Controller
public class ModelTest {
@RequestMapping("/m1")
public String test(){
return "forward:WEB-INF/jsp/test.jsp";
//return "redirect:/test2.jsp";
}
}
在没有视图解析器的前提下,进行转发需要写全路径
使用forward:来代表转发,redirect:代表重定向
请求参数接收
上面的@PathVariable注解可以获取请求中参数并应用到路径中
@RequestParam可以从请求中提取查询参数、表单参数甚至是多个参数
如果方法中的参数是一个对象,SpringMVC会自动匹配请求中参数的名字和对象的属性名,如果匹配就会给该对象赋值
<form action="${pageContext.request.contextPath}/t1" method="get">
id:<input type="text" name="id">
name:<input type="text" name="name">
age:<input type="text" name="age">
<input type="submit">
</form>
---------------------------------------------------
@GetMapping("/t1")
public String test(@RequestParam String name, Model model){
model.addAttribute("msg", name);
return "test";
}
@GetMapping("/test2")
public String test2(User user){
System.out.println(user);
return "test";
}
过滤器
SpringMVC提供了过滤器类CharacterEncodingFilter,直接使用即可
<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>
JackSon
JackSon是一种JSON解析工具,将java对象转化成JSON字符串
<!--JackSon-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.18.1</version>
</dependency>

浙公网安备 33010602011771号