SpringMVC和Mybatis(二)參數綁定、和Struts區別

參數綁定
點擊修改後進入修改頁面
開發mapper
根據id查詢商品信息
根據id更新items表的數據(數據庫)
可以直接使用逆向工程的代碼


開發service
根據id查詢商品信息
修改商品信息(業務層)
ItemsService.java
public interface ItemsService {


//商品查詢列表
public List<ItemsCustom> findItemsList(ItemsQueryVo itemsQueryVo)throws Exception;

//根據id查詢商品信息
public ItemsCustom findItemsById(Integer id)throws Exception;

//修改商品信息。 id爲修改商品的id,itemsCustom爲修改的商品信息
public void updateItems(Integer id,ItemsCustom itemsCustom)throws Exception;
}


ItemsServiceImpl.java
public class ItemsServiceImpl implements ItemsService {


@Autowired
private ItemsMapperCustom itemsMapperCustom;

@Autowired
private ItemsMapper itemsMapper;

//itemsMapperCustom直接從service傳到dao
@Override
public List<ItemsCustom> findItemsList(ItemsQueryVo itemsQueryVo) throws Exception {
// TODO Auto-generated method stub
return itemsMapperCustom.findItemsList(itemsQueryVo);
}


@Override
public ItemsCustom findItemsById(Integer id) throws Exception {




Items items = itemsMapper.selectByPrimaryKey(id);
//中間對商品信息進行業務處理
//...
//最後返回ItemsCustom
ItemsCustom itemsCustom = new ItemsCustom();
//將items的內容拷貝到itemsCustom
BeanUtils.copyProperties(items, itemsCustom);

return itemsCustom;
}


@Override
public void updateItems(Integer id, ItemsCustom itemsCustom) throws Exception {
//添加業務校驗,在service接口對關鍵參數進行校驗
//校驗id是否爲空,如果爲空拋出spring的異常


//更新商品信息使用updateByPrimaryKeyWithBLOBs根據id更新items表中所有字段,包括大文本
//要求必須傳入id,需要重複設置id
itemsCustom.setId(id);
itemsMapper.updateByPrimaryKeyWithBLOBs(itemsCustom);

}


}
============================================================================================
開發controller並調試


ItemsController.java


//使用Controller標識他是一個控制器
@Controller
public class ItemsController {

//注入service
@Autowired
private ItemsService itemsService;


//商品查詢列表
//一般建議將url和方法名寫成一樣,方便queryItems和url進行映射,一個方法對應一個url
@RequestMapping("/queryItems")
public ModelAndView queryItems()throws Exception{
//調用service查找數據庫,查詢商品,這裏先使用靜態模擬
List<ItemsCustom> itemsList = itemsService.findItemsList(null);

//返回ModelAndView
ModelAndView modelAndView = new ModelAndView();
//相當於request的setAttribut,在jsp頁面中通過itemsList取數據
modelAndView.addObject("itemsList",itemsList);

//指定視圖
//下邊的路徑,如果在視圖解析器中配置jsp路徑的前綴和jsp路徑的後綴,就改爲
//modelAndView.setViewName("/WEB-INF/jsp/items/itemsList.jsp");
//上邊的路徑配置可以不再程序中指定jsp路徑的前綴和jsp路徑的後綴
modelAndView.setViewName("items/itemsList");
return modelAndView;
}

//定義其他方法
//商品添加
//商品修改

//商品信息修改頁面顯示
@RequestMapping("/editItems")
public ModelAndView editItems()throws Exception{

//調用service根據商品id查詢商品信息
ItemsCustom itemsCustom = itemsService.findItemsById(1);

//返回ModelAndView
ModelAndView modelAndView = new ModelAndView();

//相當於request的setAttribut,在jsp頁面中通過itemsList取數據
modelAndView.addObject("itemsCustom",itemsCustom);

//指定視圖
modelAndView.setViewName("items/editItems");
return modelAndView;
}

//商品信息修改提交
@RequestMapping("/editItemsSubmit")
public ModelAndView editItemsSubmit()throws Exception{

//調用service更新商品信息,頁面需要將商品信息傳到此方法
//.............

//返回ModelAndView
ModelAndView modelAndView = new ModelAndView();

//相當於request的setAttribut,在jsp頁面中通過itemsList取數據
//modelAndView.addObject("itemsCustom",itemsCustom);

//指定視圖
modelAndView.setViewName("success");
return modelAndView;
}


========================================================================================
調試:
itemsList.jsp


<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"
contentType="text/html; charset=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">
<html>
  <head>
    
