大黑 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,共同学习、共同进步,谢谢!