回顾原生的Web应用
SpringMvc
-
ContextLoaderListener做了什么
-
DispatcherServlet创建一个子容器
-
mvc配置文件中需要声明的bean
-
HandlerMapping
-
HandlerAdapter
-
ViewResolver
回顾原生的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> <!-- 全局的配置参数,listener filter servlet 都可以获取参数 可以定义多个 --> <context-param> <param-name>Encoding</param-name> <param-value>UTF-8</param-value> </context-param> <!-- 过滤器 可以定义多个--> <filter> <filter-name>filter1</filter-name> <filter-class>filter.MyFilter</filter-class> </filter> <filter-mapping> <filter-name>filter1</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 监听器可以定义多个 --> <listener> <listener-class>listener.MyListener</listener-class> </listener> <!-- servlet可以定义多个 --> <servlet> <servlet-name>success</servlet-name> <servlet-class>servlet.UserServlet</servlet-class> <init-param> <param-name>key1</param-name> <param-value>value1</param-value> </init-param> <!-- 初始化加载顺序,会调用servlet的init方法 --> <load-on-startup>2</load-on-startup> </servlet> <servlet> <servlet-name>success2</servlet-name> <servlet-class>servlet.UserServlet2</servlet-class> <init-param> <param-name>key1</param-name> <param-value>value1</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <!-- servlet映射,跟每一个Servlet对应 --> <servlet-mapping> <servlet-name>success</servlet-name> <url-pattern>/success</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>success2</servlet-name> <url-pattern>/success2</url-pattern> </servlet-mapping> </web-app>
全局参数
web容器启动后,会创建一个ServletContext上下文对象,在web.xml中配置<context-param>会被上下文对象存储,任何可以获取ServletContext上下文的地方都可以调用getInitParameter("key");获取初始化参数,属于全局范围。
listener

package listener; import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; public class MyListener implements ServletContextListener { @Override public void contextInitialized(ServletContextEvent servletContextEvent) { System.out.println("glistener1 init"); ServletContext servletContext = servletContextEvent.getServletContext(); String value = servletContext.getInitParameter("Encoding"); System.out.println("当前设置编码" + value); } @Override public void contextDestroyed(ServletContextEvent servletContextEvent) { System.out.println("listener1 dest"); } }
listener监听器分为三类,分别监听ServletContext域,HttpSession域,ServletRequest域。每一类又分成监听域对象的创建、销毁和域对象内的属性的变化。在web.xml中可以定义多个监听器。同类型的监听器按照加载顺序执行。
以上代码片段创建了一个servletContextListener用来监听Servlet上下文的创建和销毁。
filter

package filter;/* * @auther 顶风少年 * @mail dfsn19970313@foxmail.com * @date 2020-02-06 17:35 * @notify * @version 1.0 */ import javax.servlet.*; import java.io.IOException; public class MyFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { System.out.println("filter1 init"); } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { ServletContext servletContext = servletRequest.getServletContext(); String encoding = servletContext.getInitParameter("Encoding"); servletRequest.setCharacterEncoding(encoding); filterChain.doFilter(servletRequest,servletResponse); } @Override public void destroy() { System.out.println("filter1 destory"); } }
filter过滤器,在xml中通过<filter>和<filter-mapping>定义,两个为一组在mapping中定义要过滤的路径,匹配路径的都会进入filter。在filter类中有三个方法。分别是初始化(init),销毁(destroy)。doFilter,每一个匹配路径符合的都会进入doFilter(),如果方法内部业务逻辑正确,则可以使用FilterChain.doFilter(req,resp);表示放行。多个filter会组成过滤器链,当一个第一个放行后,则进入第二个。全部通过则会到达servlet,一个不通过,则不通过。
servlet

