一、概述
SpringMVC是基于Spring提供的一个开源框架,用于替代复杂的Struts,利用SpringMVC,控制器的开发和测试都会比较简单。SpringMVC主要由几个部分组成:DispatcherServlet、处理器(控制器)映射、处理器(控制器)、视图解析器和视图。核心是处理器映射和视图解析器:通过处理器映射,找到合适的Controller来处理请求;通过视图解析器,对返回的结果按要求进行渲染展示。
二、SpringMVC运行原理
一个很经典的图:
上图是SpringMVC的运行流程:
(1)用户发送请求,请求URL被dispatcherServlet拦截
(2)dispatcherServlet根据处理器映射HandlerMapping找到合适的控制器
(3)dispatcherServlet将请求发给这个合适的控制器Controller
(4)Controller调用业务的相关处理方法,得到ModelAndView
(5)Controller调用Service得到的ModelAndView再返回给DispatcherServlet
(6)DispatcherServlet再根据配置找到合适的视图解析器ViewResolver
(7)将视图解析器与返回的ModelAndView结合,得到需要展示的视图View
(8)视图View显示在用户浏览器上,完成HTTP的响应过程。
在这个运行过程中,能发现DispatcherServlet是个很重要的东西,几个核心部分的调用都要靠它来完成。而在宏观意义上,它也就是这个web应用的总Controller,该给Model的给Model,该给视图View的给View。而它所负责的工作,总结一下就是这几项:1、拦截用户URL请求;2、初始化DispatcherServlet上下文对应的webApplicationContext,并将其与业务层、持久层的webApplicationContext相关联,也就是DispatcherServlet对应的webApplicationContext与业务层和持久层的webApplicationContext也有关联,靠这个关联,DispatcherServlet才能选择合适的控制器和视图解析器;3、初始化SpringMVC的各个组建,并装配到DispatcherServlet中。
其他几个接口的作用,通过对运行过程的理解就能判断出来。HandlerMapping负责客户请求到Controller的映射;Controller处理用户请求,并通过Service接口完成具体业务流程,返回ModelAndView ;ViewResolver对View进行渲染,返回给浏览器。
三、案例
工具:IDEA2016
工程结构:
在idea新建web项目,注意,这里lib为我们自己新建,里面是项目所依赖的jar包,主要是spring相关包(可以去GitHub上下载源码,然后把里面的lib文件复制出来)。
然后需要将lib里的包添加到项目中,添加过程为:
:
然后配置那个最重要的宏观控制器,也被称为是前端控制器,在web.xml中进行配置,代码如下:
<?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_3_1.xsd"
version="3.1">
<!--配置SpringMVC前端控制器-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--contextConfigLocation配置SpringMVC加载的配置文件
如果不配置contextConfigLocation,默认加载的是/WEB-INF/servlet名称-servlet.xml文件,
这里的话就会是springmvc-servlet.xml文件-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:config/springmvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<!--url-pattern有多种配置方式:
1、*.action,表示访问以action结尾由DispatcherServlet进行解析
2、/,表示所有访问地址都由DispatcherServlet进行解析
3、/*,这种配置不建议采用,使用这种配置,最终要转发到一个jsp页面时,仍然会由DispatcherServlet
进行解析,但是并不能根据这个jsp找到对应的handler(controller),所以会报错-->
<url-pattern>*.action</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
然后是配置springmvc.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
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-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">
<!--配置Controller-->
<bean name="/queryUsers.action" class="com.zxh.controller.myController"/>
<!--处理器映射器,将bean的name作为URL进行查找,需要在配置controller时指定beanname-->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
<!--处理器适配器,所有处理器适配器都实现handleradapter接口-->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
<!--配置视图解析器,解析jsp-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"/>
</beans>
好了,配置文件就是这些,接下来是一些类的编写
编写实体类User:
package com.zxh.bean;
/**
* Created by xhzhang on 2018/10/16.
*/
public class User {
private String name;
private int id;
private int age;
private String address;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
然后是controller类:
package com.zxh.controller;
import com.zxh.bean.User;
import org.springframework.lang.Nullable;
import org.springframework.web.servlet.mvc.Controller;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
/**
* Created by xhzhang on 2018/10/16.
*/
public class myController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse){
List<User>userList=new ArrayList<User>();
User user1=new User();
user1.setAddress("hahha");
user1.setAge(1);
user1.setId(1);
user1.setName("zss");
User user2=new User();
user2.setAddress("wwww");
user2.setAge(2);
user2.setId(2);
user2.setName("wjjj");
userList.add(user1);
userList.add(user2);
ModelAndView modelAndView=new ModelAndView();
modelAndView.addObject("userList",userList);
modelAndView.setViewName("/WEB-INF/jsp/userList.jsp");
return modelAndView;
}
}
可以看到controller返回一个ModelAndView类型,这个返回值也会被送给DispatcherServlet,由它根据配置文件中决定选用一个合适的视图解析器。
View通过一个jsp页面展现,这个jsp文件的路劲就是
代码如下:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%--
Created by IntelliJ IDEA.
User: xhzhang
Date: 2018/10/16
Time: 16:43
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>
<form action="${pageContext.request.contextPath }/queryUsers.action" method="post">
用户列表:
<table width="100%" border=1>
<tr>
<td>用户id</td>
<td>用户名称</td>
<td>用户年龄</td>
<td>用户住址</td>
</tr>
<c:forEach items="${userList }" var="user">
<tr>
<td>${user.id }</td>
<td>${user.name }</td>
<td>${user.age}</td>
<td>${user.address }</td>
</tr>
</c:forEach>
</table>
</form>
</body>
</html>
此处需要注意,因为用到了jstl标签,所以要引入库
配置Tomcat,启动服务,能看到欢迎页面,这个欢迎页面默认的是index.jsp。
访问URL:http://localhost:8080/queryUsers.action