在SpringMVC项目环境中,经常需要配置一些信息,包括:前端控制器(DispatcherServlet)、处理器映射器(HandlerMapping)、处理器适配器(HandlerAdapter)、视图解析器(ViewResolver)、处理器(Handler)和视图(View)。下面将介绍在SpringMVC项目中常用的配置信息。
1、前端控制器(DispatcherServlet)
前端控制器(DispatcherServlet)其作用是接收用户请求,然后给用户反馈结果。它的作用相当于一个转发器或中央处理器,控制整个流程的执行,对各个组件进行统一调度,以降低组件之间的耦合性,有利于组件之间的扩展。
由于使用了SpringMVC,请求就要交由SpringMVC来管理。在一般的JSP/Servlet开发模式中,请求会被映射到web.xml中,然后匹配到对应的Servlet配置上,进而调用相应的Servlet类处理请求并反馈结果。那么当使用SpringMVC框架来开发时,就需要将所有符合条件的请求拦截到SpringMVC的专有Servlet上,让SpringMVC框架进行下一步的处理。
在项目的web.xml配置文件中,添加SpringMVC的前端控制器(DispatcherServlet),用于拦截符合配置的url请求。具体配置如下:
<?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">
<!-- SpringMVC前端控制器 -->
<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:spring-mvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>
</web-app>
2、处理器映射器(HandlerMapping)和处理器适配器(HandlerAdapter)
处理器映射器(HandlerMapping)其作用是根据请求的URL路径,通过注解或者XML配置,寻找匹配的处理器(Handler)信息。处理器适配器(HandlerAdapter)其作用是根据映射器找到的处理器(Handler)信息,按照特定规则执行相关的处理器(Handler)。对于用户的请求,处理器映射器和处理器适配器为前端控制器(DispatcherServlet)与处理器(Handler)的交互搭建了重要的桥梁。
处理器映射器和处理器适配器有两种配置方式:一种是基于XML的资源配置,也即非注解的配置方式;另外一种是基于Annotation注解的配置。在实际开发中,为了提高开发效率,使用最多的就是基于annotation-driven标签的配置,如下所示:
<!-- 开启SpringMVC注解模式(设置注解映射器、注解适配器) -->
<mvc:annotation-driven></mvc:annotation-driven>
<!-- 使用扫描配置,对某一个包下的所有类进行扫描,找出所有使用@Controller注解的Handler控制器类 -->
<context:component-scan base-package="com.pjb.mvc.controller"></context:component-scan>
2.1 <mvc:annotation-driven>自动注册标签
<mvc:annotation-driven></mvc:annotation-driven>
使用<mvc:annotation-driven>标签来配置。<mvc:annotation-driven>标签是一种简写模式,使用默认配置替代了一般的手动配置。<mvc:annotation-driven>标签会自动注册处理器映射器和处理器适配器,Spring3.1之前默认自动注册的处理器映射器和处理器适配器分别为:DefaultAnnotaionHandlerMapping、AnnotaionMethodHandlerAdapter,它们位于SpringMVC的核心jar包的org.springframework.web.servlet.mvc.annotation包下。在Spring3.1之后,DefaultAnnotaionHandlerMapping、AnnotaionMethodHandlerAdapter已经被列为过期的映射器和适配器。SpringMVC添加了新的基于注解的处理器映射器和处理器适配器,分别为RequestMappingHandlerMapping和RequestMappingHandlerAdapter,它们同样位于SpringMVC的核心jar包的org.springframework.web.servlet.mvc.annotation包下。
2.2 <context:component-scan>扫描标签
为了让注解的处理器映射器和处理器适配器找到注解的Handler,有两种配置方式。
第一种方式:在SpringMVC的核心配置文件(spirng-mvc.xml)中,声明相关bean信息。
<bean class="com.pjb.mvc.controller.UserController"></bean>
第二种方式:使用扫描配置,对某一个包下的所有类进行扫描,找出所有使用@Controller注解的Handler控制器类。
<context:component-scan base-package="com.pjb.mvc.controller"></context:component-scan>
3、视图解析器(ViewResolver)
视图解析器(ViewResolver)的作用就是,把一个逻辑上的视图名称解析为一个真正的视图。当处理器适配器(HandlerAdapter)处理了相关的Handler的具体方法之后,Handler会返回一个视图对象 ModelAndView,该视图对象中包含了需要跳转的视图信息(VIew)和需要在视图上显示的数据(Model),此时前端控制器(DispatcherServlet)会请求视图解析器(ViewResolver)来帮助其解析视图对象 ModelAndView,并返回相关的绑定有相关数据(Model)的视图(View)。
常用的视图解析器有:XmlViewResolver(从XML配置文件解析视图)、ResourceBundleViewResolver(从properties资源集解析视图)、InternalResourceViewResolver(根据模板名称和位置解析视图),这里使用默认的InternalResourceViewResolver。
3.1 InternalResourceViewResolver视图解析器
InternalResourceViewResolver名为“内部资源视图解析器”,是在日常开发中最常用的视图解析器。配置如下:
<!-- 视图解析器 -->
<bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages"/>
<property name="suffix" value=".jsp"/>
</bean>
当 ModelAndView 对象返回具体的View名称时,它会将前缀 prefix 与后缀 suffix 与具体视图名称拼接,得到一个视图资源文件的具体加载连接,从而加载真正的视图文件并反馈给用户。
上面的配置实现了,当一个被请求的 Controller 处理器方法返回一个名为“login”的视图时,InternalResourceViewResolver视图解析器会将“login”解析成一个 InternalResourceView 的对象,然后将返回的 model 模型属性信息存放到对应的 HttpServletRequest 属性中,最后利用 RequestDispatcher 在服务器端把请求 forward 到 “/WEB-INF/pages/login.jsp” 上。
最后完整的SpringMVC核心配置文件(spring-mvc.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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<!-- 开启SpringMVC注解模式(设置注解映射器、注解适配器) -->
<mvc:annotation-driven></mvc:annotation-driven>
<!-- 使用扫描配置,对某一个包下的所有类进行扫描,找出所有使用@Controller注解的Handler控制器类 -->
<context:component-scan base-package="com.pjb.mvc.controller"></context:component-scan>
<!-- 视图解析器 -->
<bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
4、处理器(Handler)
处理器(Handler)其作用是执行相关的请求处理逻辑,并返回相应的数据和视图信息,将其封装至 ModelAndView 对象中。
由于上面的配置中,使用了基于注解的处理器映射器和处理器适配器,所以不需要在XML文件中配置任何信息,也不需要实现任何接口,只需要在作为Handler处理器的Java类中添加相应的@Controller注解即可。
【示例】创建用户控制器,模拟实现用户信息的增删改查操作,代码如下:
package com.pjb.mvc.controller;
import com.pjb.mvc.model.UserModel;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
/**
* 用户控制器
* 使用@Controller注解来标识它是一个控制器
* @author pan_junbiao
**/
@Controller
@RequestMapping("/user")
public class UserController
{
/**
* 获取用户
*/
@RequestMapping("/getUser")
public ModelAndView getUser()
{
//获取用户信息(模拟Service层的业务)
UserModel userModel = new UserModel();
userModel.setUserId(1);
userModel.setUserName("pan_junbiao的博客");
userModel.setBlogUrl("https://blog.csdn.net/pan_junbiao");
userModel.setRemark("您好,欢迎访问 pan_junbiao的博客");
//创建返回结果ModelAndView对象
ModelAndView modelAndView = new ModelAndView();
//相当于request的setAttribut方法
modelAndView.addObject("userInfo",userModel);
//指定视图
modelAndView.setViewName("/userInfo");
return modelAndView;
}
/**
* 新增用户
*/
@RequestMapping("/addUser")
public ModelAndView addUser()
{
String message = "新增用户";
//创建返回结果ModelAndView对象
ModelAndView modelAndView = new ModelAndView();
//相当于request的setAttribut方法
modelAndView.addObject("message",message);
//指定视图
modelAndView.setViewName("/addUser");
return modelAndView;
}
/**
* 修改用户
*/
@RequestMapping("/updateUser")
public ModelAndView updateUser()
{
String message = "修改用户";
//创建返回结果ModelAndView对象
ModelAndView modelAndView = new ModelAndView();
//相当于request的setAttribut方法
modelAndView.addObject("message",message);
//指定视图
modelAndView.setViewName("/updateUser");
return modelAndView;
}
/**
* 删除用户
*/
@RequestMapping("/deleteUser")
public ModelAndView deleteUser()
{
String message = "删除用户";
//创建返回结果ModelAndView对象
ModelAndView modelAndView = new ModelAndView();
//相当于request的setAttribut方法
modelAndView.addObject("message",message);
//指定视图
modelAndView.setViewName("/deleteUser");
return modelAndView;
}
}
Model模型类如下:
package com.pjb.mvc.model;
/**
* 用户信息模型类
* @author pan_junbiao
**/
public class UserModel
{
private int userId; //用户编号
private String userName; //用户姓名
private String blogUrl; //博客地址
private String remark; //备注
//省略getter与setter方法...
}
5、视图(View)
【示例】创建上述用户控制器类中相应的视图信息。
(1)创建首页(index.jsp)。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>首页</title>
<meta name="author" content="pan_junbiao的博客">
</head>
<body>
<a href="user/getUser.action">获取用户</a><br>
<a href="user/addUser.action">新增用户</a><br>
<a href="user/updateUser.action">修改用户</a><br>
<a href="user/deleteUser.action">删除用户</a><br>
</body>
</html>
(2)创建名称为userInfo.jsp的JSP页面,用于显示用户信息。具体代码如下:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>用户信息</title>
<meta name="author" content="pan_junbiao的博客">
<style>
table { border-collapse: collapse;}
table,table tr th, table tr td { border:1px solid #000000; padding: 5px 10px;}
</style>
</head>
<body>
<table align="center">
<caption>用户信息</caption>
<tr>
<th>用户编号</th>
<td>${userInfo.userId}</td>
</tr>
<tr>
<th>用户姓名</th>
<td>${userInfo.userName}</td>
</tr>
<tr>
<th>博客地址</th>
<td>${userInfo.blogUrl}</td>
</tr>
<tr>
<th>备注信息</th>
<td>${userInfo.remark}</td>
</tr>
</table>
</body>
</html>
执行结果: