一、非注解映射器和適配器(工程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"/>
而使用此配置器時邻储,相關的控制器需要實現(xiàn)Controller
接口赋咽,我們看相關的類實現(xiàn)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;
//實現(xiàn)Controller接口的映射器
public class ItemsController1 implements Controller{
@Override
public ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response) throws Exception {
//調用service查詢數(shù)據(jù)庫,查詢商品列表吨娜,這里使用靜態(tài)數(shù)據(jù)庫模擬
List<Items> itemsList = new ArrayList<Items>();
Items items_1 = new Items();
items_1.setName("聯(lián)想筆記本");
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取數(shù)據(jù)了
modelAndView.addObject("itemsList",itemsList);
//指定視圖
modelAndView.setViewName("/WEB-INF/jsp/items/itemsList.jsp");
return modelAndView;
}
}
這個類其實我們在之前的工程中已經給出了。
- 非注解適配器
HttpRequestHandlerAdapter
<bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter"/>
使用此適配器的控制器需要實現(xiàn)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;
//實現(xiàn)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("聯(lián)想筆記本");
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
數(shù)據(jù)毡琉。在上面我們已經給出相關的代碼。
注意:這里我們配置多個適配器和映射器是不會沖突的妙色。因為這里的映射器和適配器都是非注解的绊起。
二、注解映射器和適配器(工程springMVC03
)
2.1 相關說明
- 1.非注解的多個映射器或適配器不會沖突燎斩,但是卻不能和注解的適配器同時使用,必須要成對蜂绎,即注解的適配器必須使用注解的映射器栅表。
- 2.我們發(fā)現(xiàn)在上一個工程中我們將相關映射器和適配器刪掉之后工程還是可以運行的,這是因為
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
文件沒有配置上许布,在后面我們會給出完整的配置文件,可以自行查看绎晃。其實在開發(fā)中也是使用此種方式蜜唾。
2.3 控制器編寫
使用注解的方式,當然控制器的編寫也是不一樣了庶艾,我們發(fā)現(xiàn)在使用非注解的方式時編寫控制器總是要繼承相關的接口袁余,那必然就要實現(xiàn)相關的方法,那如果我們想編寫多個方法就不是很方便了咱揍,這里我們看注解方式可以很好的改善這一問題:
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實現(xiàn)對下面方法和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("聯(lián)想筆記本");
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取數(shù)據(jù)了
modelAndView.addObject("itemsList",itemsList);
//指定視圖
modelAndView.setViewName("/WEB-INF/jsp/items/itemsList.jsp");
return modelAndView;
}
//其他方法也可以同時在此類中進行添加
}
說明:這里我們使用注解@Controller
表示此類是一個控制器积暖,使用注解@RequestMapping
表示其對應的url
藤为。同時我們可以看到不需要繼承任何接口,于是我們可以在此類中定義多個方法夺刑,而相關的url
映射使用注解即可缅疟。
2.4 配置控制器
<!-- 配置Handler -->
<!--對于注解的Handler可以單個配置,id不需要了遍愿,因為在類中使用注解已經配置好了存淫,在實際開發(fā)中使用主鍵掃描 -->
<!-- <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不需要了,因為在類中使用注解已經配置好了,在實際開發(fā)中使用主鍵掃描 -->
<!-- <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"/>
<!-- **************注解的處理器適配器漓帚,所有的處理器適配器都實現(xiàn)HandlerAdapter************** -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>
<!-- 使用下面的注解驅動可以代替上面的注解映射器和注解適配器的配置母债,同時默認加載了很多的參數(shù)綁定方法,比如json轉換的解析器
如果使用此種方式就不用配置上面的映射器和適配器了胰默,在實際開發(fā)中使用此種方式 -->
<!-- <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
執(zhí)行流程的認識奴迅。
1.前端控制器
這里當然我們首先供前端控制器開始青责,此類中有一個入口方法doDispatch()
,我們從此方法開始取具。-
2.前端控制器調用映射器查找控制器
我們在doDispatch()
中找到這樣一段
2
這里我們進入getHandler
方法:
3
可以看到此方法返回一個執(zhí)行鏈HandlerExecutionChain
脖隶。 -
3.調用處理器處理器調用
handler
映射器返回執(zhí)行鏈之后前端加載器就會調用處理器去處理相關方法,在doDispatch()
方法中找到:
4
我們進入此方法的時候發(fā)現(xiàn)出現(xiàn)了很多適配器暇检,我們在之前都見過产阱,它們在執(zhí)行完之后都會返回一個ModelAndView
。 -
4.視圖渲染块仆,將
model
數(shù)據(jù)填充到request
域
在doDispatch()
方法中找到
5
進入此方法构蹬,在此方法中找到:
6
7
可以看到調用的是render
方法,得到一個view
悔据,再調用view
的渲染方法庄敛,將model
數(shù)據(jù)填充到request
域中。在前端控制器類render()
方法中找到:
8
此類是一個接口科汗,我們進入其抽象方法
9
再次進入藻烤,可以看到:
10
進入方法renderMergedOutputModel
這里我們可以看到很多渲染類,之前我們配置了一個
InternalResourceViewResolver
头滔,選擇InternalResourceView
怖亭,看到下面這段代碼:點擊進入:
這里就將模型數(shù)據(jù)填充到了視圖類中。