spring-mvc

核能气质少年 提交于 2020-02-08 16:18:26

回顾原生的Web应用

  1. 全局参数

  2. listener

  3. filter

  4. servlet

SpringMvc

  1. ContextLoaderListener做了什么

  2. DispatcherServlet创建一个子容器

  3. mvc配置文件中需要声明的bean

  4. HandlerMapping

    1. BeanNameUrlHandlerMapping

    2. RequestMappingHandlerMapping

  5. HandlerAdapter

    1. SimpleControllerHandlerAdapter

    2. RequestMappingHandlerAdapter

  6. ViewResolver

    1. InternalResourceViewResolver

    2. 义多个视图解析器(源码解析)

回顾原生的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>
View Code

全局参数

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");
    }
}
View Code

listener监听器分为三类,分别监听ServletContext域,HttpSession域,ServletRequest域。每一类又分成监听域对象的创建、销毁和域对象内的属性的变化。在web.xml中可以定义多个监听器。同类型的监听器按照加载顺序执行。

以上代码片段创建了一个servletContextListener用来监听Servlet上下文的创建和销毁。

servletContextListener、 HttpSessionListener、 ServletRequestListener、 ServletContextAttributeListener、 HttpSessionAttributeListener、 ServletRequestAttributeListener

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");
    }
}
View Code

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();
    }
}
View Code

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>
View Code

首先我们在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());
    }
}
View Code

在全局配置参数的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>
View Code

该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>
View Code
<?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>
View Code

在这里我们跟踪源码,查看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;
    }
}
View Code
<?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>
View Code

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;
    }
}
View Code
<?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>
View Code

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>
View Code

 

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>
View Code

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>
View Code
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";
    }
}
View Code
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>我是page1</h1>
</body>
</html>
View Code

定义多个视图解析器(源码解析)

我们可以定义多个视图解析器,属性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";
    }
}
View Code
<?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>
View Code

入口类,就从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>
View Code
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();
    }
}
View Code

 

 


 

 

 

 


 

 

 

 


 

 

 



 

 

 

 

 

 

 

 

 

 



 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!