1、MVC設計模式(這裏講的是b/s情況下的模式)
2、springMVC框架與spring的關係
springMVC只是spring框架的一個模塊;如下圖是spring整個框架的內容:
3、springMVC的框架結構原理
1、 用戶發起請求,請求到DispatcherServlet前端控制器
DispatcherServlet(中央調度),負責request和response,負責調用處理器映射器查找Handler,負責調用處理器適配器執行Handler,有了前端控制器降低了各各組件之間的耦合性,系統擴展性提高。
2、 DispatcherServlet前端控制器請求處理器映射器HandlerMapping查找Handler
根據用戶請求的url,根據一定的規則去查找(比如:xml配置,註解)
3、 HandlerMapping處理器映射器將Handler返回給前端控制器
4、 DispatcherServlet前端控制器調用HandlerAdapter處理器適配器執行Handler
程序員編寫的Handler是按照適配器要求的規則去執行Handler
5、 HandlerAdapter處理器適配器執行Handler
適配器按照一定規則去執行Handler
6、 Handler執行完成,返回ModelAndView
ModelAndView是springmvc的封裝對象,將model和view封裝在一起。
7、 HandlerAdapter處理器適配器將ModelAndView返回給前端 控制器
8、 前端控制器調用視圖解析器,進行視圖解析,解析完成給前端控制器返回View
View是springmvc的封裝對象,是一個接口,實現類包括jspview,pdfview。。。。
9、 前端控制器調用view進行視圖渲染
將模型數據填充到view(將model數據填充到request)響應給用戶
10、前端控制器響應給用戶。
4、這裏詳細的說明一下springmvc平常要了解的(開發是不常用的,一般都是用註解)三大組件:1、處理器映射器常用的兩個是(在註解開發中就是指的requestMapping註解):
<!-- 處理器映射器 根據url匹配bean的name 處理器映射器實現了HandlerMapping接口 -->
<bean
class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />
<!-- 簡單url映射的處理器映射器 -->
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/hello1.action">hello_controller</prop>
<prop key="/hello2.action">hello_controller</prop>
<prop key="/hello3.action">hello_controller3</prop>
</props>
</property>
</bean>
對應的controller類的配置:
<!-- 配置action -->
<bean id="hello_controller" name="/helloworld.action" class="cn.itcast.springmvc.Hello" />
<!-- 配置action -->
<bean id="hello_controller3" class="cn.itcast.springmvc.Hello1" />
根據處理器映射器就可以找到對應的handler(函數)
package cn.itcast.springmvc;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
/**
*
* <p>Title: Hello</p>
* <p>Description: 使用SimpleControllerHandlerAdapter適配器</p>
* <p>Company: www.itcast.com</p>
* @author
* @version 1.0
*/
public class Hello implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response) throws Exception {
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("message", "helloworld!!!!!!");
//響應到jsp的邏輯試圖
//modelAndView.setViewName("/WEB-INF/jsp/hello.jsp");
return modelAndView;
}
}
2、瞭解兩個處理器適配器(實際上就是我們在使用springmvc的controller註解)
<!-- 處理器適配器 實現了HandlerAdapter接口 action按照適配器要求開發 ,規則是實現Controller接口 -->
<bean
class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" />
<!-- 配置HttpRequestHandlerAdapter處理器適配器 -->
<bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter" />
使用不同的適配器在MVC的C層的類需要實現不同的接口
使用SimpleControllerHandlerAdapter適配器,就要使用SimpleControllerHandlerAdapter適配器的規則進行處理
/**
*
* <p>Title: Hello</p>
* <p>Description: 使用SimpleControllerHandlerAdapter適配器</p>
* <p>Company: www.itcast.com</p>
* @author
* @version 1.0
*/
public class Hello implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response) throws Exception {
ModelAndView modelAndView = new ModelAndView();
//下面的方法就相當於request.setAttribute("message", message);
modelAndView.addObject("message", "helloworld!!!!!!");
return modelAndView;
}
}
使用 使用HttpRequestHandlerAdapter適配器,就要使用HttpRequestHandlerAdapter適配器的規則進行處理
/**
*
* <p>Title: Hello1</p>
* <p>Description: 使用HttpRequestHandlerAdapter</p>
* <p>Company: www.itcast.com</p>
* @version 1.0
*/
public class Hello1 implements HttpRequestHandler {
@Override
public void handleRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//向頁面顯示一行提示信息
String message = "hellworld1";
request.setAttribute("message", message);
//指定轉向頁面,使用request指定頁面完整路徑
request.getRequestDispatcher("/WEB-INF/jsp/hello.jsp").forward(request, response);
}
}
3、視圖解析器
<!-- 視圖解析器 解析jsp視圖,默認使用jstl,要求classpath下有jstl的jar包 -->
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 視圖的前綴 -->
<property name="prefix" value="/WEB-INF/jsp/" />
<!-- 視圖的後綴 -->
<property name="suffix" value=".jsp" />
</bean>
這樣使用視圖解析器,就可以在controller層直接使用邏輯視圖名稱進行頁面的響應:
modelAndView.setViewName("hello");
這裏可以參考git倉庫資源中的源碼:點擊打開鏈接
5、針對springMVC在平常的開發中註解使用如下:
1、@controller
標識該類爲控制器類,@controller、@service、@repository分別對應了web應用三層架構的組件即控制器、服務接口、數據訪問接口
2、 @RequestMapping
進行url映射,一個方法對應一個url,定義方法:在action方法上定義requestMapping
3、在平常的開發中會使用 根路徑+子路徑 來辨別action的URL
4、 URI模板模式映射
(使用url的模板式映射的思想是:讓每一條資源數據都有唯一的一個URL路徑)
5、請求方法限定
可以限定爲get、post、或兩者都可以
限定GET方法
@RequestMapping(method = RequestMethod.GET)
如果通過Post訪問則報錯:
HTTP Status 405 - Request method 'POST' not supported
例如:
@RequestMapping(value="/useredit/{userid}",method=RequestMethod.GET)
限定POST方法
@RequestMapping(method = RequestMethod.POST)
如果通過Post訪問則報錯:
HTTP Status 405 - Request method 'GET' not supported
GET和POST都可以
@RequestMapping(method={RequestMethod.GET,RequestMethod.POST})
6、springMVC的請求參數綁定(重點)
這裏請求的參數綁定在handler處理器的形式參數中(Springmvc通過參數解析器,將客戶端請求的key/value解析成方法形參數);參數解析器:
Spring提供了很多參數解析器,將key/value的數據解析成形參,通過反射解析method中的參數(類型、名稱),按照類型和名稱規則解析形參;
屬性編輯器:
將key/value轉換成pojo中的屬性
6.1 默認支持的參數類型
- HttpServletRequest
- 通過request對象獲取請求信息
- HttpServletResponse
- 通過response處理響應信息
- HttpSession
- 通過session對象得到session中存放的對象
- Model
- 通過model向頁面傳遞數據,如下:
- model.addAttribute("user",new User("李四"));
- model也可以通過modelMap或map將數據傳到頁面。
6.2 表單對象-簡單數據類型
Action方法的形參數默認支持:string、int、double等簡單類型,建議使用包裝類型(可以設置null)。
注意:對於date類型的參數需要註冊屬性編輯器。
使用方法:
直接在形參上定義
也可以在pojo中通過屬性傳遞簡單類型
6.3表單對象-pojo類型
第一種,不需要封裝目標bean
6.4 字符串數組綁定
6.5、 List綁定參數類型
頁面向action傳遞複雜的批量數據,比如學生的成績信息(課程名稱、成績)
頁面定義:
Scores:包裝對象中list屬性的名稱
Coursename:包裝對象中list中pojo的屬性名稱。
Score:包裝對象中list中pojo的屬性名稱。
如果上邊下標相同的Coursename和Score設置在一個pojo中。
Action方法定義:
使用List<pojo>接收上邊的接收,pojo中包括上邊課程名稱(coursename)和成績(score)
6.6、 @RequestParam綁定單個請求參數
value:參數名字,即入參的請求參數名字,如value=“studentid”表示請求的參數區中的名字爲studentid的參數的值將傳入;
required:是否必須,默認是true,表示請求中一定要有相應的參數,否則將報400錯誤碼;
defaultValue:默認值,表示如果請求中沒有同名參數時的默認值
需求 :
學生查詢方法中必須要有一個參數group(學生分組)
實現:
7、 springMVC中結果轉發
Redirect:請求重定向
瀏覽器中地址欄的url通過Redirect變了,重新定義了一個request。
Action方法通過Redirect重定向到另一個方法,方法形參無法帶到另一個方法。
定義方法:
//請求重定向
return "redirect:querystudent.action";
Forward:頁面轉發
瀏覽器中地址欄的url通過Forward不變,沒有重新定義了一個request。
Action方法通過Forward轉發到另一個方法,方法形參可以帶到另一個方法。
定義方法:
//頁面轉發
return "forward:querystudent.action";
8、springMVC中 @RequestBody @ResponseBody註解實現json數據交互
Json數據在企業中使用好處:
Json在企業開發中已經作爲通用的接口參數類型。
Json數據在頁面(客戶端)解析很方便。
Json定義:
var obj={”name”:”張三”,”age”:12}//key/value格式
Json數據解析:
obj.name
在處理器適配器上配置json的解析器,原因是處理器適配器處理handler
配置
<!--註解適配器 -->
<!-- <bean
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
json轉換器
<property name="messageConverters">
<list>
<bean
class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean>
</list>
</property>
</bean> -->
controller層
/**
*
* <p>Title: JsonAction</p>
* <p>Description: json轉換測試</p>
* <p>Company: www.itcast.com</p>
* @author 傳智.燕青
* @date 2014-12-15下午5:38:43
* @version 1.0
*/
@Controller
public class JsonAction {
//請求json響應json
@RequestMapping("/requestJson")
public @ResponseBody Student requestJson(@RequestBody Student student)throws Exception{
System.out.println(student);
return student;
}
//請求key/value響應json
@RequestMapping("/responseJson")
public @ResponseBody Student responseJson(Student student)throws Exception{
System.out.println(student);
return student;
}
}
9、springMVC的攔截器
攔截器是針對handlerMapping的攔截器,由handlerMapping查找Handler後,將攔截器返回給前端控制器(DispatcherServlet)。
間接配置全局攔截器:讓springmvc框架自動向每個handlerMapping中註冊攔截器
<!--攔截器 -->
<mvc:interceptors>
<!--多個攔截器,順序執行 -->
<!-- <mvc:interceptor>
<mvc:mapping path="/**" />
<bean class="cn.itcast.springmvc.interceptor.HandlerInterceptor1"></bean>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**" />
<bean class="cn.itcast.springmvc.interceptor.HandlerInterceptor2"></bean>
</mvc:interceptor> -->
<mvc:interceptor>
<mvc:mapping path="/**" />
<bean class="cn.itcast.springmvc.interceptor.LoginInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
定義攔截器
實現HandlerInterceptor接口。
public class HandlerInterceptor1 implements HandlerInterceptor {
//handler,springmvc根據url找到Handler(只有一個方法)
//執行時機:進入Handler方法之前執行,如果返回false表示攔截,如果返回true表示放行
//使用場景:用於用戶身份校驗,用戶權限攔截校驗
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
System.out.println("HandlerInterceptor1..preHandle");
return false;
}
//執行時機:進入Handler方法之後 ,在返回modelAndView之前
//使用場景:使用modelAndView,向頁面傳遞通用數據,使用統一的view
@Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("HandlerInterceptor1..postHandle");
}
//執行時機:Handler方法執行完成,(modelAndView已經返回)
//使用場景:統一異常處理,統一記錄系統日誌,用於action方法執行監控(在preHandle記錄一個時間點,在afterCompletion記錄執行結束時間點,將結束時間點減去開始執行時間點,得到執行時長)
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex)
throws Exception {
System.out.println("HandlerInterceptor1..afterCompletion");
}
10、springmvc驅動
<!--註解映射器 -->
<!-- <bean
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping" /> -->
<!--註解適配器 -->
<!-- <bean
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
json轉換器
<property name="messageConverters">
<list>
<bean
class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean>
</list>
</property>
</bean> -->
<!-- 使用<mvc:annotation-driven />替換上邊定義的處理器映射器和適配器 並且默認是支持@RequestBody @ResponseBody這兩個註解的--> <mvc:annotation-driven />
參考代碼案例:點擊打開鏈接