1. 什么是SpringMVC?
- M-model 模型(dao、service)
- Dao层:连接数据库(实体)
- Service层:调用dao层,执行具体地业务
- V-view 视图(jsp)
- 负责模型展示,一般就是我们看到的用户界面
- C-controller 控制器(Servlet)
- 接收前端(jsp/html)数据,交给service层处理数据,处理完毕后把返回的数据返回给视图,由视图负责展示
2. SpringMVC的执行原理(重点)
2.1 原理图
- DispatcherServlet:表示前置控制器,是整个SpringMVC的控制中心。用户发出请求,DispatcherServlet接收请求并拦截请求。
分析:假设来了个请求:http://loclhost:8080/SpringMVC/hello
http://localhost:8080:服务器域名;
SpringMVC部署在服务器上的Web站点;
hello表示控制器
上述url表示:请求位于服务器localhost:8080上的SpringMVC站点的hello控制器。
- HandlerMapping:处理器映射。DispatcherServlet调用HandlerMapping,HandlerMapping根据请求url查找Handler(处理器)。
- HandlerExecution:表示具体的Handler,其主要作用是根据url查找控制器,如上url被查找控制器:hello。
- 将解析后的信息传递给DispatcherServlet。
根据url查找到对应的Controller控制器,hello。
- HandlerAdapter:表示处理器适配器,其按照特定的规则去执行Handler。
- Handler让具体的Controller执行,Controller将具体的信息返回给HandlerAdapter,如ModelAndView。
- HandlerAdapter将视图逻辑名和模型传递给DispatcherServlet。
- ViewResolver:DispatcherServlet调用视图解析器来解析HandlerAdapter传递的逻辑视图名。
- 视图解析器将解析的逻辑视图名传给DispatcherServlet
- DispatcherServlet根据视图解析器解析的视图结果,调用具体的视图
- 最终视图呈现给用户。
2.2 细节
主要分为三部分:
体现在springmvc-servlet.xml配置文件中,是以下三部分:
- 处理器映射
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
<bean id="/hello" class="com.kuang.controller.HelloController"/>
利用处理器映射器可以找到要执行的类
- 处理器适配
<!--处理器适配器-->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
执行方法 controller
- 视图展示
<!--视图解析
1. 获取了ModelAndView的数据
2. 解析ModelAndView的视图名字
3. 拼接视图名字,找到对应的视图 hello
4. 将数据渲染到视图上
-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
展示"/WEB-INF/jsp/hello.jsp"页面。
3. 注解开发
3.1 开发流程
- 修改web.xml配置文件
- 创建springmvc-servlet.xml配置文件
- 创建测试类(执行)
- 创建测试页面(返回数据)
3.2 细节
- 修改web.xml配置文件
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--
DispatcherServlet必须绑定spring的配置文件
-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc-servlet.xml</param-value>
</init-param>
<!--启动级别-->
<load-on-startup>1</load-on-startup>
</servlet>
<!--
在springMVC中,
/ : 只匹配所有的请求,不会去匹配jsp页面
/* :匹配所有的请求,包括jsp页面
-->
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
- 创建springmvc-servelet.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
https://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">
<!--自动扫描包,让指定包下的注解生效,由IOC容器统一管理-->
<context:component-scan base-package="com.kuang.contraller"/>
<!--让springMVC不处理静态资源 .css .js .html , ....-->
<mvc:default-servlet-handler/>
<!--
支持mvc注解驱动
在spring中一般采用@RequestMapping注解来完成映射关系
要想使@RequestMapping注解生效
必须向上下文注册DefaultAnnotationHandlerMapping
和一个AnnotationMethodHandlerAdapter实例
这两个实例分别在类级别和方法级别处理
而annotation-driven配置帮助我们自动完成上述两个实例的注入
-->
<mvc:annotation-driven/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
简化了之前的加载映射器和适配器操作:<mvc:annotation-driven/>
- 创建测试类
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
//@RequestMapping("/springmvc-03-annotation")
public class HelloController {
@RequestMapping("/hello")
public String hello(Model model){
// 封装数据
model.addAttribute("msg","Hello SpringMVC Annotation!");
return "hello"; // 会被视图解析器处理
}
}
- 创建返回页
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
${msg}
</body>
</html>
4. 重定向与转发
4.1 介绍
转发是服务器行为,重定向是客户端行为。转发耗时比重定向少。
- 转发
转发——>客户浏览器发送HTTP请求——>web服务器接受请求——>调用内部一个方法在容器内部完成请求处理和转发动作——>再将转发跳转到的那个网页资源返回给客户; 转发只能在同一个容器内完成 转发的时候浏览器地址是不会变的,在客户浏览器里只会显示第一次进入的那个网址或者路径,客户看不到这个过程,只是得到了想要的目标资源。转发行为浏览器只做了一次请求。(转发只能跳转一次) - 重定向
重定向——>客户浏览器发送HTTP请求——>web服务器接受请求后发送302状态码以及新的位置给客户浏览器——>客户浏览器发现是302响应,则自动再发送一个新的HTTP请求,请求指向新的地址(302:Found 临时移动,但资源只是临时被移动。即你访问网址A,但是网址A因为服务器端的拦截器或者其他后端代码处理的原因,会被重定向到网址B。)——>服务器根据此请求寻找资源发个客户;再客户浏览器中显示的是重定向之后的路径,客户可以看到地址的变化。重定向行为浏览器做了至少两次请求。(重定向可以跳转多次) - 换句话说:
转发不会改变请求页的url,但是重定向会改变原本的url,跳转到指定的页面。
SpringMVC实现转发和重定向
- 转发
@RequestMapping("/t1")
public String test1(Model model){
model.addAttribute("msg","转发-way1");
return "/WEB-INF/jsp/test.jsp"; // 跳转 WEB-INF/jsp/test.jsp
}
@RequestMapping("/t2")
public String test2(Model model){
model.addAttribute("msg","转发-way2");
return "forward:/WEB-INF/jsp/test.jsp"; // 跳转 WEB-INF/jsp/test.jsp
}
- 重定向
@RequestMapping("/t3")
public String test3(Model model){
return "redirect:/index.jsp"; // 跳转 WEB-INF/jsp/test.jsp
}
5. 接收参数与数据回显
5.1 接收参数
- 接收单个数据
// 接收一个字段
@GetMapping("/t1")
public String test1(@RequestParam("username") String name, Model model){
System.out.println("接收到的前端数据:" + name);
model.addAttribute("msg",name);
return "test";
}
- 接收一个对象
// 接收一个对象
// 请求的参数与实体类参数一一对应
@GetMapping("/t2")
public String test2(User user, Model model){
System.out.println("接收到的前端数据:" + user);
model.addAttribute("msg",user);
return "test";
}
5.2 数据回显
三种方式。
- ModelAndView
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
// 模型和视图
ModelAndView mv = new ModelAndView();
// 封装对象 放在ModelAndView中
mv.addObject("msg","HelloSpringMVC!");
// 封装要跳转的视图 放在ModelAndView中
mv.setViewName("hello"); // /WEB-INF/jsp/hello.jsp
return mv;
}
- Model
@RequestMapping("/hello")
public String hello(Model model){
// 封装数据
model.addAttribute("msg","Hello SpringMVC Annotation!");
return "hello"; // 会被视图解析器处理
}
- ModelMap
- 继承了LinkedMap的全部特性,Model是其简化版。