    <title>check list</title>
    
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">    
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->


  </head>
  
  <body>
  <form action="${pageContext.request.contextPath }/item/queryItem.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>
  </tr>
  <c:forEach items="${itemsList }" var="item">
  <tr>
  <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>
 
  <td><a href="${pageContext.request.contextPath }/editItems.action?id=${item.id}">修改</a></td>
  </tr>
  </c:forEach>
  </table>
  </form>
  </body>
</html>


editItems.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"
contentType="text/html; charset=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">
<html>
  <head>
    
    <title>check list</title>
    
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">    
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->

  </head>
  
  <body>
  <form id="itemForm" action="" method="post" enctype="multipart/form-data">
  <input type="hidden" name="id" value="${itemsCustom.id }" />
  修改商品信息:
  <table width="100%" border=1>
  <tr>
  <td>商品名稱</td>
  <td><input type="text" name="name" value="${itemsCustom.name }" /></td>
  </tr>
  <tr>
  <td>商品價格</td>
  <td><input type="text" name="price" value="${itemsCustom.price }" /></td>
  </tr>
  <tr>
  <td>商品的生產日期</td>
  <td><input type="text" name="createtime" value="<fmt:formatDate value="${itemsCustom.createtime }" pattern="yyy-mm-dd HH:mm:ss" /> "/></td>
  <tr>
  <td>商品圖片</td>
  <td>
  <c:if test="${itemsCustom.pic !=null }">
  <img alt="" src="/pic/${itemsCustom.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">${itemsCustom.detail }</textarea>
  </td>
  </tr>
  <tr>
  <td colspan="2" align="center"><input type="submit" value="提交" />
  </td>
  </tr>
  </table>
  </form>
  </body>
</html>


===============================================================================================
controller註解開發
@requestMapping
定義controller方法對應的url,進行處理器映射。

1.窄化請求映射

ItemsController.java

//使用Controller標識他是一個控制器
@Controller
//爲了對url進行分類管理可以定義一個根路徑,最終訪問url是根路徑+子路徑
//比如:商品列表:/items/queryItems.action
@RequestMapping("/items")
public class ItemsController {


還需要修改前臺頁面
itemsList.jsp
  <c:forEach items="${itemsList }" var="item">
  <tr>
  <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>
 
  <td><a href="${pageContext.request.contextPath }/items/editItems.action?id=${item.id}">修改</a></td>
  </tr>
  </c:forEach>
  </table>
  </form>
  </body>
</html>


還需要修改前臺頁面
editItems.jsp


<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"
contentType="text/html; charset=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">
<html>
  <head>
    
    <title>check list</title>
    
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">    
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->


  </head>
  
