学习笔记

1 Springmvc框架

1.1 什么是springmvc

springmvc是spring框架的一个模块,springmvc和spring无需通过中间整合层整合。
springmvc是一个基于mvc的web框架。

image-20191207170331686.png

1.2 mvc在b/s系统下的应用

mvc是一个设计模式,mvc在b/s系统下的应用

image-20191207170935073.png

1.3 springmvc框架

image-20191207171000916.png

2 入门程序

2.1 环境

  • 数据库环境:sqlserver2008
  • Java环境:jdk1.7.0_72
  • eclipse indigo
  • springmvc版本:spring4.2

image-20191207171309591.png

2.2 需求

springmvc和mybatis使用一个案例(商品订单)

image-20191207171335125.png

功能需求:商品列表查询

2.3 配置前端控制器

  • web.xml中配置

      <!-- 配置前端控制器 -->
      <servlet>
          <servlet-name>springmvc</servlet-name>
          <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
          <!-- contextConfigLocation配置springmvc加载的配置文件(配置处理器映射器、适配器等等)
          如果不配置contextConfigLocation,默认加载的是/WEB-INF/servlet名称/serlvet.xml(springmvc/servlet.xml)
           -->
          <init-param>
              <param-name>contextConfigLocation</param-name>
              <param-value>classpath:springmvc.xml</param-value>
          </init-param>
      </servlet>
      
      <servlet-mapping>
          <servlet-name>springmvc</servlet-name>
          <!-- 
              第一种:*.action,访问以action结尾的由DispatcherServlet进行解析
              第二种:/,所有访问的地址都由DispatcherServlet进行解析,对于静态文件解析需要配置不让DispatcherServlet解析
          使用此种方法可以实现RESTful风格
              第三种:/*,这样配置不对,使用这种配置最终要转发到jsp界面时,
          仍由DispatcherServlet解析jsp,不能根据jsp页面找到Handler,所以会报错
           -->
          <url-pattern>*.action</url-pattern>
      </servlet-mapping>

2.4 处理器适配器

  • 在classpath下的springmvc.xml中配置

    <!-- 处理器适配器 
    所有的处理器适配器都实现HandlerAdapter接口
    -->
    <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" /> 
  • 通过查看源代码,此适配器能执行实现controller接口的Handler

    public class SimpleControllerHandlerAdapter implements HandlerAdapter {  
         public boolean supports(Object handler) {  
             return (handler instanceof Controller);  
         }  
         ......  
    }

2.5 开发Handler

  • 需要实现controller接口,才能由org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter适配器执行

    public class ItemsController1 implements Controller{
        @Override
        public ModelAndView handleRequest(HttpServletRequest request,
                HttpServletResponse response) throws Exception {
            
            //调用service查找数据库,查询商品列表,这里使用静态数据模拟
            List<Items> itemsList = new ArrayList<Items>();
            
            Items items_1 = new Items();
            items_1.setName("联想笔记本");  
            items_1.setPrice(6000f);  
            items_1.setDetail("ThinkPad T430 联想笔记本电脑!");  
              
            Items items_2 = new Items();  
            items_2.setName("苹果手机");  
            items_2.setPrice(5000f);  
            items_2.setDetail("iphone6苹果手机!");  
              
            itemsList.add(items_1);  
            itemsList.add(items_2);  
            
            //返回ModelAndView
            ModelAndView modelAndView = new ModelAndView();
            //相当于request的setAttribute,在jsp页面中通过itemsList取数据
            modelAndView.addObject("itemsList", itemsList);
            
            //指定视图
            modelAndView.setViewName("/WEB-INF/jsp/items/itemsList.jsp");
            
            return modelAndView;
        }
    
    }

2.6 视图编写

<%@ page language="java" contentType="text/html; charset=UTF-8"  
    pageEncoding="UTF-8"%>  
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>   
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt"  prefix="fmt"%>  
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">  
<html>  
<head>  
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  
<title>查询商品列表</title>  
</head>  
<body>   
<form action="${pageContext.request.contextPath }/item/queryItem.action" method="post">  
查询条件:  
<table width="100%" border=1>  
<tr>  
<td><input type="submit" value="查询"/></td>  
</tr>  
</table>  
商品列表:  
<table width="100%" border=1>  
<tr>  
    <td>商品名称</td>  
    <td>商品价格</td>  
    <td>生产日期</td>  
    <td>商品描述</td>  
    <td>操作</td>  
</tr>  
<c:forEach items="${itemsList }" var="item">  
<tr>  
    <td>${item.name }</td>  
    <td>${item.price }</td>  
    <td><fmt:formatDate value="${item.createtime}" pattern="yyyy-MM-dd HH:mm:ss"/></td>  
    <td>${item.detail }</td>  
    <td><a href="${pageContext.request.contextPath }/item/editItem.action?id=${item.id}">修改</a></td>  
</tr>  
</c:forEach>  
</table>  
</form>  
</body>  
</html>  

2.7 配置Handler

  • 将编写Handler在spring容器加载

    <!-- 配置Handler -->
    <bean name="/queryItems.action" class="cn.itcast.ssm.controller.ItemsController1"/>

2.8 配置处理器映射器

  • 在classpath下的springmvc.xml中配置

    <!-- 处理器映射器 
    将bean的name作为URL进行查找,需要在配置Handler是指定beanname(就是url)
    --> 
    <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" /> 

2.9 配置视图解析器

  • 需要配置解析jsp的视图解析器

    <!-- 视图解析器 
    解析jsp视图,默认实用jstl标签,classpath下面得有jstl的包
    -->       
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" />

2.10 部署调试

  • 访问地址:http://localhost:8080/SpringMVCStudy/queryItems.action
    image-20191207174117345.png
  • 如果地址输错,处理器映射器根据url找不到Handler,报下边的错误。说明url错误。
    image-20191207174138914.png
  • 如果处理器映射器根据url找到了Handler,转发的jsp页面找到,报下边的错误,说明jsp页面地址错误了。
    //指定视图里的ViewName可能写错了,不存在你写的那个jsp文件
    modelAndView.setViewName("/WEB-INF/jsp/items/itemsList.jsp");
    image-20191207174207824.png

    3 非注解的处理器映射器和适配器

3.1 非注解的处理器映射器

  • 处理器映射器:
    org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping

    <!-- 配置Handler -->
    <bean id="itemsController1" name="/queryItems.action" class="cn.itcast.ssm.controller.ItemsController1"/>
      
    <!-- 处理器映射器 
    将bean的name作为URL进行查找,需要在配置Handler是指定beanname(就是url)
    --> 
    <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" /> 
  • 另外一个映射器
    org.springframework.web.servlet.handler.SimpleUrlHandlerMapping

    <!--简单url映射  -->  
    <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">  
        <property name="mappings">  
            <props>  
                <!-- 对itemsController1进行url映射,url是/queryItems1.action,1个bean可以配多个url -->  
                <prop key="/queryItems1.action">itemsController1</prop>  
                <prop key="/queryItems2.action">itemsController1</prop> 
            </props> 
        </property>  
    </bean> 
  • 多个映射器可以并存,前端控制判断url能让哪个映射器处理,就让哪个映射器处理。

3.2 非注解的处理器适配器

  • org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter
    要求编写的Handler实现Controller接口

    <!-- 处理器适配器 
    所有的处理器适配器都实现HandlerAdapter接口
    -->
    <bean 
          class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" /> 
  • org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter
    要求编写的Handler实现HttpRequestHandler接口

    <!-- 另一个非注解的适配器 -->
    <bean 
        class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter" />
  • ItemsController2

    public class ItemsController1 implements HttpRequestHandler{
        @Override
        public void handleRequest(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            
            //调用service查找数据库,查询商品列表,这里使用静态数据模拟
            List<Items> itemsList = new ArrayList<Items>();
            
            Items items_1 = new Items();
            items_1.setName("联想笔记本");  
            items_1.setPrice(6000f);  
            items_1.setDetail("ThinkPad T430 联想笔记本电脑!");  
    
            Items items_2 = new Items();  
            items_2.setName("苹果手机");  
            items_2.setPrice(5000f);  
            items_2.setDetail("iphone6苹果手机!");  
            itemsList.add(items_1);  
            itemsList.add(items_2);  
    
            //设置模型数据
            request.setAttribute("itemsList", itemsList);
            //设置转发的视图
            request.getRequestDispatcher("/WEB-INF/jsp/items/itemsList.jsp").forward(request, response);
            //使用此方法可以通过修改response,设置响应的数据格式,比如json数据
        }
    }
  • 别忘了配置Handler和映射器

          <!-- 配置另外一个Handler -->
          <bean id="itemsController2" class="cn.itcast.ssm.controller.ItemsController1"></bean>
         <!--简单url映射  -->  
        <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">  
            <property name="mappings">  
                <props>  
                    <!-- 对itemsController1进行url映射,url是/queryItems1.action,1个bean可以配多个url -->  
                    <prop key="/queryItems1.action">itemsController1</prop>  
                    <prop key="/queryItems2.action">itemsController1</prop> 
                    <prop key="/queryItems3.action">itemsController2</prop> 
                </props> 
            </property>  
        </bean> 
  • 总的来说,处理器映射器就是根据URL来找Handler,处理器适配器就是按照它要求的规则(handler instanceof XXX接口)去执行Handler

4 DispatcherSerlvet.properties

通过以前咱们写的样例,会发现,多个适配器和多个映射器可以并存但是其实你不在springmvc.xml中配置适配器,也可以正常运行程序。因为在SpringMVC的jar包中含有一个默认配置文件,如果没有在springmvc.xml配置,就默认使用DispatcherSerlvet.properties的配置如图
image-20191207174936482.png
前端控制器会从上边的文件中加载处理映射器、适配器、视图解析器等组件,如果不在springmvc.xml中配置,使用默认加载的。

# Default implementation classes for DispatcherServlet's strategy interfaces.  
# Used as fallback when no matching beans are found in the DispatcherServlet context.  
# Not meant to be customized by application developers.  
  
org.springframework.web.servlet.LocaleResolver=
    org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver  
  
org.springframework.web.servlet.ThemeResolver=
    org.springframework.web.servlet.theme.FixedThemeResolver  
  
org.springframework.web.servlet.HandlerMapping=    org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\  
org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping  
  
org.springframework.web.servlet.HandlerAdapter=
    org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\  
    org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\  
    org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter  
  
org.springframework.web.servlet.HandlerExceptionResolver=
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver,\  
    org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\  
    org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver  
  
org.springframework.web.servlet.RequestToViewNameTranslator=
    org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator  
  
org.springframework.web.servlet.ViewResolver=
    org.springframework.web.servlet.view.InternalResourceViewResolver  
  
org.springframework.web.servlet.FlashMapManager=
    org.springframework.web.servlet.support.SessionFlashMapManager  

5 注解的处理器映射器和适配器

  • 注解映射器

    • 在spring3.1之前,使用org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMappin注解映射器。
    • 在spring3.1之后,使用org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping注解映射器。
  • 注解适配器

    • 在spring3.1之前使用org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter注解适配器。
    • 在spring3.1之后使用org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter注解适配器。

5.1 配置注解映射器和适配器

<!-- 注解映射器 -->  
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>  
<!-- 注解适配器 -->  
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>  

<!-- 使用mvc的注解驱动mvc:annotation-driven可以代替上边的注解映射器和注解适配器配置 
mvc:annotation-driven默认加载很多参数绑定方法,比如json转换解析器
如果使用mvc:annotation-driven就不用配置上边的RequestMappingHandlerMapping和RequestMappingHandlerAdapter
实际开发使用RequestMappingHandlerAdapter
-->
<!-- <mvc:annotation-driven></mvc:annotation-driven> -->

5.2 开发注解Handler

  • 必须同时使用注解的映射器和注解的适配器,必须配对使用。

        //使用Controller标识他是一个控制器
        @Controller
        public class ItemsController3 {
        
            //商品查询列表
            //@RequestMapping实现queryItems方法和url进行映射,一个方法对应一个url
            //一般建议将url和方法名写成一样
            @RequestMapping("/queryItems")
            public ModelAndView queryItems() throws Exception{
                
                //调用service查找数据库,查询商品列表,这里使用静态数据模拟
                List<Items> itemsList = new ArrayList<Items>();
                
                Items items_1 = new Items();
                items_1.setName("联想笔记本");  
                items_1.setPrice(6000f);  
                items_1.setDetail("ThinkPad T430 联想笔记本电脑!");  
                  
                Items items_2 = new Items();  
                items_2.setName("苹果手机");  
                items_2.setPrice(5000f);  
                items_2.setDetail("iphone6苹果手机!");  
                  
                itemsList.add(items_1);  
                itemsList.add(items_2);  
            
                //返回ModelAndView
                ModelAndView modelAndView = new ModelAndView();
                //相当于request的setAttribute,在jsp页面中通过itemsList取数据
                modelAndView.addObject("itemsList", itemsList);
              
                //指定视图
                modelAndView.setViewName("/WEB-INF/jsp/items/itemsList.jsp");
              
                return modelAndView;
            }
        }

5.3 在spring中加载Handler

<!-- 对于注解Handler可以单个进行配置 
    实际开发中建议使用组件扫描
-->
<!-- <bean class="cn.itcast.ssm.controller.ItemsController3"></bean> -->
<!-- 可以扫描controller,service,... 
   这里让组件扫描controller,指定controller的包
-->
<context:component-scan base-package="cn.itcast.ssm.controller"></context:component-scan>

5.4 部署测试

6 源码分析

  • 通过前端控制区源码分析springmvc的执行过程
  • 点开org.springframework.web.servlet.DispatcherServlet,里面有doDiapatch的方法

    protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {  
        HttpServletRequest processedRequest = request;  
        HandlerExecutionChain mappedHandler = null;  
        boolean multipartRequestParsed = false;  
        WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);  
        try {  
            ModelAndView mv = null;  
            Exception dispatchException = null;  
            try {  
                processedRequest = checkMultipart(request);  
                multipartRequestParsed = processedRequest != request;  
                // Determine handler for the current request.  
                mappedHandler = getHandler(processedRequest, false);  
                if (mappedHandler == null || mappedHandler.getHandler() == null) {  
                    noHandlerFound(processedRequest, response);  
                    return;  
                }  
                // Determine handler adapter for the current request.  
                HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());  
                // Process last-modified header, if supported by the handler.  
                String method = request.getMethod();  
                boolean isGet = "GET".equals(method);  
                if (isGet || "HEAD".equals(method)) {  
                    long lastModified = ha.getLastModified(request, mappedHandler.getHandler()); 
                    if (logger.isDebugEnabled()) {
                        String requestUri = urlPathHelper.getRequestUri(request);
                        logger.debug("Last-Modified value for [" + requestUri + "] is: " + lastModified);  
                    }  
                    if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
                        return; 
                    }
                }  
                if (!mappedHandler.applyPreHandle(processedRequest, response)) { 
                    return;  
                }  
                try {  
                    // Actually invoke the handler.  
                    mv = ha.handle(processedRequest, response, mappedHandler.getHandler());  
                }  
                finally {  
                    if (asyncManager.isConcurrentHandlingStarted()) { 
                        return;  
                    }  
                }  
                applyDefaultViewName(request, mv);  
                mappedHandler.applyPostHandle(processedRequest, response, mv);  
            }  
            catch (Exception ex) {  
                dispatchException = ex;  
            }  
            processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);  
        }  
        catch (Exception ex) {  
            triggerAfterCompletion(processedRequest, response, mappedHandler, ex);  
            } 
        catch (Error err) {  
            triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err);  
        }  
        finally {  
            if (asyncManager.isConcurrentHandlingStarted()) { 
                // Instead of postHandle and afterCompletion 
                mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);  
                return;  
            }  
            // Clean up any resources used by a multipart request.
            if (multipartRequestParsed) {  
                cleanupMultipart(processedRequest);  
            }  
        } 
    }
    • 第一步:前端控制器接收请求:.action类型的URL通过过滤器进入DispatcherServlet类,调用其doDiapatch()方法

      protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {  
          HttpServletRequest processedRequest = request;  
          HandlerExecutionChain mappedHandler = null;  
          boolean multipartRequestParsed = false;  
      
          WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);  
          ......  
      } 
    • 第二步:前端控制器调用处理器映射器查找Handler:在doDiapatch()方法中调用了DispatcherServlet类的getHandler方法

          HandlerExecutionChain mappedHandler = null;  
          ......  
          mappedHandler = getHandler(processedRequest, false); 
    • 其中getHandler方法:

      @Deprecated  
      protected HandlerExecutionChain getHandler(HttpServletRequest request, boolean cache) throws Exception { 
          return getHandler(request);  
      }  
      protected HandlerExecutionChain getHandler(HttpServletRequest request) 
          throws Exception {  
          for (HandlerMapping hm : this.handlerMappings) {  
              if (logger.isTraceEnabled()) {  
                  logger.trace(  
                     "Testing handler map [" + hm + "] in DispatcherServlet with name '" 
        }  
        HandlerExecutionChain handler = hm.getHandler(request);  
        if (handler != null) { 
            return handler;  
        }  
    }  
    return null;  
} 
```

- 说明映射器根据request当中的URL,找到了Handler,最终返回一个执行器的链(HandlerExecutionChain)。这个链里面有Handler。
  • 第三步:调用处理器适配器执行Handler,得到执行结果ModelAndView

    ModelAndView mv = null;  
    ......  
    mv = ha.handle(processedRequest, response, mappedHandler.getHandler());  
  • 第四步:视图渲染,将model数据填充到request域

    • 视图解析,得到view,在doDiapatch()方法中有这一句

      processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
      • 其中processDispatchResult方法

        private void processDispatchResult(HttpServletRequest request, 
                                           HttpServletResponse response, 
                                           HandlerExecutionChain mappedHandler, 
                                           ModelAndView mv, 
                                           Exception exception)
            throws Exception {  
            boolean errorView = false;  
            if (exception != null) {  
                if (exception instanceof ModelAndViewDefiningException) {  
                    logger.debug("ModelAndViewDefiningException encountered", exception);  
                    mv = ((ModelAndViewDefiningException) exception).getModelAndView();
                }  
                else {  
                    Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null); 
                    mv = processHandlerException(request, response, handler, exception);  
                    errorView = (mv != null);  
                }  
            }  
            // Did the handler return a view to render? 
            if (mv != null && !mv.wasCleared()) {  
                render(mv, request, response);
                if (errorView) { 
                    WebUtils.clearErrorRequestAttributes(request);
                } 
            }  
            else {  
                if (logger.isDebugEnabled()) { 
                    logger.debug("Null ModelAndView returned to DispatcherServlet with name '" 
                             "': assuming HandlerAdapter completed request handling");  
            }  
        }  
        if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
            // Concurrent handling started during a forward  
            return;  
        }  
        if (mappedHandler != null) { 
            mappedHandler.triggerAfterCompletion(request, response, null);
        }  
    }
    ```

  - 其中render(mv, request, response);方法中有

    ```java
    view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request);
    ```

  - 渲染方法:  

    ```java
    view.render(mv.getModelInternal(), request, response); 
    ```

- 调用视图渲染方法,将model数据填充到request域

  ```java
  protected void exposeModelAsRequestAttributes(Map<String, Object> model, HttpServletRequest request) 
      throws Exception {
      //遍历model里面的数据,填充到request域
      for (Map.Entry<String, Object> entry : model.entrySet()) { 
          String modelName = entry.getKey();  
          Object modelValue = entry.getValue();
          if (modelValue != null) {  
              request.setAttribute(modelName, modelValue);
              if (logger.isDebugEnabled()) {  
                  logger.debug("Added model object '" 
                               + modelName 
                               + "' of type [" 
                               + modelValue.getClass().getName() 
                               + "] to request in view with name '" 
                               + getBeanName() 
                               + "'"); 
              }  
          }  
          else {  
              request.removeAttribute(modelName);  
              if (logger.isDebugEnabled()) {  
                  logger.debug("Removed model object '" + modelName + 
                               "' from request in view with name '" + getBeanName() + "'");  
              }  
          }  
      } 
  }
  ```

7 入门程序小结

通过入门程序理解springmvc前端控制器、处理器映射器处理器适配器、视图解析器用法。

前端控制器配置:

  • 第一种:*.action,访问以action结尾的由DispatcherServlet进行解析
  • 第二种:/,所有访问的地址都由DispatcherServlet进行解析,对于静态文件解析需要配置不让DispatcherServlet解析,使用此种方法可以实现RESTful风格

处理器映射器:

  • 非注解处理器映射器(了解)
  • 注解的处理器映射器(掌握)

    • 对标记有@Controller类中标识有@RequestMapping的方法进行映射。在@RequestMapping里边定义映射的url。
    • 使用注解映射器不用再xml中配置url和Handler的映射关系。

处理器适配器:

  • 非注解处理器适配器(了解)
  • 注解的处理器适配器(掌握)

    • 注解的处理器映射器和注解的处理器适配器是配对使用的。

      • <mvc:annotation-driven></mvc:annotation-driven>可以代替下面的配置

        <!-- 注解映射器 -->
        <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
        <!-- 注解适配器 -->
        <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>

    • 实际开发使用:mvc:annotation-driven

视图解析器配置前缀和后缀

<!-- 视图解析器 
解析jsp视图,默认实用jstl标签,classpath下面得有jstl的包
-->       
<bean  
    class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <!-- 配置jsp路径的前缀 -->
    <property name="prefix" value="/WEB-INF/jsp/"></property>  
    <!-- 配置jsp路径的后缀 -->
    <property name="suffix" value=".jsp"></property>      
</bean>
  • 程序中不用指定前缀和后缀:

    //指定视图  
    //下边的路径,如果在视图解析器中配置jsp的路径前缀和后缀,修改为items/itemsList  
    //modelAndView.setViewName("/WEB-INF/jsp/items/itemsList.jsp")  
    //下边的路径配置就可以不在程序中指定jsp路径的前缀和后缀  
    modelAndView.setViewName("items/itemsList");

被江队泡的茶饼
0 声望0 粉丝