Spring MVC体系结构和处理请求控制器
1.请求处理流程及体系结构
Spring MVC请求处理流程
- 首先用户发送请求到前端控制器(DispatcherServlet),前端控制器根据用户传入的请求信息决定用哪个页面控制器/处理器(Controller)来处理,并把请求委托给处理器。
- 页面控制器/处理器(Controller)接收到请求后,调用业务对象,进行业务处理,处理完毕后返回一个ModelAndView(模型数据和逻辑视图名)。
- 前端控制器收回控制权,然后根据返回的逻辑视图名找到真正的视图,并把模型数据传入以便展示视图渲染。
- 前端控制器再次收回控制权,将响应结果返回给用户。
Spring MVC框架的体系结构
- 客户端发出HTTP请求,Web应用服务器接收请求。若匹配DispatcherServlet的请求映射路径(在web.xml中指定),则Web容器将该请求转交给DispatcherServlet处理。
- DispatcherServlet接收请求后,将根据请求的信息(包括URL、请求参数、HTTP方法等)及HandlerMapping的配置(在-servlet.xml中配置)找到处理请求的处理器(Handler)。
- 当DispatcherServlet根据HandlerMapping找到对应当前请求的Handler后,通过HandlerAdapter对Handler进行封装,再以统一的适配器接口调用Handler。HandlerAdapter可以理解为具体使用Handler来干活的人。
- 在请求信息到达真正调用Handler的处理方法之前的这段时间里,Spring MVC会将请求信息以一定的方式转换并绑定到请求方法的入参中,对于入参对象会进行数据转换、数据格式化以及数据校验等操作。在这些之后,真正地调用Handler的处理方法进行相应的业务逻辑处理。
- 处理器完成业务逻辑处理之后将返回一个ModelAndView对象给DispatcherServlet,ModelAndView对象包含了逻辑视图名和模型数据信息。
- ModelAndView对象中包含的是“逻辑视图名”而非真正的视图对象。DispatcherServlet会通过ViewResolver将逻辑视图名解析为真真的视图对象View。当然,负责数据展示的视图可以是JSP、XML、PDF、JSON等多种数据格式,对此Spring MVC均可灵活配置。
- 当得到真实的视图对象View后,DispatcherServlet会使用ModelAndView对象中的模型数据对View进行视图渲染。
- 最终客户端获得响应消息,可以是普通的HTML页面,也可以是一个XML或者JSON格式的数据等。
2.使用Spring MVC进行环境搭建
使用Spring MVC框架的步骤如下:
1.下载jar文件
spring-web-3.2.13.RELEASE.jar
spring-webmvc-3.2.13
2.配置文件
在web.xml中配置Servlet
创建Spring MVC的配置文件
3.创建Controller-处理请求的控制器
BeanNameURLHandlerMapping
4.创建View-jsp
5.部署运行
在导入相关jar包后,在web.xml中配置Servlet,具体代码如下:
<!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>
<!-- 核心控制器的配置 -->
<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>
<!-- 注此 springmvc-servlet.xml 要与 创建的springmvc的配置文件名一样-->
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
之后再创建Spring MVC的配置文件(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:mvc="http://www.springframework.org/schema/mvc"
xmlns:p="http://www.springframework.org/schema/p"
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/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">
<!--扫描注解@Controller @RequestMapping-->
<context:component-scan base-package="cn.kgc.controller"/>
<mvc:annotation-driven/>
<!-- 完成视图的对应 -->
<!-- 对转向页面的路径解析。prefix:前缀, suffix:后缀 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" >
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
<!--/WEB-INF/jsp/index.jsp-->
<!--/WEB-INF/jsp/userlist.jsp-->
</bean>
</beans>
在cn.kgc.controller包下创建IndexController
package cn.kgc.controller;
import cn.kgc.entity.User;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
/**
* User: LiKai
* Date: 2019/7/11
* Time: 18:15
*/
@Controller
@RequestMapping("/index")
public class IndexController {
private Logger log = Logger.getLogger(IndexController.class);
@RequestMapping({"/test","/"})
public ModelAndView index(HttpServletRequest request, HttpServletResponse response) {
log.info("test succeed");
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("index");
return modelAndView;
}
@RequestMapping(value = "/welcome", method = RequestMethod.GET)
public ModelAndView welcome(@RequestParam(value = "username",required = false) String username) {
log.info("test succeed!! POST username: " + username);
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("index");
return modelAndView;
}
@RequestMapping(value = "/test2")
public ModelAndView index2(@RequestParam String username) {
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("username",username);
modelAndView.setViewName("index");
log.info("hello spring mvc!!");
return modelAndView;
}
@RequestMapping(value = "/test3")
public String index3(String username, Model model) {
model.addAttribute("userName",username);
model.addAttribute(username);
User user = new User();
user.setUserName(username);
model.addAttribute(user);
model.addAttribute("current",user);
log.info("hello spring mvc!user test!");
return "index";
}
@RequestMapping(value = "/test4")
public String index4(String username, Map<String,Object> model) {
model.put("username", username);
return "index";
}
}
创建View
在第二部配置视图解析器时,根据定义prefix(前缀) —/WEB-INF/jsp/和suffix(后缀)—.jsp所以在WEB-INF下创建jsp文件夹,并在该文件夹下创建真正的JSP视图–index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page isELIgnored="false" %>
<%-- <%@ page isELIgnored="true|false"%>
如果设定为真,那么JSP中的表达式被
当成字符串处理。比如下面这个表达式<p>${2000 % 20}</p>
在isELIgnored="true"时输出为${2000 % 20},
而isELIgnored="false"时输出为100。--%>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>Hello Spring MVC</h1>
<h1>username----------->${userName}</h1>
<h1>username----------->${string}</h1>
<h1>username----------->${user.userName}</h1>
<h1>username current----------->${current.userName}</h1>
<h1>username map----------->${username}</h1>
</body>
</html>