SpringMVC

image.png

image.png

SpringMVC

01.SpringMVC架構

image.png

關於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三大組件:

處理映射器:制定url到指定方法的映射

處理器適配器:根據不同的Handler找到不同的處理器適配器去執行Handler

視圖解析器:根據不同的視圖去解析(視圖可以是jsppdfwordfreeMark

<?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 整合後springdao層的配置

    數據源

    會話工廠

    掃描Mapper

2)service層

    事務   ApplicationContext-trans.xml

    @Service註解掃描 ApplicationContext-service.xml

3)controller層

    SpringMvc.xml

    註解掃描:掃描@Controller註解

    註解驅動:替我們顯示的配置了最新版的處理器映射器和處理器適配器

    視圖解析器:顯示的配置是爲了在controller中不用每個方法都寫頁面的全路徑

4)web.xml

    springMvc前端控制器配置

    spring監聽

04-1.參數綁定

1. 默認支持類型(修改功能,modelrequeststringmodelview

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. StringModel(重定向和轉發、相對路徑和絕對路徑)

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.springmvcstruts2不同

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. 請求方法限定

image.png

09.異常處理器

springmvc在處理請求過程中出現異常信息交由異常處理器進行處理,自定義異常處理器可以實現一個系統的異常處理邏輯。

異常處理思路

系統中異常包括兩類:預期異常和運行時異常RuntimeException,前者通過捕獲異常從而獲取異常信息,後者主要通過規範代碼開發、測試通過手段減少運行時異常的發生。

系統的dao、servicecontroller出現都通過throws Exception向上拋出,最後由springmvc前端控制器交由異常處理器進行異常處理,如下圖:

exception.png

自定義異常類

爲了區別不同的異常通常根據異常類型自定義異常類,這裏我們創建一個自定義系統異常,如果controller、servicedao拋出此類異常說明是系統預期處理的異常信息。

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

image.png

2. 新建xxx.xml文件, 我這裏命名爲img.xml

image.png

3. xml文件中配置如下內容:

<Context path="/img" reloadable="true" docBase="D:\img" />

image.png

path : 瀏覽器訪問目錄, 與xml文件名必須一致

       docBase : 虛擬目錄

4. Tomcatconf\web.xml文件中找到如下配置:

listings 修改成true

image.png

5. 通過瀏覽器訪問

      http://ip:端口號/虛擬目錄, 如可以顯示,虛擬目錄配置成功

image.png

2. 導包

CommonsMultipartResolver解析器依賴commons-fileuploadcommons-io,加入如下jar包:

image.png

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接口將讀到的內容轉換爲jsonxml等格式的數據並綁定到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默認用MappingJacksonHttpMessageConverterjson數據進行轉換,需要加入jackson的包,如下:

image.png

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中沒有動詞,只有名詞。沒有參數

資源操作:使用putdeletepostget,使用不同方法對資源進行操作。分別對應添加、刪除、修改、查詢。一般使用時還是postgetPutDelete幾乎不使用。

需求

RESTful方式實現商品信息查詢,返回json數據

添加DispatcherServletrest配置(在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中的模板變量映射到功能處理方法的參數上。

image.png

@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實現:

image.png

// 查詢商品列表
@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>

2. 實現登錄攔截過程

image.png




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