SpringMVC介紹
Spring web mvc 和Struts2都屬于表現層的框架,它是Spring框架的一部分
SpringMVC處理流程
入門程序
創建工程
導入jar包
在web.xml中配置前端控制器DispatcherServlet
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>
</web-app>
在上面的url-pattern中攔截規則有如下:
- /* 表示攔截所有 jsp js png .css 會全部攔截
- *.action *.do 攔截以do action 結尾的請求
- / 攔截所有(不包括jsp) 包含 .js .png .css
創建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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!--配置controller掃描包-->
<context:component-scan base-package="cn.probuing.springmvc.controller"/>
</beans>
創建pojo
public class Item {
// 商品id
private int id;
// 商品名稱
private String name;
// 商品價格
private double price;
// 商品創建時間
private Date createtime;
// 商品描述
private String detail;
創建帶參數的構造器
set/get。。。
}
創建ItemController
ItemController是一個普通的java類,不需要實現任何接口
需要再類上添加@Controller注解,將Controller交由Spring管理
在方法上面添加@RequestMapping注解 里面指定請求的url
@RequestMapping("/itemList.action")
public ModelAndView queryItemList() {
// 創建頁面需要顯示的商品數據
// 創建頁面需要顯示的商品數據
List<Items> list = new ArrayList<>();
list.add(new Items(1, "1華為 榮耀8", 2399f, new Date(), "質量好!1"));
list.add(new Items(2, "2華為 榮耀8", 2399f, new Date(), "質量好!2"));
list.add(new Items(3, "3華為 榮耀8", 2399f, new Date(), "質量好!3"));
list.add(new Items(4, "4華為 榮耀8", 2399f, new Date(), "質量好!4"));
list.add(new Items(5, "5華為 榮耀8", 2399f, new Date(), "質量好!5"));
list.add(new Items(6, "6華為 榮耀8", 2399f, new Date(), "質量好!6"));
//創建modelandview 模型視圖對象
ModelAndView mav = new ModelAndView();
//設置視圖跳轉名稱
mav.setViewName("WEB-INF/jsp/itemList.jsp");
//設置model數據
mav.addObject("itemList", list);
return mav;
}
啟動測試
SpringMVC架構
框架結構
組件說明
以下組件通常由SpringMVC提供實現
前端控制器 DispatcherServlet
用戶請求到達前端控制器,它就相當于MVC模式中的C,dispatcherServlet是整個流程控制的中心,由它調用其它組件處理用戶的請求,DispathcerServlet的存在降低了各個組件之間的耦合性
處理器映射器 HandlerMapping
HandlerMapping負責根據用戶請求url找到Handler(處理器)springmvc提供了不同的映射器實現不同的映射方式。
Handler處理器
Handler是繼DispathcerServlet前端控制器的后端控制器,在DispathcerServlet的控制下Handler對具體的用戶請求進行處理 由于Handler涉及到具體的用戶業務請求,所以一般情況需要自己開發Handler
HandlerAdapter 處理器適配器
通過HandlerAdapter對處理器進行執行,這是適配器模式的應用,通過擴展適配器可以對更對類型的處理器進行執行
ViewResolver 視圖解析器
ViewResolver 負責將處理結果生成View視圖,ViewResolver首先根據邏輯視圖名解析成物理視圖名即具體的頁面地址,再生成View視圖對象,最后對View進行渲染將處理結果通過頁面展示給客戶
View視圖
springmvc框架提供了很多View視圖類型的支持,包括:jstlView、freemarkerView、pdfView等
說明
在SpringMVC的各個組件中,處理器映射器,處理器適配器、視圖解析器稱為SpringMVC的三大組件
需要用戶開發的組件是:Handler View
注解映射器和適配器
配置處理器映射器
注解式處理器映射器,對類中標記了@ResquestMapping的方法進行映射。根據@RequestMapping定義的url匹配@ResquestMapping標記的方法,匹配成功返回HandlerMethod對象給前端控制器。
HandlerMethod對象中封裝URL對應的方法Method
從Spring3.1開始,廢除了DefaultAnnotationHandlerMapping的使用 拓建使用RequestMappingHandlerMapping完成注解式處理器映射
在springmvc.xml配置文件中配置如下
<!--配置處理器映射器-->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
配置處理器適配器
注解式處理器適配器,對標記@RequestMapping的方法進行適配
從Spring3.1版本開始,廢除了AnnotationMethodHandlerAdapter的使用,推薦使用RequestMappingHandlerAdapter完成注解式適配器適配
在springmvc.xml配置文件中配置如下
<!--配置處理器適配器-->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>
注解驅動
直接配置處理器映射器和處理器適配器比較麻煩,可以使用注解驅動來加載 SpringMVC使用 <mvc:annotation-driven>自動加載RequestMappingHandlerMapping和RequestMappingHandlerAdapter
可以在springmvc.xml配置文件中使用<mvc:annotation-driven>替代注解處理器和適配器的設置
<mvc:annotation-driven/>
視圖解析器
視圖解析器使用SpringMVC框架默認的InternalResourceViewResolver,這個視圖解析器支持JSP視圖解析
在springmvc.xml配置文件中配置如下
<!--視圖解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--配置邏輯視圖前綴-->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!--配置邏輯視圖后綴-->
<property name="suffix" value=".jsp"/>
</bean>
修改ItemController
// @RequestMapping:里面放的是請求的url,和用戶請求的url進行匹配
// action可以寫也可以不寫
@RequestMapping("/itemList.action")
public ModelAndView queryItemList() {
// 創建頁面需要顯示的商品數據
List<Item> list = new ArrayList<>();
list.add(new Item(1, "1華為 榮耀8", 2399, new Date(), "質量好!1"));
list.add(new Item(2, "2華為 榮耀8", 2399, new Date(), "質量好!2"));
list.add(new Item(3, "3華為 榮耀8", 2399, new Date(), "質量好!3"));
list.add(new Item(4, "4華為 榮耀8", 2399, new Date(), "質量好!4"));
list.add(new Item(5, "5華為 榮耀8", 2399, new Date(), "質量好!5"));
list.add(new Item(6, "6華為 榮耀8", 2399, new Date(), "質量好!6"));
// 創建ModelAndView,用來存放數據和視圖
ModelAndView modelAndView = new ModelAndView();
// 設置數據到模型中
modelAndView.addObject("itemList", list);
// 設置視圖jsp,需要設置視圖的物理地址
// modelAndView.setViewName("/WEB-INF/jsp/itemList.jsp");
// 配置好視圖解析器前綴和后綴,這里只需要設置邏輯視圖就可以了。
// 視圖解析器根據前綴+邏輯視圖名+后綴拼接出來物理路徑
modelAndView.setViewName("itemList");
return modelAndView;
}
整合mybatis
整合目標:控制層采用SpringMVC 持久層采用mybatis
導入jar包
創建數據庫配置文件db.properties
- db.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://140.210.70.23:3306/springmvc?characterEncoding=utf-8
jdbc.username=appUser
jdbc.password=AA1122BB
web.xml
- 在web.xml加入Spring監聽器 ContextLoaderListener 并指定Spring配置文件
- web.xml文件中配置SpringMVC的前端控制器
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--指定配置文件-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!--spring mvc 前端控制器-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--指定SpringMVC配置文件-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>
</web-app>
springmvc.xml
- 在springmvc中配置controller掃描包
- 視圖解析器
- 注解驅動
<?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:p="http://www.springframework.org/schema/p"
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/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">
<!--配置controller掃描包-->
<context:component-scan base-package="cn.probuing.springmvc.controller"/>
<!--配置處理器映射器-->
<!--<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>-->
<!--配置處理器適配器-->
<!--<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>-->
<!--注解驅動-->
<mvc:annotation-driven/>
<!--視圖解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--配置邏輯視圖前綴-->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!--配置邏輯視圖后綴-->
<property name="suffix" value=".jsp"/>
</bean>
</beans>
applicationContext.xml
- spring配置文件中配置 數據庫文件,連接池
- 配置mybatis的工廠并指定核心配置文件的位置
- 指定mapper動態代理開發的掃描
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-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">
<context:property-placeholder location="classpath:db.properties"/>
<!-- 數據庫連接池 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="maxActive" value="10"/>
<property name="maxIdle" value="5"/>
</bean>
<!-- Mybatis的工廠 -->
<bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!-- 核心配置文件的位置 -->
<property name="configLocation" value="classpath:SqlMapConfig.xml"/>
</bean>
<!-- Mapper動態代理開發 掃描 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 基本包 -->
<property name="basePackage" value="cn.probuing.springmvc.dao"/>
</bean>
</beans>
參數綁定
在開發中 需要從請求的參數中把請求的id取出來
id包含在Request對象中,可以從Request對象中取id
想獲得Request對象需要再Controller方法的形參中添加一個參數即可。Springmvc框架會自動把Request對象傳遞給方法
jsp頁面
<td><a href="${pageContext.request.contextPath }/itemEdit.action?id=${item.id}">修改</a></td>
Controller
/**
* 通過id查詢商品
*
* @param request
* @return
*/
@RequestMapping("/itemEdit")
public ModelAndView queryItemById(HttpServletRequest request) {
String strId = request.getParameter("id");
Items items = itemService.queryItemById(Integer.valueOf(strId));
//傳遞結果回頁面
ModelAndView mva = new ModelAndView();
mva.setViewName("editItem");
//設置數據
mva.addObject("item", items);
return mva;
}
默認支持的參數類型
處理器形參中添加如下類型的參數處理適配器會默認識別并進行賦值
- HttpServletRequest 通過request對象獲取請求信息
- HttpServletResponse 通過response處理響應信息
- HttpSession 通過session對象得到session中存放的對象
Model/ModelMap
Model
除了ModelAndView之外,還可以使用Model來向頁面傳遞數據
Model是一個接口,在參數里直接聲明model即可
如果使用Model則可以不適用ModelAndView對象,Model對象可以向頁面傳遞數據View對象則可以使用String返回值替代
不管是Model還是ModelAndView其本質都是使用Request對象向jsp傳遞數據
/**
* 根據id查詢商品,使用Model
*
* @param request
* @param model
* @return
*/
@RequestMapping("/itemEdit")
public String queryItemById(HttpServletRequest request, Model model) {
// 從request中獲取請求參數
String strId = request.getParameter("id");
Integer id = Integer.valueOf(strId);
// 根據id查詢商品數據
Item item = this.itemService.queryItemById(id);
// 把結果傳遞給頁面
// ModelAndView modelAndView = new ModelAndView();
// 把商品數據放在模型中
// modelAndView.addObject("item", item);
// 設置邏輯視圖
// modelAndView.setViewName("itemEdit");
// 把商品數據放在模型中
model.addAttribute("item", item);
return "itemEdit";
}
ModelMap
ModelMap是Model接口的實現類,也可以通過ModelMap向頁面傳遞數據。
使用Model和ModelMap的效果一樣,如果直接使用Model,springmvc會實例化ModelMap
* @param request
* @param model
* @return
*/
@RequestMapping("/itemEdit")
public String queryItemById(HttpServletRequest request, ModelMap model) {
// 從request中獲取請求參數
String strId = request.getParameter("id");
Integer id = Integer.valueOf(strId);
// 根據id查詢商品數據
Item item = this.itemService.queryItemById(id);
// 把結果傳遞給頁面
// ModelAndView modelAndView = new ModelAndView();
// 把商品數據放在模型中
// modelAndView.addObject("item", item);
// 設置邏輯視圖
// modelAndView.setViewName("itemEdit");
// 把商品數據放在模型中
model.addAttribute("item", item);
return "itemEdit";
}
綁定簡單類型
當請求的參數名稱和處理器形參名稱一致時會將請求參數與形參進行綁定。這樣從Request取參數的方法就可以進一步簡化
/**
* 根據id查詢商品,綁定簡單數據類型
*
* @param id
* @param model
* @return
*/
@RequestMapping("/itemEdit")
public String queryItemById(int id, ModelMap model) {
// 根據id查詢商品數據
Item item = this.itemService.queryItemById(id);
// 把商品數據放在模型中
model.addAttribute("item", item);
return "itemEdit";
}
支持綁定的數據類型
參數類型推薦使用包裝數據類型,因為基礎數據類型不可以為null
整形:Integer、int
字符串:String
單精度:Float、float
雙精度:Double、double
布爾型:Boolean、boolean
說明:對于布爾類型的參數,請求的參數值為true或false?;蛘?或0
請求url:
http://localhost:8080/xxx.action?id=2&status=false
處理器方法:
public String editItem(Model model,Integer id,Boolean status)
@RequestParam
使用@RequestParam常用于處理簡單類型的綁定
- value 參數名字,即入參的請求參數名字
required 是否必須 默認是true 表示請求中一定要有響應的參數 否則報錯
default 默認值,表示如果請求中沒有同名參數時的默認值
@RequestMapping("/itemEdit")
public String queryItemById(@RequestParam(value = "itemId", required = true, defaultValue = "1") Integer id,
ModelMap modelMap) {
// 根據id查詢商品數據
Item item = this.itemService.queryItemById(id);
// 把商品數據放在模型中
modelMap.addAttribute("item", item);
return "itemEdit";
}
綁定POJO類型
如果提交的參數很多,或者提交的表單中的內容很多的時候,可以使用簡單類型接受數據,也可以使用pojo接收數據。
- 要求:pojo對象中的屬性名和表單中的input的name屬性一致
Controller
@RequestMapping(value = "/updateitem.action")
public String updateitem(Items items) {
itemService.updateItemsById(items);
return "success";
}
- 處理亂碼問題
加入過濾器
<!--編碼過濾器-->
<filter>
<filter-name>encoding</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>*.action</url-pattern>
</filter-mapping>
綁定包裝POJO
創建包裝的POJO QueryVo
package cn.probuing.springmvc.pojo;
/**
* @Auther: wxblack-mac
* @Date: 2018/8/28 17:45
* @Description:
*/
public class QueryVo {
private Items items;
public Items getItems() {
return items;
}
public void setItems(Items items) {
this.items = items;
}
}
jsp頁面
<!-- <form id="itemForm" action="" method="post" enctype="multipart/form-data"> -->
<form id="itemForm" action="${pageContext.request.contextPath }/updateitem.action" method="post">
<input type="hidden" name="items.id" value="${item.id }" /> 修改商品信息:
<table width="100%" border=1>
<tr>
<td>商品名稱</td>
<td><input type="text" name="items.name" value="${item.name }" /></td>
</tr>
<tr>
<td>商品價格</td>
<td><input type="text" name="items.price" value="${item.price }" /></td>
</tr>
自定義參數綁定
有時候參數無法被springmvc轉換,我們需要自定義轉換參數
自定義Converter 實現Converter接口 泛型為 源類型和轉換后的類型
/**
* @Auther: wxblack-mac
* @Date: 2018/8/28 19:05
* DataConverter
* S:需要轉換的源的類型
* T:需要轉換的目標類型
*/
public class DataConverter implements Converter<String, Date> {
@Override
public Date convert(String s) {
//轉換s
try {
SimpleDateFormat sdf = new SimpleDateFormat("yyy-MM-dd HH:mm:ss");
Date date = sdf.parse(s);
return date;
} catch (ParseException e) {
return null;
}
}
}
配置轉換器Converter
在springmvc.xml文件中
<!--配置轉換器工廠bean-->
<bean id="conversionservicefactorybean"
class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<!--配置轉換器-->
<property name="converters">
<list>
<!--指定自定義轉換器實現類-->
<bean class="cn.probuing.springmvc.converters.DataConverter"/>
</list>
</property>
</bean>
高級參數綁定
數組參數
@RequestMapping(value = "deletes.action")
public String deletes(Integer[] ids) {
for (Integer id : ids) {
System.out.println(id+"111");
}
return "success";
}
集合參數
<c:forEach items="${itemList }" var="item" varStatus="s">
<tr>
<td><input type="checkbox" name="ids" value="${item.id}"/></td>
<td>
<input type="hidden" name="itemList[${s.index}].id" value="${item.id }"/>
<input type="text" name="itemList[${s.index}].name" value="${item.name }"/>
</td>
<td><input type="text" name="itemList[${s.index}].price" value="${item.price }"/></td>
<td><input type="text" name="itemList[${s.index}].createtime" value="<fmt:formatDate value="${item.createtime}" pattern="yyyy-MM-dd HH:mm:ss"/>"/></td>
<td><input type="text" name="itemList[${s.index}].detail" value="${item.detail }"/></td>
<td><a href="${pageContext.request.contextPath }/itemEdit.action?id=${item.id}">修改</a></td>
</tr>
</c:forEach>
SpringMVC和Struts2區別
- 1、SpringMVC的入口是一個Servlet即前端控制器。而Struts2入口是一個filter過濾器
- 2、SpringMVC請求參數傳遞到方法的形參,Struts2傳遞參數是通過類的屬性
- 3、SpringMVC是基于方法開發(一個url對應一個方法),可以設計成單例或者多例
- 4、Struts采用值棧存儲請求和響應數據,通過OGNL存儲數據 SpringMVC通過參數計息期將request請求內容解析,并給方法形參賦值,將數據和視圖封裝成ModelAndView對象,最后又將ModelAndView中的模型數據通過request域傳輸到頁面,jsp視圖解析器默認使用jstl
@RequestMapping
通過@RequestMapping注解可以定義不同的處理器映射規則
URL路徑映射
@RequestMapping(value="item")或者 @RequestMapping("/item")
value是一個數組,可以將多個url映射到同一個方法
/**
* 查詢商品列表
* @return
*/
@RequestMapping(value = { "itemList", "itemListAll" })
public ModelAndView queryItemList() {
// 查詢商品數據
List<Item> list = this.itemService.queryItemList();
// 創建ModelAndView,設置邏輯視圖名
ModelAndView mv = new ModelAndView("itemList");
// 把商品數據放到模型中
mv.addObject("itemList", list);
return mv;
}
添加到類上 窄化路徑
對于重復的父路徑可以使用URL放在類上可以指定簡化的類路徑
//@RequestMapping("item")
public class ItemController {
請求方法限定
method={RequestMethod.POST,RequestMethod.GET} 指定請求方式
- 限定GET方法
@RequestMapping(method = RequestMethod.GET)
- 限定POST方法
@RequestMapping(method = RequestMethod.POST)
Controller方法返回值
返回ModelAndView
controller 方法中定義ModelAndView對象并返回,對象中可添加moedel數據,指定View
返回void
在Controller方法形參上可以定義request和response
適合json 和 ajax請求時的方式
/**
* 返回void測試
*
* @param request
* @param response
* @throws Exception
*/
@RequestMapping("queryItem")
public void queryItem(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 1 使用request進行轉發
// request.getRequestDispatcher("/WEB-INF/jsp/success.jsp").forward(request,
// response);
// 2 使用response進行重定向到編輯頁面
// response.sendRedirect("/springmvc-web2/itemEdit.action");
// 3 使用response直接顯示
response.getWriter().print("{\"abc\":123}");
}
返回字符串
邏輯視圖名
controller 方法返回字符串可以指定邏輯視圖名,通過視圖解析為物理視圖地址
Redirect重定向
Controller方法返回字符串可以重定向到一個url地址
/**
* 更新商品
*
* @param item
* @return
*/
@RequestMapping("updateItem")
public String updateItemById(Item item) {
// 更新商品
this.itemService.updateItemById(item);
// 修改商品成功后,重定向到商品編輯頁面
// 重定向后瀏覽器地址欄變更為重定向的地址,
// 重定向相當于執行了新的request和response,所以之前的請求參數都會丟失
// 如果要指定請求參數,需要在重定向的url后面添加 ?itemId=1 這樣的請求參數
return "redirect:/itemEdit.action?itemId=" + item.getId();
}
forward轉發
Controllrer方法執行后繼續執行另一個Controller方法
/**
* 更新商品
*
* @param item
* @return
*/
@RequestMapping("updateItem")
public String updateItemById(Item item) {
// 更新商品
this.itemService.updateItemById(item);
// 修改商品成功后,重定向到商品編輯頁面
// 重定向后瀏覽器地址欄變更為重定向的地址,
// 重定向相當于執行了新的request和response,所以之前的請求參數都會丟失
// 如果要指定請求參數,需要在重定向的url后面添加 ?itemId=1 這樣的請求參數
// return "redirect:/itemEdit.action?itemId=" + item.getId();
// 修改商品成功后,繼續執行另一個方法
// 使用轉發的方式實現。轉發后瀏覽器地址欄還是原來的請求地址,
// 轉發并沒有執行新的request和response,所以之前的請求參數都存在
return "forward:/itemEdit.action";
}
異常處理器
Springmvc在處理請求過程中出現異常信息交由異常處理器進行處理,自定義異常處理器可以實現一個系統的異常處理邏輯
異常處理思路
系統中異常包括兩類:預期異常和運行時異常,前者通過捕獲異常從而獲取異常信息,后者主要通過規范代碼開發、測試通過手段減少運行時異常發生
異常處理器自定義實現類
實現HandlerExceptionResolver接口
/**
* @Auther: wxblack-mac
* @Date: 2018/8/30 14:50
* @Description:
*/
public class MyExceptionHandler implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
System.out.println(o);
ModelAndView mav = new ModelAndView();
mav.addObject("error", "未知異常");
mav.setViewName("error");
return mav;
}
}
方法形參中:httpServletRequest 請求對象 httpServletResponse 響應對象
Object o:異常信息封裝 包名+類名+方法名
Exception e:異常對象
返回的ModelAndView 可以指定視圖和數據
配置異常處理
<!--自定義異常處理-->
<bean class="cn.probuing.springmvc.exceptionhandler.MyExceptionHandler"/>
上傳圖片
加入上傳圖片的jar包
配置文件上傳解析器
- 文件上傳解析器 id必須設置為multipartResolver
<!--配置文件文件上傳解析器-->
<bean class="org.springframework.web.multipart.commons.CommonsMultipartResolver" id="commonsMultipartResolver">
<!--設置文件大小-->
<property name="maxUploadSize" value="5000000"/>
</bean>
jsp頁面
<form id="itemForm" action="{item.id }"/> 修改商品信息:
<table width="100%" border=1>
<tr>
<td>商品名稱</td>
<td><input type="text" name="items.name" value="{item.price }"/></td>
</tr>
<tr>
<td>商品生產日期</td>
<td><input type="text" name="items.createtime"
value="<fmt:formatDate value="${item.createtime}" pattern="yyyy-MM-dd HH:mm:ss"/>"/></td>
</tr>
<tr>
<td>商品圖片</td>
<td>
<c:if test="${item.pic !=null}">
<img src="/pic/${item.pic}" width=100 height=100/>
<br/>
</c:if>
<input type="file" name="pictureFile"/>
</td>
</tr>
<%--
--%>
<tr>
<td>商品簡介</td>
<td><textarea rows="3" cols="30" name="items.detail">${item.detail }</textarea>
</td>
</tr>
<tr>
<td colspan="2" align="center"><input type="submit" value="提交"/>
</td>
</tr>
</table>
</form>
java代碼
方法接收時,圖片形參的名字必須要和jsp頁面 傳遞的圖片的name一致
@RequestMapping(value = "/updateitem.action")
public String updateitem(QueryVo vo, MultipartFile pictureFile) throws IOException {
//創建圖片名稱
String picName = UUID.randomUUID().toString().replaceAll("-", "");
//獲取文件名
String oriName = pictureFile.getOriginalFilename();
//獲取圖片后綴
String ext = FilenameUtils.getExtension(oriName);
//保存圖片
pictureFile.transferTo(new File("/Users/wxblack-mac/pic/" + picName + "." + ext));
//保存數據庫
vo.getItems().setPic(picName + "." + ext);
itemService.updateItemsById(vo.getItems());
return "redirect:/itemEdit.action?id=" + vo.getItems().getId();
}
JSON數據交互
@RequestBody
@RequestBody注解用于讀取http請求的內容,通過springmvc提供的HttpMessageConverter接口將讀取到的內容轉換為java對象并綁定到Controller方法的參數上
@ResponseBody
@ReponseBody注解用于將Controller的方法返回的對象,通過SpringMVC提供的HttpMessageConverter接口轉換為指定格式的數據。通過Response響應到客戶端
加入jar包
Controller
@RequestMapping(value = "/json.action")
public @ResponseBody
Items json(@RequestBody Items items) {
return items;
}
JS發送Json數據
$(function () {
var params = '{"id": 1,"name": "測試商品","price": 99.9,"detail": "測試商品描述","pic": "123456.jpg"}';
alert(params);
$.ajax({
url: "${pageContext.request.contextPath}/json.action",
data: params,
contentType: "application/json;charset=UTF-8",
type: "post",
dataType: "json",
success: function (data) {
alert(data.name);
}
});
});
配置Json轉換器
如果不適用注解驅動,就需要給處理器適配器配置json轉換器
在springmvc.xml配置文件中,給處理器適配器加入json轉換器
<!--處理器適配器 -->
<bean class=*"org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"*>
<property name=*"messageConverters"*>
<list>
<bean class=*"org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"*></bean>
</list>
</property>
</bean>
RESTful支持
什么是restful?
Restful就是一個資源定位及資源操作的風格。不是標準也不是協議,只是一種風格?;谶@個風格設計的軟件可以更簡潔,更有層次,更易于實現緩存等機制
傳統方式操作資源
http://127.0.0.1/item/queryItem.action?id=1 查詢,GET
http://127.0.0.1/item/saveItem.action 新增,POST
http://127.0.0.1/item/updateItem.action 更新,POST
http://127.0.0.1/item/deleteItem.action?id=1 刪除,GET或POST
使用RESTful操作資源
http://127.0.0.1/item/1 查詢,GET
http://127.0.0.1/item 新增,POST
http://127.0.0.1/item 更新,PUT
http://127.0.0.1/item/1 刪除,DELETE
測試
- 首先我們指定參數注入在地址中,在地址中的參數使用{}包裹并使用@PathVariable指定地址中的參數,對應到方法的形參中
/**
* 通過id查詢商品
*
* @return
*/
@RequestMapping("/itemEdit/{id}.html")
public ModelAndView queryItemByIdRestFul(@PathVariable Integer id) {
Items items = itemService.queryItemById(id);
//傳遞結果回頁面
ModelAndView mva = new ModelAndView();
mva.setViewName("editItem");
//設置數據
mva.addObject("item", items);
return mva;
}
-
訪問
訪問地址
攔截器
定義
SpringMVC 的處理器攔截器類似于Servlet開發中的過濾器Filter,用于對處理器進行預處理和后處理
public class HandlerInterceptor1 implements HandlerInterceptor {
// controller執行后且視圖返回后調用此方法
// 這里可得到執行controller時的異常信息
// 這里可記錄操作日志
@Override
public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
System.out.println("HandlerInterceptor1....afterCompletion");
}
// controller執行后但未返回視圖前調用此方法
// 這里可在返回用戶前對模型數據進行加工處理,比如這里加入公用信息以便頁面顯示
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
throws Exception {
System.out.println("HandlerInterceptor1....postHandle");
}
// Controller執行前調用此方法
// 返回true表示繼續執行,返回false中止執行
// 這里可以加入登錄校驗、權限攔截等
@Override
public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
System.out.println("HandlerInterceptor1....preHandle");
// 設置為true,測試使用
return true;
}
}
攔截器定義 springmvc.xml
<!-- 配置攔截器 -->
<mvc:interceptors>
<mvc:interceptor>
<!-- 所有的請求都進入攔截器 -->
<mvc:mapping path="/**" />
<!-- 配置具體的攔截器 -->
<bean class="cn.itcast.ssm.interceptor.HandlerInterceptor1" />
</mvc:interceptor>
<mvc:interceptor>
<!-- 所有的請求都進入攔截器 -->
<mvc:mapping path="/**" />
<!-- 配置具體的攔截器 -->
<bean class="cn.itcast.ssm.interceptor.HandlerInterceptor2" />
</mvc:interceptor>
</mvc:interceptors>
多個攔截器調用總結
按照配置執行后,我們可以看到 preHandler方法返回false后第一個攔截器只執行了preHandler方法,其他的兩個方法沒有執行,第二個攔截器的所有方法不執行,且Controller也不執行了
HandlerInterceptor1的preHandler方法返回true HandlerInterceptor2返回false時,我們可以看到第二個攔截器的preHandler方法返回false后第一個攔截器的postHandler沒有執行,第二個攔截器的postHandler和afterCompletion沒有執行,且controller也不執行了
preHandler按攔截器定義的順序調用
postHandler按攔截器定義的順序逆序調用
afterCompletion按攔截器定義順序逆序調用
postHandler在攔截器鏈內所有攔截器返回成功調用,在多個攔截器時,只有所有攔截器的preHandler返回成功時 才會執行postHandler方法
afterCompletion只有preHandle 返回true才調用 在多個攔截器時,只要當前