package servlet;/* * @auther 顶风少年 * @mail dfsn19970313@foxmail.com * @date 2020-02-06 12:33 * @notify * @version 1.0 */ import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.util.Enumeration; public class UserServlet extends HttpServlet { @Override public void init() throws ServletException { System.out.println("servlet1"); super.init(); } @Override public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html;charset=UTF-8"); PrintWriter out = resp.getWriter(); out.println("success"); out.close(); } }
servlet服务,同样的在web.xml中通过<servlet>和<servlet-mapping>,每一个servletClass需要实现HttpServlet,类HttpServlet默认实现了各种请求方式的实现。我们需要根据自身需要覆盖对应的请求方式。配置<load-on-startup>1</load-on-startup>代表该Servlet的加载顺序,ServletContext创建后,会对设置了该标签的Servlet进行初始化,负值不初始化,值越小越先被初始化。所谓初始化就是调用Servlet的init()
SpringMvc
ContextLoaderListener做了什么
在这里我们跟踪源码,主要找到listener创建ApplicationContext和创建过程中在哪里加载的配置文件。

<context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/applicationconfig.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
首先我们在web.xml配置了一个监听器ContextLoaderListener,另外配置了全局参数contextConfigLocation

public class ContextLoaderListener extends ContextLoader implements ServletContextListener { public ContextLoaderListener() { } public ContextLoaderListener(WebApplicationContext context) { super(context); } public void contextInitialized(ServletContextEvent event) { this.initWebApplicationContext(event.getServletContext()); } public void contextDestroyed(ServletContextEvent event) { this.closeWebApplicationContext(event.getServletContext()); ContextCleanupListener.cleanupAttributes(event.getServletContext()); } }
在全局配置参数的value中我指向了一个Spring配置文件,并且添加了一个bean。

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean class="pojo.Person" id="person"></bean> </beans>
该ContextLoaderListener实现了ServletContextListener,那他的功能就是监听ServletContext创建和销毁。其次,它继承了ContextLoader,该类是Spring的类。我们先来看看contextInitialized()方法在ServletContext创建时都做了什么。
DispatcherServlet创建一个子容器

<servlet> <servlet-name>app</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/springmvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>app</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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"> <context:component-scan base-package="com.datang"/> </beans>
在这里我们跟踪源码,查看DispatcherServlet创建子容器的,和加载配置文件的源码。前边我们说过,Servlet初始化会调用init()方法。而DispatcherServlet也继承自HttpServlet。

mvc配置文件中需要声明的bean
HandlerMapping(处理器映射器):HandlerMapping的作用就是解析请求链接,然后根据请求链接找到执行这个请求的类(HandlerMapping所说的handler,也就是我们写的Controller或是Action)。
HandlerAdapter(处理器适配器):HandlerAdapter的作用是,执行handlerMapping找到的处理器。
ViewResolver(
视图解析器
):Controller处理完毕根据返回的逻辑视图,找到物理视图。
HandlerExceptionResolver:异常处理器,如果出现了异常由该类接手。
LocaleResolver:客户端转换器,获取客户端的语言环境和时区转换。
ThemeResolver:视图样式表,不知道干啥的,下边会说到。
FlashMapManager:管理重定向。
MultipartResolver:多部件解析。
以上bean都需要在mvc的配置文件中配置,是很麻烦的,但是,如果我们不配置默认使用DispatcherServlet.properties中的配置。注意!这个配置文件中,没有MultipartResolver。
HandlerMapping
HandlerMapping的作用就是解析请求链接,然后根据请求链接找到执行这个请求的类(HandlerMapping所说的handler,也就是我们写的Controller或是Action)。
BeanNameUrlHandlerMapping
BeanNameUrlHandlerMapping处理器映射器,处理器必须实现Controller接口,并且将该类配置成bean,bean的id需要是/开头,标识它是一个处理器。

package com.datang.controller;/* * @auther 顶风少年 * @mail dfsn19970313@foxmail.com * @date 2020-02-07 17:44 * @notify * @version 1.0 */ import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.Controller; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class BeanNameUrlHandlerMappingController implements Controller { @Override public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception { System.out.println("我是根据BeanNameUrlHandlerMapping找到的controller,但是显然的,我是错误的,因为我返回的是null"); return null; } }

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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"> <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/> <bean id="/beannameurlhandlermappingcontroller" class="com.datang.controller.BeanNameUrlHandlerMappingController"></bean> <context:component-scan base-package="com.datang"/> </beans>
RequestMappingHandlerMapping
RequestMappingHandlerMapping处理器映射器,需要使用@Controller注册bean然后对方法上带有@RequestMapping注解的方法,注册为处理器映射器。

package com.datang.controller;/* * @auther 顶风少年 * @mail dfsn19970313@foxmail.com * @date 2020-02-07 18:04 * @notify * @version 1.0 */ import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.servlet.ModelAndView; @Controller public class RequestMappingHandlerMappingController { @RequestMapping(value = "requestmappinghandlermappingcontroller",method = RequestMethod.GET) public ModelAndView handler() { System.out.println("我是根据RequestMappingHandlerMapping找到的controller,但是显然的,我是错误的,因为我返回的是null"); return null; } }

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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"> <!-- 根据beanName找到处理器 --> <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/> <bean id="/beannameurlhandlermappingcontroller" class="com.datang.controller.BeanNameUrlHandlerMappingController"></bean> <!-- 根据@RequestMapping 找到处理器--> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/> <context:component-scan base-package="com.datang"/> </beans>
HandlerAdapter
HandlerAdapter的作用是,执行handlerMapping找到的处理器。处理器有多种,显然的每一种的处理器所执行的方法都不一样。比如上边的两种,继承自Controller的处理器方法固定的是handleRequest()而使用@RequestMapping注解的则方法名不同。所以处理器适配器的存在是有必要的。
SimpleControllerHandlerAdapter
SimpleControllerHandlerAdapter这个处理器适配器是配合BeanNameUrlHandlerMapping处理器映射器使用的。定义了SimpleControllerHandlerAdapter便不会有其他的适配器。这里请求beannameurlhandlermappingcontroller会成功,但是请求requestmappinghandlermappingcontroller是不成功的。
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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"> <!-- 根据beanName找到处理器 --> <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/> <bean id="/beannameurlhandlermappingcontroller" class="com.datang.controller.BeanNameUrlHandlerMappingController"></bean> <!-- 根据@RequestMapping 找到处理器--> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/> <!-- 配合BeanNameUrlHandlerMapping使用 --> <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/> <context:component-scan base-package="com.datang"/> </beans>
RequestMappingHandlerAdapter
RequestMappingHandlerAdapter这个处理器适配器是配合RequestMappingHandlerMapping处理器映射器使用的。这次就可以正确访问requestmappinghandlermappingcontroller。

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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"> <!-- 根据beanName找到处理器 --> <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/> <bean id="/beannameurlhandlermappingcontroller" class="com.datang.controller.BeanNameUrlHandlerMappingController"></bean> <!-- 根据@RequestMapping 找到处理器--> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/> <!-- 配合BeanNameUrlHandlerMapping使用 --> <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/> <!-- 配合RequestMappingHandlerMapping使用 --> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/> <context:component-scan base-package="com.datang"/> </beans>
ViewResolver
InternalResourceViewResolver
根据Controller返回的逻辑视图名,寻找物理视图。

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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"> <!-- 根据beanName找到处理器 --> <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/> <bean id="/beannameurlhandlermappingcontroller" class="com.datang.controller.BeanNameUrlHandlerMappingController"></bean> <!-- 根据@RequestMapping 找到处理器--> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/> <!-- 配合BeanNameUrlHandlerMapping使用 --> <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/> <!-- 配合RequestMappingHandlerMapping使用 --> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/> <!-- 视图解析器,配置视图的前缀和后缀 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsps/"/> <property name="suffix" value=".jsp"/> </bean> <context:component-scan base-package="com.datang"/> </beans>

package com.datang.controller;/* * @auther 顶风少年 * @mail dfsn19970313@foxmail.com * @date 2020-02-07 21:09 * @notify * @version 1.0 */ import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.servlet.ModelAndView; @Controller public class ReturnJsp { @RequestMapping(value = "returnjsp", method = RequestMethod.GET) public String handler() { return "page1"; } }

<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <h1>我是page1</h1> </body> </html>
定义多个视图解析器(源码解析)
我们可以定义多个视图解析器,属性order规定视图解析器的优先级。DispatcherServlet试图从所有的视图解析器中匹配视图,如果匹配成功则不继续匹配。那么就让我们来碰碰壁吧。可以看出第二个路径出错了,问题就在于,它好像根本没有走我们的第二个视图解析器呀!看源码吧。(不想看源码,直接看解决办法。)

package com.datang.controller;/* * @auther 顶风少年 * @mail dfsn19970313@foxmail.com * @date 2020-02-07 21:09 * @notify * @version 1.0 */ import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.view.InternalResourceView; @Controller public class ReturnJsp { @RequestMapping(value = "returnjsp", method = RequestMethod.GET) public String handler() { return "page1"; } @RequestMapping(value = "returnjsp2", method = RequestMethod.GET) public String handler2() { return "page2"; } }

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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"> <!-- 根据beanName找到处理器 --> <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/> <bean id="/beannameurlhandlermappingcontroller" class="com.datang.controller.BeanNameUrlHandlerMappingController"></bean> <!-- 根据@RequestMapping 找到处理器--> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/> <!-- 配合BeanNameUrlHandlerMapping使用 --> <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/> <!-- 配合RequestMappingHandlerMapping使用 --> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/> <!-- 视图解析器,配置视图的前缀和后缀 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsps/"/> <property name="suffix" value=".jsp"/> <property name="order" value="1"/> </bean> <!-- 第二个视图解析器 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsps2/"/> <property name="suffix" value=".jsp"/> <property name="order" value="2"/> </bean> <context:component-scan base-package="com.datang"/> </beans>
入口类,就从DispatcherServlet开始(因为我已经debug了好久才找到从这么看最直观!!!)



<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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"> <!-- 根据beanName找到处理器 --> <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/> <bean id="/beannameurlhandlermappingcontroller" class="com.datang.controller.BeanNameUrlHandlerMappingController"></bean> <!-- 根据@RequestMapping 找到处理器--> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/> <!-- 配合BeanNameUrlHandlerMapping使用 --> <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/> <!-- 配合RequestMappingHandlerMapping使用 --> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/> <!-- 视图解析器,配置视图的前缀和后缀 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!-- 使用自己的viewClass --> <property name="viewClass" value="com.datang.view.MyInternalResourceView"/> <property name="prefix" value="/WEB-INF/jsps/"/> <property name="suffix" value=".jsp"/> <property name="order" value="1"/> </bean> <!-- 第二个视图解析器 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!-- 使用自己的viewClass --> <property name="viewClass" value="com.datang.view.MyInternalResourceView"/> <property name="prefix" value="/WEB-INF/jsps2/"/> <property name="suffix" value=".jsp"/> <property name="order" value="2"/> </bean> <context:component-scan base-package="com.datang"/> </beans>

package com.datang.view;/* * @auther 顶风少年 * @mail dfsn19970313@foxmail.com * @date 2020-02-08 14:49 * @notify * @version 1.0 */ import org.springframework.web.servlet.view.InternalResourceView; import java.io.File; import java.util.Locale; public class MyInternalResourceView extends InternalResourceView { @Override public boolean checkResource(Locale locale) throws Exception { //这里,super.getUrl就是prefix+viewName+suffix File file = new File(this.getServletContext().getRealPath("/") + super.getUrl()); // 判断该页面是否存在 return file.exists(); } }
来源:https://www.cnblogs.com/zumengjie/p/12269916.html