SpringMVC
01.SpringMVC架構
關於DispatcherServlet源碼實現原理我參考了:http://blog.csdn.net/congcong68/article/details/40451233
02.spring入門程序
程序執行步驟:
Tomcat啓動-->加載web.xml-->加載web.xml中的servlet-->加載SpringMvc.xml配置文件-->
SpringMvc.xml(名稱不固定)裏面有:
<context:component-scan base-package="com.my.controller"></context:component-scan>
-->就會掃描這個包裏面的所有類,然後就會加載含有@Controller註解的類,並將其加載到內存中變成對象
代碼
Web.xml
<!-- springMVC前端控制器 --> <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> <!-- tomcat啓動的時候加載這個servlet,第一個啓動 --> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springMvc</servlet-name> <url-pattern>*.action</url-pattern> </servlet-mapping> </web-app>
SpringMvc.xml:裏面有組件的配置信息
SpringMVC三大組件:
l 處理映射器:制定url到指定方法的映射
l 處理器適配器:根據不同的Handler找到不同的處理器適配器去執行Handler
l 視圖解析器:根據不同的視圖去解析(視圖可以是jsp、pdf、word、freeMark)
<?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:dubbo="http://code.alibabatech.com/schema/dubbo" 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://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <!-- 配置@Controller註解掃描 --> <context:component-scan base-package="com.my.controller"></context:component-scan> <!-- 如果沒有顯示的配置處理器映射器和處理器適配那麼springMvc會去默認的dispatcherServlet.properties中查找, 對應的處理器映射器和處理器適配器去使用,這樣每個請求都要掃描一次他的默認配置文件,效率非常低,會降低訪問速度,所以要顯示的配置處理器映射器和 處理器適配器 --> <!-- 註解形式的處理器映射器 --> <!-- <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"></bean> --> <!-- 註解形式的處理器適配器 --> <!-- <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"></bean> --> <!-- 配置最新版的註解的處理器映射器 --> <!-- <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"></bean> --> <!-- 配置最新版的註解的處理器適配器 --> <!-- <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"></bean> --> <!-- 註解驅動:(與註解無關) 作用:替我們自動配置最新版的註解的處理器映射器和處理器適配器 --> <mvc:annotation-driven></mvc:annotation-driven> <!-- 配置視圖解析器 作用:在controller中指定頁面路徑的時候就不用寫頁面的完整路徑名稱了,可以直接寫頁面去掉擴展名的名稱 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!-- 真正的頁面路徑 = 前綴 + 去掉後綴名的頁面名稱 + 後綴 --> <!-- 前綴 --> <property name="prefix" value="/WEB-INF/jsp/"></property> <!-- 後綴 --> <property name="suffix" value=".jsp"></property> </bean> </beans>
Handler層代碼
@Controller public class ItemsController { //指定URL到請求方法的映射 @RequestMapping("/list") public ModelAndView itemsList() throws Exception{ List<Items> itemList = new ArrayList<Items>(); //商品列表 Items items_1 = new Items(); items_1.setName("聯想筆記本_3"); items_1.setPrice(6000f); items_1.setDetail("ThinkPad T430 聯想筆記本電腦!"); Items items_2 = new Items(); items_2.setName("蘋果手機"); items_2.setPrice(5000f); items_2.setDetail("iphone6蘋果手機!"); itemList.add(items_1); itemList.add(items_2); //模型和視圖 //model模型: 模型對象中存放了返回給頁面的數據 //view視圖: 視圖對象中指定了返回的頁面的位置 ModelAndView modelAndView = new ModelAndView(); //將返回給頁面的數據放入模型和視圖對象中 modelAndView.addObject("itemList", itemList); //指定返回的頁面位置,"itemList"是頁面取數據的變量 modelAndView.setViewName("itemList"); return modelAndView; } }
03.ssm整合(list功能)
1)Dao層
pojo和映射文件以及接口使用逆向工程生成
SqlMapConfig.xml mybatis核心配置文件
ApplicationContext-dao.xml 整合後spring在dao層的配置
數據源
會話工廠
掃描Mapper
2)service層
事務 ApplicationContext-trans.xml
@Service註解掃描 ApplicationContext-service.xml
3)controller層
SpringMvc.xml
註解掃描:掃描@Controller註解
註解驅動:替我們顯示的配置了最新版的處理器映射器和處理器適配器
視圖解析器:顯示的配置是爲了在controller中不用每個方法都寫頁面的全路徑
4)web.xml
springMvc前端控制器配置
spring監聽
04-1.參數綁定
1. 默認支持類型(修改功能,model和request,string和modelview)
Model比request強大一點
String和modelview都行,不過string代碼少一點
注:mapper接口中的方法,如果是單表操作,則已經自動生成;多表操作需手動創建。
@Controller public class ItemsController { @Autowired private ItemsService itmesService; /** * springMvc中默認支持的參數類型:也就是說在controller方法中可以加入這些也可以不加, 加不加看自己需不需要,都行. *HttpServletRequest *HttpServletResponse *HttpSession *Model */ @RequestMapping("/itemEdit") public String itemEdit(HttpServletRequest reuqest, Model model) throws Exception{ String idStr = reuqest.getParameter("id"); Items items = itmesService.findItemsById(Integer.parseInt(idStr)); //Model模型:模型中放入了返回給頁面的數據 //model底層其實就是用的request域來傳遞數據,但是對request域進行了擴展. model.addAttribute("item", items); //如果springMvc方法返回一個簡單的string字符串,那麼springMvc就會認爲這個字符串就是頁面的名稱 return "editItem"; }
@Service public class ItemsServiceImpl implements ItemsService { @Autowired private ItemsMapper itemsMapper; @Override public Items findItemsById(Integer id) throws Exception { Items items = itemsMapper.selectByPrimaryKey(id); return items; }
public interface ItemsMapper { Items selectByPrimaryKey(Integer id);
2. 基本類型和pojo類型
@Controller public class ItemsController { @Autowired private ItemsService itmesService; //springMvc可以直接接收基本數據類型,包括string.spirngMvc可以幫你自動進行類型轉換. //controller方法接收的參數的變量名稱必須要等於頁面上input框的name屬性值 //public String update(Integer id, String name, Float price, String detail) throws Exception{ //spirngMvc可以直接接收pojo類型:要求頁面上input框的name屬性名稱必須等於pojo的屬性名稱 @RequestMapping("/updateitem") public String update(Items items) throws Exception{ itmesService.updateItems(items); return "success"; }
@Service public class ItemsServiceImpl implements ItemsService { @Autowired private ItemsMapper itemsMapper; @Override public void updateItems(Items items) throws Exception { itemsMapper.updateByPrimaryKeyWithBLOBs(items); } }
int updateByPrimaryKeyWithBLOBs(Items record);
3. 接收vo類型
public class QueryVo { //商品對象 private Items items;
@Controller public class ItemsController { @Autowired private ItemsService itmesService; //如果Controller中接收的是Vo,那麼頁面上input框的name屬性值要等於vo的屬性.屬性.屬性..... @RequestMapping("/search") public String search(QueryVo vo) throws Exception{ System.out.println(vo); return ""; } }
4. 自定義類型轉換器
當從界面傳過來date類型的時候,使用pojo接收會報錯,因爲springmvc只會轉換基本數據類型;對於其他類型,則需要自定義類型轉換器。
具體操作:
01.先新建一個轉換器類
import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import org.springframework.core.convert.converter.Converter; /** * S - source:源 * T - target:目標 * @author zj * */ public class CustomGlobalStrToDateConverter implements Converter<String, Date> { @Override public Date convert(String source) { try { Date date = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").parse(source); return date; } catch (ParseException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } }
02.在springmvc配置文件中配置
<!-- 註解驅動: 替我們顯示的配置了最新版的註解的處理器映射器和處理器適配器 --> <mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven> <!-- 配置自定義轉換器 注意: 一定要將自定義的轉換器配置到註解驅動上 --> <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"> <property name="converters"> <set> <!-- 指定自定義轉換器的全路徑名稱 --> <bean class="cn.itheima.controller.converter.CustomGlobalStrToDateConverter"/> </set> </property> </bean>
注意: 一定要將自定義的轉換器配置到註解驅動上,因爲會被處理器適配器去識別,進行轉換
5. 高級參數綁定
數組:
頁面
<form action="${pageContext.request.contextPath }/updateAll.action" method="post"> <table width="100%" border=1> <tr> <td><input type="submit" value="批量修改"/></td> </tr> </table> 商品列表: <table width="100%" border=1> <tr> <td></td> <td>商品名稱</td> <td>商品價格</td> <td>生產日期</td> <td>商品描述</td> <td>操作</td> </tr> <c:forEach items="${itemList }" var="item" varStatus="status"> <tr> <!-- name屬性名稱要等於vo中的接收的屬性名 --> <!-- 如果批量刪除,可以用List<pojo>來接收,頁面上input框的name屬性值= vo中接收的集合屬性名稱+[list的下標]+.+list泛型的屬性名稱 --> <td> <input type="checkbox" name="ids" value="${item.id }"/> </td> <td>${item.name }</td> <td>${item.price }</td> <td><fmt:formatDate value="${item.createtime}" pattern="yyyy-MM-dd HH:mm:ss"/></td> <td>${item.detail }</td> </tr> </c:forEach> </table> </form>
@RequestMapping("/delAll") //會將多選框中的id放入vo類中,ids數組中 public String delAll(QueryVo vo) throws Exception{ //如果批量刪除,一堆input複選框,那麼可以提交數組.(只有input複選框被選中的時候才能提交) System.out.println(vo); return ""; }
public class QueryVo { //商品對象 private Items items; //訂單對象... //用戶對象.... //批量刪除使用 private Integer[] ids;
集合:
頁面:
<form action="${pageContext.request.contextPath }/updateAll.action" method="post"> 查詢條件: <table width="100%" border=1> <tr> <!-- 如果Controller中接收的是Vo,那麼頁面上input框的name屬性值要等於vo的屬性.屬性.屬性..... --> <td>商品名稱:<input type="text" name="items.name"/></td> <td>商品價格:<input type="text" name="items.price"/></td> <td><input type="submit" value="批量修改"/></td> </tr> </table> 商品列表: <table width="100%" border=1> <tr> <td></td> <td>商品名稱</td> <td>商品價格</td> <td>生產日期</td> <td>商品描述</td> <td>操作</td> </tr> <c:forEach items="${itemList }" var="item" varStatus="status"> <tr> <!-- name屬性名稱要等於vo中的接收的屬性名 --> <!-- 如果批量刪除,可以用List<pojo>來接收,頁面上input框的name屬性值= vo中接收的集合屬性名稱+[list的下標]+.+list泛型的屬性名稱 --> <td> <input type="checkbox" name="ids" value="${item.id }"/> <input type="hidden" name="itemsList[${status.index }].id" value="${item.id }"/> </td> <td><input type="text" name="itemsList[${status.index }].name" value="${item.name }"/></td> <td><input type="text" name="itemsList[${status.index }].price" value="${item.price }"/></td> <td><input type="text" name="itemsList[${status.index }].createtime" value="<fmt:formatDate value="${item.createtime}" pattern="yyyy-MM-dd HH:mm:ss"/>"/></td> <td><input type="text" name="itemsList[${status.index }].detail" value="${item.detail }"/></td> <td><a href="${pageContext.request.contextPath }/items/itemEdit/${item.id}">修改</a></td> </tr> </c:forEach> </table> </form>
@RequestMapping("/updateAll") public String updateAll(QueryVo vo) throws Exception{ System.out.println(vo); return ""; }
public class QueryVo { //商品對象 private Items items; //訂單對象... //用戶對象.... //批量刪除使用 private Integer[] ids; //批量修改使用 private List<Items> itemsList;
04-2.controller返回值
1. Void
返回void(使用它破壞了springMvc的結構,所以不建議使用)
可以使用request.setAttribut 來給頁面返回數據
可以使用request.getRquestDispatcher().forward()來指定返回的頁面
如果controller返回值爲void則不走springMvc的組件,所以要寫頁面的完整路徑名稱
//返回數據 //request.setAttribute("", arg1); //指定返回的頁面(如果controller方法返回值爲void,則不走springMvc組件,所以要寫頁面的完整路徑名稱) //request.getRequestDispatcher("/WEB-INF/jsp/success.jsp").forward(request, response);
2. String和Model(重定向和轉發、相對路徑和絕對路徑)
String(推薦使用)
返回普通字符串,就是頁面去掉擴展名的名稱, 返回給頁面數據通過Model來完成
返回的字符串以forward:開頭爲請求轉發
返回的字符串以redirect:開頭爲重定向
重定向(model):
重定向,如果使用request,數據不能帶的;但是如果使用model可以帶上傳遞的數據
//重定向:瀏覽器中url發生改變,request域中的數據不可以帶到重定向後的方法中 //model.addAttribute("id", items.getId()); //在springMvc中凡是以redirect:字符串開頭的都爲重定向 return "redirect:itemEdit/"+items.getId();
轉發:
//請求轉發:瀏覽器中url不發生改變,request域中的數據可以帶到轉發後的方法中 model.addAttribute("id", items.getId()); //spirngMvc中請求轉發:返回的字符串以forward:開頭的都是請求轉發, //後面forward:itemEdit.action表示相對路徑,相對路徑就是相對於當前目錄,當前爲類上面指定的items目錄.在當前目錄下可以使用相對路徑隨意跳轉到某個方法中 //後面forward:/itemEdit.action路徑中以斜槓開頭的爲絕對路徑,絕對路徑從項目名後面開始算 return "forward:/items/itemEdit.action";
3. ModelAndView
ModelAndView modelAndView.addObject("itemList", list); 指定返回頁面的數據 modelAndView.setViewName("itemList"); 指定返回的頁面
4. 相對路徑和絕對路徑
相對路徑:
相對於當前目錄,也就是在當前類的目錄下,這時候可以使用相對路徑跳轉
絕對路徑:
從項目名後開始.
在springMvc中不管是forward還是redirect後面凡是以/開頭的爲絕對路徑,不以/開頭的爲相對路徑
例如:forward:/items/itemEdit.action 爲絕對路徑
forward:itemEdit.action爲相對路徑
05.亂碼問題
Post:
<!-- 配置Post請求亂碼 --> <filter> <filter-name>CharacterEncodingFilter</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>CharacterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
Get:
01.修改Tomcat配置文件添加編碼與工程編碼一致:server.xml
<Connector URIEncoding=”utf8” connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
02.對參數進行重編碼
String username = new String(request.getParameter(“username”).getBytes(“ISO8859-1”),”utf-8”)
06.jsp傳圖片注意
<!-- 上傳圖片是需要指定屬性 enctype="multipart/form-data" -->
<!-- <form id="itemForm" action="" method="post" enctype="multipart/form-data"> -->
07.springmvc與struts2不同
1、 springmvc的入口是一個servlet即前端控制器,而struts2入口是一個filter過慮器。
2、 springmvc是基於方法開發(一個url對應一個方法),請求參數傳遞到方法的形參,可以設計爲單例或多例(建議單例),struts2是基於類開發,傳遞參數是通過類的屬性,只能設計爲多例。
3、 Struts採用值棧存儲請求和響應的數據,通過OGNL存取數據, springmvc通過參數解析器是將request請求內容解析,並給方法形參賦值,將數據和視圖封裝成ModelAndView對象,最後又將ModelAndView中的模型數據通過reques域傳輸到頁面。Jsp視圖解析器默認使用jstl。
08.@RequestMapping用法
1. URL路徑映射
2. 窄化請求映射
3. 請求方法限定
09.異常處理器
springmvc在處理請求過程中出現異常信息交由異常處理器進行處理,自定義異常處理器可以實現一個系統的異常處理邏輯。
異常處理思路
系統中異常包括兩類:預期異常和運行時異常RuntimeException,前者通過捕獲異常從而獲取異常信息,後者主要通過規範代碼開發、測試通過手段減少運行時異常的發生。
系統的dao、service、controller出現都通過throws Exception向上拋出,最後由springmvc前端控制器交由異常處理器進行異常處理,如下圖:
自定義異常類
爲了區別不同的異常通常根據異常類型自定義異常類,這裏我們創建一個自定義系統異常,如果controller、service、dao拋出此類異常說明是系統預期處理的異常信息。
public class CustomException extends Exception { /** serialVersionUID*/ private static final long serialVersionUID = -5212079010855161498L; public CustomException(String message){ super(message); this.message = message; } //異常信息 private String message; public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } }
自定義異常處理器
public class CustomExceptionResolver implements HandlerExceptionResolver { @Override public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { ex.printStackTrace(); CustomException customException = null; //如果拋出的是系統自定義異常則直接轉換 if(ex instanceof CustomException){ customException = (CustomException)ex; }else{ //如果拋出的不是系統自定義異常則重新構造一個系統錯誤異常。 customException = new CustomException("系統錯誤,請與系統管理 員聯繫!"); } ModelAndView modelAndView = new ModelAndView(); modelAndView.addObject("message", customException.getMessage()); modelAndView.setViewName("error"); return modelAndView; } }
錯誤頁面
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>錯誤頁面</title> </head> <body> 您的操作出現錯誤如下:<br/> ${message } </body> </html>
異常處理器配置
在springmvc.xml中添加:
<!-- 異常處理器 --> <bean id="handlerExceptionResolver" class="cn.itcast.ssm.controller.exceptionResolver.CustomExceptionResolver"/>
異常測試
修改商品信息,id輸入錯誤提示商品信息不存在。
修改controller方法“editItem”,調用service查詢商品信息,如果商品信息爲空則拋出異常:
010.SpringMVC上傳圖片
1. 配置虛擬圖片服務器
前提:
環境基於Tomcat6.x系列實驗, 其它版本的Tomcat虛擬目錄配置可能略有不同
1. 進入Tomcat conf\Catalina\localhost
2. 新建xxx.xml文件, 我這裏命名爲img.xml
3. 在xml文件中配置如下內容:
<Context path="/img" reloadable="true" docBase="D:\img" />
path : 瀏覽器訪問目錄, 與xml文件名必須一致
docBase : 虛擬目錄
4. 在Tomcat的conf\web.xml文件中找到如下配置:
listings 修改成true
5. 通過瀏覽器訪問
http://ip:端口號/虛擬目錄, 如可以顯示,虛擬目錄配置成功
2. 導包
CommonsMultipartResolver解析器依賴commons-fileupload和commons-io,加入如下jar包:
3. 配置解析器
在springmvc.xml
<!-- 文件上傳 --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!-- 設置上傳文件的最大尺寸爲5MB --> <property name="maxUploadSize"> <value>5242880</value> </property> </bean>
4. 頁面
<!-- 上傳圖片是需要指定屬性 enctype="multipart/form-data" --> <form id="itemForm" action="${pageContext.request.contextPath }/items/updateitem" method="post" enctype="multipart/form-data"> <%-- <form id="itemForm" action="${pageContext.request.contextPath }/items/updateitem.action" method="post"> --%> <input type="hidden" name="id" value="${item.id }" /> 修改商品信息: <table width="100%" border=1> <tr> <td>商品名稱</td> <td><input type="text" name="name" value="${item.name }" /></td> </tr> <tr> <td>商品價格</td> <td><input type="text" name="price" value="${item.price }" /></td> </tr> <tr> <td>商品生產日期</td> <td><input type="text" name="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="detail">${item.detail }</textarea> </td> </tr> <tr> <td colspan="2" align="center"><input type="submit" value="提交" /> </td> </tr> </table> </form>
5. web層操作
@RequestMapping("/updateitem") //pictureFile跟頁面中”<input type="file" name="pictureFile"/> ”的name值一樣 public String update(MultipartFile pictureFile,Items items, Model model, HttpServletRequest request) throws Exception{ //1. 獲取圖片完整名稱 String fileStr = pictureFile.getOriginalFilename(); //2. 使用隨機生成的字符串+源圖片擴展名組成新的圖片名稱,防止圖片重名 String newfileName = UUID.randomUUID().toString() + fileStr.substring(fileStr.lastIndexOf(".")); //3. 將圖片保存到硬盤 pictureFile.transferTo(new File("E:\\image\\" + newfileName)); //4.將圖片名稱保存到數據庫 items.setPic(newfileName); itmesService.updateItems(items); return "redirect:itemEdit/"+items.getId(); }
011.json數交互
@RequestBody
作用:
@RequestBody註解用於讀取http請求的內容(字符串),通過springmvc提供的HttpMessageConverter接口將讀到的內容轉換爲json、xml等格式的數據並綁定到controller方法的參數上。
List.action?id=1&name=zhangsan&age=12
本例子應用:
@RequestBody註解實現接收http請求的json數據,將json數據轉換爲java對象
@ResponseBody
作用:
該註解用於將Controller的方法返回的對象,通過HttpMessageConverter接口轉換爲指定格式的數據如:json,xml等,通過Response響應給客戶端
本例子應用:
@ResponseBody註解實現將controller方法返回對象轉換爲json響應給客戶端
請求json,響應json實現:
1. 環境準備
Springmvc默認用MappingJacksonHttpMessageConverter對json數據進行轉換,需要加入jackson的包,如下:
2. springmvc.xml配置
在註解適配器中加入messageConverters
<!--註解適配器 --> <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>
注意:如果使用<mvc:annotation-driven /> 則不用定義上邊的內容。
3. 頁面
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <script type="text/javascript" src="${pageContext.request.contextPath }/js/jquery-1.4.4.min.js"></script> <title>查詢商品列表</title> </head> <body> <script type="text/javascript"> function sendJson(){ //請求json響應json $.ajax({ type:"post", url:"${pageContext.request.contextPath }/items/sendJson.action", contentType:"application/json;charset=utf-8", data:'{"name":"測試商品","price":99.9}', success:function(data){ alert(data); } }); } </script> <input type="button" value="senJson" onClick="sendJson()"/> <form action="${pageContext.request.contextPath }/updateAll.action" method="post"> 查詢條件: <table width="100%" border=1> <tr> <!-- 如果Controller中接收的是Vo,那麼頁面上input框的name屬性值要等於vo的屬性.屬性.屬性..... --> <td>商品名稱:<input type="text" name="items.name"/></td> <td>商品價格:<input type="text" name="items.price"/></td> <td><input type="submit" value="批量修改"/></td> </tr> </table> 商品列表: <table width="100%" border=1> <tr> <td></td> <td>商品名稱</td> <td>商品價格</td> <td>生產日期</td> <td>商品描述</td> <td>操作</td> </tr> <c:forEach items="${itemList }" var="item" varStatus="status"> <tr> <!-- name屬性名稱要等於vo中的接收的屬性名 --> <!-- 如果批量刪除,可以用List<pojo>來接收,頁面上input框的name屬性值= vo中接收的集合屬性名稱+[list的下標]+.+list泛型的屬性名稱 --> <td> <input type="checkbox" name="ids" value="${item.id }"/> <input type="hidden" name="itemsList[${status.index }].id" value="${item.id }"/> </td> <td><input type="text" name="itemsList[${status.index }].name" value="${item.name }"/></td> <td><input type="text" name="itemsList[${status.index }].price" value="${item.price }"/></td> <td><input type="text" name="itemsList[${status.index }].createtime" value="<fmt:formatDate value="${item.createtime}" pattern="yyyy-MM-dd HH:mm:ss"/>"/></td> <td><input type="text" name="itemsList[${status.index }].detail" value="${item.detail }"/></td> <td><a href="${pageContext.request.contextPath }/items/itemEdit/${item.id}">修改</a></td> </tr> </c:forEach> </table> </form> </body> </html>
4. controller操作
//導入jackson的jar包在 controller的方法中可以使用@RequestBody,讓spirngMvc將json格式字符串自動轉換成java中的pojo //頁面json的key要等於java中pojo的屬性名稱 //controller方法返回pojo類型的對象並且用@ResponseBody註解,springMvc會自動將pojo對象轉換成json格式字符串 @RequestMapping("/sendJson") @ResponseBody public Items json(@RequestBody Items items) throws Exception{ System.out.println(items); return items; }
012.restful
什麼是restful?
Restful就是一個資源定位及資源操作的風格。不是標準也不是協議,只是一種風格,是對http協議的詮釋。
資源定位:互聯網所有的事物都是資源,要求url中沒有動詞,只有名詞。沒有參數
資源操作:使用put、delete、post、get,使用不同方法對資源進行操作。分別對應添加、刪除、修改、查詢。一般使用時還是post和get。Put和Delete幾乎不使用。
需求
RESTful方式實現商品信息查詢,返回json數據
添加DispatcherServlet的rest配置(在web.xml)
<!-- springmvc前端控制器 --> <servlet> <servlet-name>springMvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:SpringMvc.xml</param-value> </init-param> <!-- 在tomcat啓動的時候就加載這個servlet --> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springMvc</servlet-name> <!-- *.action 代表攔截後綴名爲.action結尾的 / 攔截所有但是不包括.jsp /* 攔截所有包括.jsp --> <url-pattern>/</url-pattern> </servlet-mapping>
URL 模板模式映射
@RequestMapping(value="/ viewItems/{id}"):
{×××}佔位符,請求的URL可以是“/viewItems/1”或“/viewItems/2”,通過在方法中使用@PathVariable獲取{×××}中的×××變量。
@PathVariable用於將請求URL中的模板變量映射到功能處理方法的參數上。
@RequestMapping("/viewItems/{id}") public @ResponseBody viewItems(@PathVariable("id") String id,Model model) throws Exception{ //方法中使用@PathVariable獲取useried的值,使用model傳回頁面 //調用 service查詢商品信息 ItemsCustom itemsCustom = itemsService.findItemsById(id); return itemsCustom; }
如果RequestMapping中表示爲"/viewItems/{id}",id和形參名稱一致,@PathVariable不用指定名稱。
有多個加多個佔位符就好
商品查詢的controller方法也改爲rest實現:
// 查詢商品列表 @RequestMapping("/queryItem") public ModelAndView queryItem() throws Exception { // 商品列表 List<Items> itemsList = itemService.findItemsList(null); // 創建modelAndView準備填充數據、設置視圖 ModelAndView modelAndView = new ModelAndView(); // 填充數據 modelAndView.addObject("itemsList", itemsList); // 視圖 modelAndView.setViewName("item/itemsList"); return modelAndView; }
靜態資源訪問<mvc:resources>
如果在DispatcherServlet中設置url-pattern爲 /則必須對靜態資源進行訪問處理。
spring mvc 的<mvc:resources mapping="" location="">實現對靜態資源進行映射訪問。
如下是對js文件訪問配置:
<mvc:resources location="/js/" mapping="/js/**"/>
013.攔截器
1. 攔截器基礎
public class Interceptor1 implements HandlerInterceptor { //執行時機:controller已經執行,modelAndview已經返回 //使用場景: 記錄操作日誌,記錄登錄用戶的ip,時間等. @Override public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3) throws Exception { System.out.println("======Interceptor1=======afterCompletion========"); } //執行時機:Controller方法已經執行,ModelAndView沒有返回 //使用場景: 可以在此方法中設置全局的數據處理業務 @Override public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3) throws Exception { System.out.println("======Interceptor1=======postHandle========"); } //返回布爾值:如果返回true放行,返回false則被攔截住 //執行時機:controller方法沒有被執行,ModelAndView沒有被返回 //使用場景: 權限驗證 @Override public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception { System.out.println("======Interceptor1=======preHandle========"); return true; } }
<!-- 配置攔截器 --> <mvc:interceptors> <!-- 多個攔截器的執行順序等於springMvc.xml中的配置順序 --> <!-- <mvc:interceptor> --> <!-- 攔截請求的路徑 要攔截所有必需配置成/** --> <!-- <mvc:mapping path="/**"/> --> <!-- 指定攔截器的位置 --> <!-- <bean class="cn.itheima.interceptor.Interceptor1"></bean> --> <!-- </mvc:interceptor> --> <!-- <mvc:interceptor> --> <!-- 攔截請求的路徑 要攔截所有必需配置成/** --> <!-- <mvc:mapping path="/**"/> --> <!-- 指定攔截器的位置 --> <!-- <bean class="cn.itheima.interceptor.Interceptor2"></bean> --> <!-- </mvc:interceptor> --> <mvc:interceptor> <!-- 攔截請求的路徑 要攔截所有必需配置成/** --> <mvc:mapping path="/**"/> <!-- 指定攔截器的位置 --> <bean class="cn.itheima.interceptor.LoginInterceptor"></bean> </mvc:interceptor> </mvc:interceptors>
針對某種mapping配置攔截器
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"> <property name="interceptors"> <list> <ref bean="handlerInterceptor1"/> <ref bean="handlerInterceptor2"/> </list> </property> </bean> <bean id="handlerInterceptor1" class="springmvc.intercapter.HandlerInterceptor1"/> <bean id="handlerInterceptor2" class="springmvc.intercapter.HandlerInterceptor2"/>
針對所有mapping配置全局攔截器
<!--攔截器 --> <mvc:interceptors> <!--多個攔截器,順序執行 --> <mvc:interceptor> <mvc:mapping path="/**"/> <bean class="cn.itcast.springmvc.filter.HandlerInterceptor1"></bean> </mvc:interceptor> <mvc:interceptor> <mvc:mapping path="/**"/> <bean class="cn.itcast.springmvc.filter.HandlerInterceptor2"></bean> </mvc:interceptor> </mvc:interceptors>