大黑 2019-06-27
上篇文章主要分析了Spring提供的Controller及抽象类AbstractController,本章继续分析其具体的几个实现类。
本系列文章是基于Spring5.0.5RELEASE。
ServletForwardingController实现的功能是将接收的用户请求转发给你一个命名的servlet去处理,该命名servlet需在部署描述(web.xml)文件中定义。
源码
由继承关系ServletForwardingController继承AbstractController抽象类,并实现模板方法handleRequestInternal,完成将接收的请求进行转发,源码如下:
/**
*实现父类模板方法
*/
@Override
protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response)
throws Exception {
ServletContext servletContext = getServletContext();
Assert.state(servletContext != null, "No ServletContext");
// 获取部署文件中定义的servlet,传入servelet name参数。
RequestDispatcher rd = servletContext.getNamedDispatcher(this.servletName);
if (rd == null) {
throw new ServletException("No servlet with name '" + this.servletName + "' defined in web.xml");
}
// 判断是否是include请求
if (useInclude(request, response)) {
// 是include请求,继续使用include
rd.include(request, response);
if (logger.isDebugEnabled()) {
logger.debug("Included servlet [" + this.servletName +
"] in ServletForwardingController '" + this.beanName + "'");
}
}
else {
// 非include请求,进行转发
rd.forward(request, response);
if (logger.isDebugEnabled()) {
logger.debug("Forwarded to servlet [" + this.servletName +
"] in ServletForwardingController '" + this.beanName + "'");
}
}
return null;
}实战
编写servlet,代码如下:
public class ForwardServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().write("hello ForwardServlet...");
}
}配置部署描述文件,代码如下:
<servlet>
<servlet-name>forwording</servlet-name>
<servlet-class>com.github.dalianghe.controller.ForwardServlet</servlet-class>
</servlet>配置Spring配置文件,代码如下:
<bean name="/forwardToServlet" class="org.springframework.web.servlet.mvc.ServletForwardingController">
<property name="servletName" value="forwording"/>
</bean>编写完以上代码,启动系统并请求,地址:http://localhost:8086/forwardToServlet,请求将通过ServletForwardingController转发到Servlet进行处理,最终在界面如图:

根据参数的逻辑视图名直接选择需要展示的视图,只支持GET、HEAD请求方法类型。
源码
核心处理方法源码如下:
/**
*处理请求
*/
@Override
protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response)
throws Exception {
//获取配置的viewName属性
String viewName = getViewName();
... ...
// 把视图逻辑名设置到ModelAndView中
if (getViewName() != null) {
modelAndView.setViewName(viewName);
}
else {
modelAndView.setView(getView());
}
return (isStatusOnly() ? null : modelAndView);
}实战
因为此部分使用jsp视图,故需引入jstl支持,在pom文件中添加依赖坐标,如下:
<dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency>
在Spring配置文件中,添加相关配置,如下:
<!-- jsp视图映射与视图解析 -->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<!-- 视图前缀 -->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!-- 视图后缀 -->
<property name="suffix" value=".jsp"/>
</bean>
<!-- 配置ParamterizableViewController -->
<bean name="/helloJSP" class="org.springframework.web.servlet.mvc.ParameterizableViewController">
<property name="viewName" value="test"/>
</bean>在WEB-INF下新建jsp文件夹及test.jsp文件,文件内容如下:
<html>
<head>
<title>My Frist JSP</title>
</head>
<body>
<h1>hello jsptest</h1>
</body>
</html>启动服务,进行测试,访问/helloJSP,结果如下:

测试结果表明,我们并未编写Controller,通过配置接口实现通过Spring转发到视图。
作用与ParameterizableViewController一样,但功能强大很多,支持模式匹配。
示例
以下提供两种示例,可做为参考,如下:
<!-- 可以匹配/test1/xxx,其中xxx为视图真实名称
最终的查找路径为:/WEB-INF/jsp/xxx.jsp
Spring 视图解析前缀+视图名称+视图解析后缀
-->
<bean name="/test1/*" class="org.springframework.web.servlet.mvc.UrlFilenameViewController"/>
<!-- 可以匹配/test1/xxx/yyy,xxx为目录,yyy为视图真实名称 -->
<bean name="/index2/**" class="org.springframework.web.servlet.mvc.UrlFilenameViewController"/>本类不做演示了,有兴趣的可以自行验证,有问题可以留言或加入qq群反馈。
本章主要分析并演示了Spring提供Controller接口的实现类,目前来说用的很多,有些我也不是很明白,有讲解错误的地方,还望指定,真心的希望能与大家一起进步。
最后创建了qq群方便大家交流,可扫描加入,同时也可加我qq:276420284,共同学习、共同进步,谢谢!
