2、处理器映射器和适配器、视图解析器(springMVC笔记)

一、非注解映射器和适配器(工程springMVC02

1.1 非注解映射器

  • 非注解映射器BeanNameUrlHandlerMapping
    在之前我们使用的是这个处理器映射器,配置为:
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>

使用此映射器的时候是将bean的名字作为url进行查找,需要在配置Handler时指定bean的名字(就是url

<bean id="itemsController1" name="/queryItems.action" class="cn.itcast.ssm.controller.ItemsController1"/>
  • 非注解映射器SimpleUrlHandlerMapping
    从上面的配置可以看到,如果控制器较多的时候便不是很方便了,于是看使用此种非注解映射器如何配置:
    <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
                <!-- 对itemsController1进行url映射,一个处理器可以对应多个映射地址 -->
                <prop key="/queryItems1.action">itemsController1</prop>
                <prop key="/queryItems2.action">itemsController1</prop>
                <!-- 配置ItemsController2 -->
                <prop key="/queryItems3.action">itemsController2</prop>
            </props>
        </property>
    </bean>

使用此种映射器的时候一个控制器可以对应多个url,可以看到我们可以同时为多个控制器配置url,较为方便。这里注意:我们使用<prop>中的key指定url,其值即是相关控制器的id,但是使用此映射器的时候,配置控制器时则不需要指定name属性了。

1.2 非注解适配器

  • 非注解适配器SimpleControllerHandlerAdapter
    我们看相关的配置:
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>

而使用此配置器时,相关的控制器需要实现Controller接口,我们看相关的类实现ItemsController1.java

package cn.itcast.ssm.controller;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.HttpRequestHandler;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import cn.itcast.ssm.pojo.Items;

//实现Controller接口的映射器
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 T 430");
        
        Items items_2 = new Items();
        items_2.setName("苹果手机");
        items_2.setPrice(5000f);
        items_2.setDetail("iphone6s");
        
        itemsList.add(items_1);
        itemsList.add(items_2);
        
        //返回ModelAndView
        ModelAndView modelAndView = new ModelAndView();
        //相当于request的setAttribute方法,在jsp页面中就可以通过items取数据了
        modelAndView.addObject("itemsList",itemsList);
        
        //指定视图
        modelAndView.setViewName("/WEB-INF/jsp/items/itemsList.jsp");
        
        return modelAndView;
    }
}

这个类其实我们在之前的工程中已经给出了。

  • 非注解适配器HttpRequestHandlerAdapter
<bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter"/>

使用此适配器的控制器需要实现HttpRequestHandler接口,当然映射器可以任选。这里我们给出相关的类ItemsController2.java

package cn.itcast.ssm.controller;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.HttpRequestHandler;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import cn.itcast.ssm.pojo.Items;

//实现Controller接口的映射器
public class ItemsController2 implements HttpRequestHandler{

    @Override
    public void handleRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        List<Items> itemsList = new ArrayList<Items>();
        Items items_1 = new Items();
        items_1.setName("联想笔记本");
        items_1.setPrice(6000f);
        items_1.setDetail("ThinkPad T 430");
        
        Items items_2 = new Items();
        items_2.setName("苹果手机");
        items_2.setPrice(5000f);
        items_2.setDetail("iphone6s");
        
        itemsList.add(items_1);
        itemsList.add(items_2);
        
        request.setAttribute("itemsList",itemsList);
        //视图
        request.getRequestDispatcher("/WEB-INF/jsp/items/itemsList.jsp").forward(request, response);
        /*
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json;charset=utf-8");
        response.getWriter().write("json串");
        */
        
    }
}

注意:这种方式看起来很原始,但可通过response修改定义响应的内容,比如返回json数据。在上面我们已经给出相关的代码。
注意:这里我们配置多个适配器和映射器是不会冲突的。因为这里的映射器和适配器都是非注解的。