  <body>
  <form id="itemForm" action="${pageContext.request.contextPath }/items/editItemsSubmit.action" method="post">
  <input type="hidden" name="id" value="${itemsCustom.id }" />




2.限制http請求方法
處於安全考慮,如果限制請求爲post方法,進行get請求,報錯。
//商品信息修改頁面顯示
//@RequestMapping("/editItems")
//限制http請求方法 可以post和get
@RequestMapping(value="/editItems",method={RequestMethod.POST,RequestMethod.GET})
public ModelAndView editItems()throws Exception{


===========================================================================================
controller方法的返回值
1.返回ModeAndView
2.返回string
返回string就是返回邏輯視圖名。真正的視圖(jsp路徑)=前綴 +邏輯視圖名 +後綴
@RequestMapping(value="/editItems",method={RequestMethod.POST,RequestMethod.GET})
public String editItems(Model model)throws Exception{
//調用service根據商品id查詢商品信息
ItemsCustom itemsCustom = itemsService.findItemsById(1);

model.addAttribute("itemsCustom",itemsCustom);
return "items/editItems";
}

返回redirect
重定向特點:瀏覽器地址欄中的url會變化,修改提交的request數據無法傳到重定向的地址。重定向後重新request(request無法共享)
//商品信息修改提交
@RequestMapping("/editItemsSubmit")
public String editItemsSubmit()throws Exception{
//重定向到商品列表
return "redirect:queryItems.action";
}


返回forward
通過forward頁面轉發:瀏覽器地址欄中的url會不變化,request可以共享
//商品信息修改提交
@RequestMapping("/editItemsSubmit")
public String editItemsSubmit()throws Exception{
//頁面轉發
return "forward:queryItems.action";
}




3.返回void
在controller方法形參上可以定義request和response,使用request或response指定響應結果:
1.使用request轉向頁面,如下:
request.getRequestDispatcher("頁面路徑").forward(request,response);


2.也可以通過response頁面重定向:
response.sendRedirect("url");


3.也可以通過response指定響應結果,例如響應json數據如下:
response.setCharacterEncoding("utf-8");
response.setContentType("application/json;charset=utf-8");
response.getWriter().write("json串");


========================================================================================
參數綁定
從客戶端請求key/value數據,經過參數綁定,將key/value數據綁定到controller方法的形參上。
在springmvc中,接收頁面提交的數據是通過方法形參來接收,而不是在controller類定義成員變量來接收。


參數綁定默認支持
1.HttpServletRequest


2.HttpServletResponse


3.HttpSession


4.Model/ModelMap


5.還有簡單類型
@RequestMapping(value="/editItems",method={RequestMethod.POST,RequestMethod.GET})
public String editItems(Model model,Integer id)throws Exception{
//如果不使用@RequestParam,要求request傳入參數名稱和controller方法的形參名稱一致,方可以綁定成功。
//調用service根據商品id查詢商品信息

ItemsCustom itemsCustom = itemsService.findItemsById(id);


6.@RequestParam
通過@RequestParam對簡單類型的參數進行綁定。如果不使用@RequestParam,要求request傳入參數名稱和controller方法的形參名稱一致,方可以綁定成功。
如果使用註解不用限制request傳入參數名稱和controller方法的形參名稱一致。
/@RequestParam裏面指定request傳入參數名稱和形參進行綁定
//通過required屬性指定參數是否必須要傳入
//通過defaultValue可以設置默認值,如果id參數沒有傳入,可以將默認值和形參進行綁定
public String editItems(Model model,@RequestParam(value="id",required=true,defaultValue="")Integer items_id)throws Exception{


======================================================================================================================
7.綁定pojo
ItemsController.java


//商品信息修改提交
@RequestMapping("/editItemsSubmit")
public String editItemsSubmit(HttpServletRequest request,Integer id,ItemsCustom itemsCustom)throws Exception{

//調用service更新商品信息,頁面需要將商品信息傳到此方法
//.............
itemsService.updateItems(id, itemsCustom);




有值但是亂碼
在web.xml中添加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>


<welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
</web-app>


以上可以解決post請求亂碼問題
對於get請求中文參數出現亂碼解決方法有兩個:
修改Tomcat配置文件添加編碼與工程編碼一致,如下
<Connector URIEncoding="utf-8" connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPot="8443" />
另一種方法對參數進行重新編碼:
String userName new
String(request.getParamter("userName").getBaytes("ISO8859-1"),"utf-8")
ISO8859-1是Tomcat默認編碼,改變Tomcat編碼後的內容按utf-8。


頁面中input的name和controller的pojo形參中的屬性名稱一致,將頁面中數據綁定到pojo。
所以頁面中的name的屬性名很重要,只要一致就能綁定。
============================================================================================
8.自定義參數綁定實現日期類型綁定(未驗證成功75、76日期參數綁定)
對於controller形參中pojo對象,如果屬性中有日期類型,需要自定義參數綁定。
將請求日期數據串傳成 日期類型,要轉換的日期類型和pojo中日期屬性的類型保持一致。
所以自定義參數綁定將日期串轉成java.util.Date類型。
需要向處理器適配器中注入自定義的參數綁定組件。
<mvc:annotation-driven conversion-service="conversionService" />


打開商品生產日期選項
editItems.jsp
<form id="itemForm" action="${pageContext.request.contextPath }/items/editItemsSubmit.action" method="post">
  <input type="hidden" name="id" value="${itemsCustom.id }" />
  修改商品信息:
  <table width="100%" border=1>
  <tr>
  <td>商品名稱</td>
  <td><input type="text" name="name" value="${itemsCustom.name }" /></td>
  </tr>
  <tr>
  <td>商品價格</td>
  <td><input type="text" name="price" value="${itemsCustom.price }" /></td>
  </tr>
  <tr>
  <td>商品的生產日期</td>
  <td><input type="text" name="createtime" value="<fmt:formatDate value="${itemsCustom.createtime }" pattern="yyy-mm-dd HH:mm:ss" /> "/></td>
</tr>


springmvc.xml
<!-- 註解映射器 
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping" />-->
<!-- 註解適配器
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter" /> -->


<!-- 使用mvc:annotation-driven 代替上邊的註解映射器和註解適配器
mvc:annotation-driven默認加載很多的參數綁定方法,比如json轉換解析器就默認加載了,如果使用mvc:annotation-driven不用配置上邊的RequestMappingHandlerMapping和RequestMappingHandlerAdapter
實際開發使用的也是這個mvc:annotation-driven -->
<mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>


springmvc.xml需要配置bean


<!-- 自定義參數綁定 -->
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<!-- 轉換器 -->
<property name="converters">
<list>
<!-- 可以寫很多轉換器,字符串等 -->
<bean class="cn.itcast.ssm.controller.converter.CustomDateConverter" />
</list>
</property>
</bean>


創建controller.converter包

CustomDateConverter.java

import org.springframework.core.convert.converter.Converter;

public class CustomDateConverter implements Converter<String,Date> {


@Override
public Date convert(String source) {
//將日期串轉成日期類型
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try {
//轉成直接返回
return simpleDateFormat.parse(source);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//如果參數綁定失敗返回null
return null;
}


}




配置方式2比較繁瑣
<!-- 註解適配器 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
 <property name="webBindingInitializer" ref="customBinder"></property>
</bean>
<!-- 自定義webBinder -->
<bean id="customBinder" class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
 <property name="conversionService" ref="conversionService" />
</bean>
<!-- conversionService -->
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
 <!-- 轉換器 -->
 <property name="converters">
  <list>
   <bean class="cn.itcast.ssm.controller.converter.CustomDateConverter" />
  <list>
 </property>

</bean>

===========================================================================

SpringMVC和Struts區別
1.springmvc基於方法開發,struts基於類開發。
springmvc將url和controller方法映射,映射後springmvc生成一個Handller對象,對象只包括一個method。
方法執行結束,形參銷燬。
所以springmvc可以進行單例,建議使用單例開發。就像數據庫連接池就是單例模式,有且僅有一個連接池管理者,管理多個連接池對象。
之所以用單例,是因爲沒必要每個請求都新建一個對象,這樣子既浪費CPU又浪費內存; 
之所以用多例,是爲了防止併發問題;即一個請求改變了對象的狀態,此時對象又處理另一個請求,而之前請求對對象狀態的改變導致了對象對另一個請求做了錯誤的處理; 
用單例和多例的標準只有一個: 當對象含有可改變的狀態時(更精確的說就是在實際應用中該狀態會改變),則多例,否則單例
Struts2通過類開發,無法使用單例開發,只能用多例。
對於struts2來說,action必須用多例,因爲action本身含有請求參數的值,即可改變的狀態。
而對於struts1來說,action則可用單例,因爲請求參數的值是放在actionForm中,而非action中的。

經過測試Struts慢,是因爲使用Struts便籤。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章