springmvc主要由 一個DispatcherServlet(不需要開發),三個組件:處理器映射器,處理器適配器,視圖解析器(不需要開發)
hanlder(需要開發),view(需要開發)組成
架構流程
- 用戶發送請求至前端控制器DispatcherServlet
- DispatcherServlet收到請求調用HandlerMapping處理器映射器。
- 處理器映射器根據請求url找到具體的處理器,生成處理器對象及處理器攔截器(如果有則生成)一併返回給DispatcherServlet。
- DispatcherServlet通過HandlerAdapter處理器適配器調用處理器
- 執行處理器(Controller,也叫後端控制器)。
- Controller執行完成返回ModelAndView
- HandlerAdapter將controller執行結果ModelAndView返回給DispatcherServlet
- DispatcherServlet將ModelAndView傳給ViewReslover視圖解析器
- ViewReslover解析後返回具體View
- DispatcherServlet對View進行渲染視圖(即將模型數據填充至視圖中)。
- DispatcherServlet響應用戶
springmvc與struts2不同
- springmvc的入口是一個servlet即前端控制器,而struts2入口是一個filter過濾器。
- springmvc是基於方法開發(一個url對應一個方法),請求參數傳遞到方法的形參,可以設計爲單例或多例(建議單例),struts2是基於類開發,傳遞參數是通過類的屬性,只能設計爲多例。
- Struts採用值棧存儲請求和響應的數據,通過OGNL存取數據, springmvc通過參數解析器是將request請求內容解析,並給方法形參賦值,將數據和視圖封裝成ModelAndView對象,最後又將ModelAndView中的模型數據通過request域傳輸到頁面。Jsp視圖解析器默認使用jstl。
核心配置文件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: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">
<!-- 掃描@Controler @Service -->
<context:component-scan base-package="lx" />
<!-- 處理器映射器 -->
<!-- <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/> -->
<!-- 處理器適配器 -->
<!-- <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/> -->
<!-- 註解驅動 -->
<mvc:annotation-driven conversion-service="conversionServiceFactoryBean" />
<!-- 配置Conveter轉換器 轉換工廠 (日期、去掉前後空格)。。 -->
<bean id="conversionServiceFactoryBean"
class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<!-- 配置 多個轉換器 -->
<property name="converters">
<list>
<bean class="lx.springmvc.conversion.DateConveter" />
</list>
</property>
</bean>
<!-- 視圖解釋器 -->
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
<!-- 配置異常處理器 -->
<bean class="lx.springmvc.exception.CustomerExceptionResolver"></bean>
<!-- 上傳圖片配置實現類 -->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 上傳圖片的大小 B 5M 1*1024*1024*5 -->
<property name="maxUploadSize" value="5000000" />
</bean>
<!-- SPringmvc的攔截器 -->
<mvc:interceptors>
<!-- 多個攔截器 -->
<mvc:interceptor>
<mvc:mapping path="/**" />
<!-- 自定義的攔截器類 -->
<bean class="lx.springmvc.interceptor.Interceptor1" />
</mvc:interceptor>
<!-- <mvc:interceptor>
<mvc:mapping path="/**"/>
自定義的攔截器類
<bean class="com.itheima.springmvc.interceptor.Interceptor2"/>
</mvc:interceptor> -->
</mvc:interceptors>
</beans>
默認參數綁定
@RequestMapping("/itemEdit")
public ModelAndView toEdit(HttpServletRequest request,HttpServletResponse response
,Model model){
//servlet時代
String id = request.getParameter("id");
Items items = itemService.selectById(Integer.parseInt(id));
ModelAndView mav = new ModelAndView();
mav.addObject("item", items);
mav.setViewName("editItem");
return mav;
}
簡單數據類型綁定
@RequestMapping("/itemEdit")
public ModelAndView toEdit(
/*@RequestParam(value="id",defaultValue="1",required=false)Integer idaa,*/
Integer id,
HttpServletRequest request,HttpServletResponse response
,Model model){
//servlet時代
// String id = request.getParameter("id");
Items items = itemService.selectById(id);
ModelAndView mav = new ModelAndView();
mav.addObject("item", items);
mav.setViewName("editItem");
return mav;
}
綁定pojo
@RequestMapping("/updateitem")
public ModelAndView updateItem(Items item){
itemService.updateItem(item);
ModelAndView mav = new ModelAndView();
mav.setViewName("success");
return mav;
}
綁定包裝的pojo
public class QueryVo {
private Items item;
private List<Items> itemsList;
public List<Items> getItemsList() {
return itemsList;
}
public void setItemsList(List<Items> itemsList) {
this.itemsList = itemsList;
}
public Items getItem() {
return item;
}
public void setItem(Items item) {
this.item = item;
}
}
@RequestMapping("/updateitem")
public ModelAndView updateItem(QueryVo vo){
itemService.updateItem(vo.getItem());
ModelAndView mav = new ModelAndView();
mav.setViewName("success");
return mav;
}
頁面
<td><input type="text" name="item.name" value="${item.name }" /></td>
綁定數組
@RequestMapping("/item/itemsupdate")
public ModelAndView deleteItem(Integer[] ids){
ModelAndView mav = new ModelAndView();
mav.setViewName("success");
return mav;
}
頁面
可以批量刪除和修改
<c:forEach items="${itemList }" var="item" varStatus="s">
<tr>
<td><input type="checkbox" name="ids" value="${item.id}"></td>
<td><input type="text" name="itemsList[${s.index}].name" value="${item.name}"></td>
<td><input type="text" name="itemsList[${s.index}].price" value="${item.price}"></td>
<td><fmt:formatDate value="${item.createtime}" pattern="yyyy-MM-dd HH:mm:ss"/></td>
<%-- <td>${item.createtime }</td> --%>
<td>${item.detail }</td>
<td><a href="${pageContext.request.contextPath }/itemEdit.action?id=${item.id}">修改</a></td>
</tr>
</c:forEach>
Controller方法返回值
1.ModelAndView 無敵的,帶着數據返回視圖路徑。
@RequestMapping("/itemList")
public ModelAndView itemList(){
List<Items> list = itemService.queryItemList();
ModelAndView model = new ModelAndView();
model.addObject("itemList", list);
model.setViewName("itemList");
return model;
}
2.String 返回視圖路徑,model帶數據 (推薦:解耦,數據視圖分離)
@RequestMapping(value = "/itemlist.action")
public String itemList(Model model) {
List<Items> list = itemService.selectItemsList();
model.addAttribute("itemList", list);
return "itemList";
}
3.void ajax請求合適
重定向與轉發
return "redirect:/item/itemlist.action";
return "forward:/item/itemlist.action";
異常處理
CustomerExceptionResolver.java
package lx.springmvc.exception;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
/**
*
* @author lx
*
*/
public class CustomerExceptionResolver implements HandlerExceptionResolver{
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object obj,
Exception e) {
ModelAndView mav = new ModelAndView();
if(e instanceof MessageException){
//已知異常
mav.addObject("error",((MessageException) e).getMsg());
}else{
mav.addObject("error", "未知異常");
}
mav.setViewName("error");
return mav;
}
}
MessageException.java
package lx.springmvc.exception;
public class MessageException extends Exception{
private String msg;
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public MessageException(String msg) {
super();
this.msg = msg;
}
}
上傳圖片
先配置Tomcat虛擬目錄
@RequestMapping(value = "/updateitem.action")
public String updateitem(Items items,MultipartFile pictureFile) throws Exception{
//D:\fileupload
String name = UUID.randomUUID().toString().replaceAll("-", "");
String ext = FilenameUtils.getExtension(pictureFile.getOriginalFilename());
pictureFile.transferTo(new File ("D:\\fileupload\\" + name + "." + ext));
items.setPic(name + "." + ext);
itemService.updateItemsById(items);
return "redirect:/item/itemlist.action";
}
jsp
<!-- 上傳圖片是需要指定屬性 enctype="multipart/form-data" -->
<!-- <form id="itemForm" action="" method="post" enctype="multipart/form-data"> -->
<form id="itemForm" action="${pageContext.request.contextPath }/updateitem.action" method="post" enctype="multipart/form-data">
json數據交互
jsp
<script type="text/javascript">
$(function(){
// alert(1);
var params = '{ "id": 1,"name": "測試商品","price": 99.9,"detail": "測試商品描述","pic": "123456.jpg"}';
$.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);
}
});
});
</script>
@RequestMapping(value = "/json.action")
public @ResponseBody
Items json(@RequestBody Items items){
// System.out.println(items);
return items;
}
@RequestMapping(value = "/json.action")
public void json(@RequestBody Items items){
System.out.println(items);
}
攔截器
package lx.springmvc.interceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
public class Interceptor1 implements HandlerInterceptor{
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object arg2, Exception arg3)
throws Exception {
System.out.println("頁面渲染後");
}
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
throws Exception {
System.out.println("方法後");
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object arg2) throws Exception {
System.out.println("方法前");
// URL http://localhost:8080/springmvc-mybatis/login.action
//URI /login.action
String requestURI = request.getRequestURI();
if(!requestURI.contains("/login")){
String username = (String) request.getSession().getAttribute("USER_SESSION");
if(null == username){
response.sendRedirect(request.getContextPath() + "/login.action");
return false;
}
}
return true;
}
}
@RequestMapping(value = "/login.action",method = RequestMethod.GET)
public String login(){
return "login";
}
@RequestMapping(value = "/login.action",method = RequestMethod.POST)
public String login(String username,HttpSession httpSession){
httpSession.setAttribute("USER_SESSION", username);
return "redirect:/item/itemlist.action";
}