二、注解映射器和适配器(工程springMVC03

2.1 相关说明

  • 1.非注解的多个映射器或适配器不会冲突,但是却不能和注解的适配器同时使用,必须要成对,即注解的适配器必须使用注解的映射器。
  • 2.我们发现在上一个工程中我们将相关映射器和适配器删掉之后工程还是可以运行的,这是因为springMVC中有默认的配置,我们在包中找到一个资源文件:
    1

    前端控制器会从配置文件中加载处理器映射器、适配器、视图解析器等组件,如果不再配置文件中配置这些组件,那么就使用DispatcherServlet.properties中默认的配置。

2.2 注解的映射器和适配器

<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>

说明:这里我们分别配置了注解形式的映射器和适配器,当然springMVC给我们提供了更好用的工具,使用下面的配置我们就可以将上面的配置取消掉了:

<mvc:annotation-driven/>

说明:我们在使用此配置的时候报错很可能是schema文件没有配置上,在后面我们会给出完整的配置文件,可以自行查看。其实在开发中也是使用此种方式。

2.3 控制器编写

使用注解的方式,当然控制器的编写也是不一样了,我们发现在使用非注解的方式时编写控制器总是要继承相关的接口,那必然就要实现相关的方法,那如果我们想编写多个方法就不是很方便了,这里我们看注解方式可以很好的改善这一问题:
ItemsController3.java

package cn.itcast.ssm.controller;
import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import cn.itcast.ssm.pojo.Items;

//注解的handler
/*使用@Controller标识控制器*/

@Controller
public class ItemsController3{
    
    //商品查询列表,一般建议将url和方法名一样,@RequestMapping实现对下面方法和url进行映射,
    //即一个方法对应一个url,url后面可以加.action也可以不加
    @RequestMapping("/queryItems")
    public ModelAndView queryItems() throws Exception{
        List<Items> itemsList = new ArrayList<Items>();
        Items items_1 = new Items();
        items_1.setName("联想笔记本");
        items_1.setPrice(6000f);
        items_1.setDetail("ThinkPad T 430");
        
        Items items_2 = new Items();
        items_2.setName("苹果手机");
        items_2.setPrice(5000f);
        items_2.setDetail("iphone6s");
        
        itemsList.add(items_1);
        itemsList.add(items_2);
        
        //返回ModelAndView
        ModelAndView modelAndView = new ModelAndView();
        //相当于request的setAttribute方法,在jsp页面中就可以通过items取数据了
        modelAndView.addObject("itemsList",itemsList);
        
        //指定视图
        modelAndView.setViewName("/WEB-INF/jsp/items/itemsList.jsp");
        
        return modelAndView;
    }
    //其他方法也可以同时在此类中进行添加
}

说明:这里我们使用注解@Controller表示此类是一个控制器,使用注解@RequestMapping表示其对应的url。同时我们可以看到不需要继承任何接口,于是我们可以在此类中定义多个方法,而相关的url映射使用注解即可。

2.4 配置控制器

<!-- 配置Handler -->
<!--对于注解的Handler可以单个配置,id不需要了,因为在类中使用注解已经配置好了,在实际开发中使用主键扫描 -->
<!-- <bean class="cn.itcast.ssm.controller.ItemsController3"/> -->
<!-- 主键扫描,可以扫描Controller、service等等,这里是扫描Controller -->
<context:component-scan base-package="cn.itcast.ssm.controller"></context:component-scan>

说明:这里我们给出了两种配置方法,当然如何取舍我们在配置中已经注明。最后我们可以使用地址http://localhost:8080/springMVC03/queryItems.action进行访问。不管url中有没有.action,都使用上面的地址。

三、视图解析器

视图解析器默认是支持jstl的,但是在配置的时候我们还可以为跳转的jsp地址配置前缀和后缀:

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!-- 默认支持下面的jstl -->
        <!-- <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/> -->
        <!-- jsp路径前缀 -->
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <!-- jsp路径后缀 -->
        <property name="suffix" value=".jsp"></property>
    </bean>

这里我们配置了前缀和后缀,那么在控制器ItemsController3.java中进行跳转的时候就可以这样:

modelAndView.setViewName("items/itemsList");

最后:给出完整的配置文件springmvc.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
           http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-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/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
    
    <!-- 配置Handler -->
    <!--对于注解的Handler可以单个配置,id不需要了,因为在类中使用注解已经配置好了,在实际开发中使用主键扫描 -->
    <!-- <bean class="cn.itcast.ssm.controller.ItemsController3"/> -->
    <!-- 主键扫描,可以扫描Controller、service等等,这里是扫描Controller -->
    <context:component-scan base-package="cn.itcast.ssm.controller"></context:component-scan>
    
    <!-- **************************注解的处理器映射器************************** -->
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>

    <!-- **************注解的处理器适配器,所有的处理器适配器都实现HandlerAdapter************** -->
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>
    
    <!-- 使用下面的注解驱动可以代替上面的注解映射器和注解适配器的配置,同时默认加载了很多的参数绑定方法,比如json转换的解析器
    如果使用此种方式就不用配置上面的映射器和适配器了,在实际开发中使用此种方式 -->
    <!-- <mvc:annotation-driven/> -->
    
    <!-- ****************视图解析器,解析jsp视图,默认使用jstl,classpath下需要有jstl的包*************** -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!-- 默认支持下面的jstl -->
        <!-- <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/> -->
        <!-- jsp路径前缀 -->
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <!-- jsp路径后缀 -->
        <property name="suffix" value=".jsp"></property>
    </bean>
</beans>

四、跟踪源码

这里我们只是简要的跟踪一下源码,加深对springMVC执行流程的认识。

  • 1.前端控制器
    这里当然我们首先供前端控制器开始,此类中有一个入口方法doDispatch(),我们从此方法开始。

  • 2.前端控制器调用映射器查找控制器
    我们在doDispatch()中找到这样一段

    2

    这里我们进入getHandler方法:
    3

    可以看到此方法返回一个执行链HandlerExecutionChain

  • 3.调用处理器处理器调用handler
    映射器返回执行链之后前端加载器就会调用处理器去处理相关方法,在doDispatch()方法中找到:

    4

    我们进入此方法的时候发现出现了很多适配器,我们在之前都见过,它们在执行完之后都会返回一个ModelAndView

  • 4.视图渲染,将model数据填充到request
    doDispatch()方法中找到

    5

    进入此方法,在此方法中找到:
    6

    7

    可以看到调用的是render方法,得到一个view,再调用view的渲染方法,将model数据填充到request域中。在前端控制器类render()方法中找到:
    8

    此类是一个接口,我们进入其抽象方法
    9

    再次进入,可以看到:
    10

    进入方法renderMergedOutputModel

11

这里我们可以看到很多渲染类,之前我们配置了一个InternalResourceViewResolver,选择InternalResourceView,看到下面这段代码:
12

点击进入:
13

这里就将模型数据填充到了视图类中。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,723评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,485评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,998评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,323评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,355评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,079评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,389评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,019评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,519评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,971评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,100评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,738评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,293评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,289评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,517评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,547评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,834评论 2 345

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,600评论 18 139
  • Spring Boot 参考指南 介绍 转载自:https://www.gitbook.com/book/qbgb...
    毛宇鹏阅读 46,748评论 6 342
  • 1. 简介 1.1 什么是 MyBatis ? MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的...
    笨鸟慢飞阅读 5,429评论 0 4
  • 作画顺序:房子,树,女朋友,我,太阳,花草。女朋友手里拿着书,想画两个人是侧身45度相对的,但不会画,我自己因为上...
    蓝田_b685阅读 558评论 0 0
  • 哎呀呀,终于可以住进新房里啦!我是相当的兴奋,一想到以后附近有那么多好吃好玩的地儿,真是相当满足。好啦,转回正题,...
    MissBella阅读 1,055评论 2 18