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

处理器映射器和适配器、视图解析器(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


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


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值