1. 程式人生 > >前端Ajax/JS/HTML+後端SpringMVC(二)

前端Ajax/JS/HTML+後端SpringMVC(二)

serialize 關於 2個 ets test 得到 return 2.4 提交

1. jQuery AJAX

1.1. jQuery框架中的ajax()函數

在應用了jQuery框架後,調用ajax()函數即可發出AJAX請求,並獲取響應結果,該函數的參數必須是JSON對象,通常,在JSON對象中封裝的屬性有:

  • url:處理請求的URL,也可以理解為將請求發送到哪個URL,取值可以是絕對路徑,或相對路徑,但是,不可以跨域

  • data:請求的數據,通常是username=xx&password=xx&phone=xx類似的格式,可以通過字符串拼接得到該值,也可以通過jQuery中的$("#form-id").serialize()函數將整個表單中所有控件的值都封裝起來,使用這個函數時,是以控件的名稱與控件中的值進行封裝的,所以,需要註意各控件的名稱

  • type:請求的類型,可以是getpost

  • dataType:響應的數據的類型,可以是textxmljson,主流做法多使用json,但是,具體使用哪一種,取決於服務器響應時給出的Response Headers中的Content-Type

  • beforeSend:發出請求之前如何處理,取值是函數,用於決於具體執行的代碼,多用於例如:將發出請求的按鈕禁用,以避免在沒有響應之前卻反復提交請求

  • success:成功響應後如何處理,取值是函數,success對應的函數只在正確的響應情況下被執行,如果服務端的響應碼是302、4xx、5xx,並不會導致success對應的函數被執行!該處理函數可以添加參數,參數即是服務端響應的數據,如果dataType

    已經設置為json,則此處的函數參數類型就是JSON對象

  • error:響應出錯如何處理,取值是函數,只要響應碼是3xx、4xx、5xx,都會導致error對應的函數被執行!

2. 異常的處理

2.1. 設計案例

創建簡單的案例,發出/test/null.do請求,服務端將產生NullPointerException,發出/test/array.do請求,服務端將產生ArrayIndexOutOfBoundsException

2.2. 創建並完成案例

創建Maven Project,Group Id使用com.company.spring,Artifact Id使用SPRINGMVC-04-EXCEPTION

檢查spring-mvc.xml的配置,在組件掃描的包下創建TestController,使用@Controller@RequestMapping("/test")註解:

@Controller
@RequestMapping("/test")
public class TestController {
}

然後添加2個方法處理2個請求,並在處理過程中,使得程序出現對應的異常:

@RequestMapping("/null.do")
public String handleNull() {
    String str = null;
    str.length();
    return null;
}

@RequestMapping("/array.do")
public String handleArray() {
    int[] arr = { 0 };
    System.out.println(arr[10]);
    return null;
}

2.3. 【不推薦】使用SimpleMappingExceptionResolver

如果沒有對異常進行處理,默認的處理方式下,會把異常的跟蹤信息顯示在頁面中,這種做法會導致較差的用戶體驗,並且可能對外泄露了當前的業務邏輯甚至是項目機密。但是,頻繁的使用try...catch語法來處理異常,則很大程度上增加了編碼的難度,也不易於統一規劃和處理!

SpringMVC中提供了SimpleMappingExceptionResolver,可以配置異常與轉發到的視圖的對應關系,也就是說:只要出現了某種異常,就直接轉發到某個視圖,而不需要編寫try...catch相關代碼:

<!-- 處理異常 -->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
    <!-- 異常與轉發到的視圖的映射 -->
    <property name="exceptionMappings">
        <props>
            <prop key="java.lang.NullPointerException">error_null</prop>
            <prop key="java.lang.ArrayIndexOutOfBoundsException">error_array</prop>
        </props>
    </property>
</bean>

使用這種做法最大的問題:無法針對某個問題進行詳細的處理!也無法將具體的錯誤信息顯示在頁面中!

2.4. 【推薦】使用@ExceptionHandler

在控制器類中自定義某個方法,用於統一處理異常,這個方法需要使用@ExceptionHandler註解,並且,可以使用Exception作為方法的參數:

@ExceptionHandler
public String handleException(Exception e) {
    return null;
}

每當出現異常時,SpringMVC就會自動調用以上方法,並且將捕獲的異常對象作為調用該方法的參數,則處理時:

@ExceptionHandler
public String handleException(Exception e, HttpServletRequest request) {
    String message = e.getMessage();
    if (e instanceof ArrayIndexOutOfBoundsException) {
        request.setAttribute("msg", message);
        return "err_array";
    }
    return null;
}

註意:嘗試轉發數據時,可以使用HttpServletRequest參數,也可以使用ModelAndView返回值,卻不可以使用ModelMap參數。

2.5. Q&A

Q:使用@ExceptionHandler和配置SimpleMappingExceptionResolver這2個做法來處理異常會沖突嗎?

A:兩者同時使用,代碼並不會出現錯誤,但是,對於同一個異常,註解方式優先。

Q:使用@ExceptionHandler這種方式處理異常時,可以不使用轉發作為處理方式,而是直接響應JSON數據嗎?

A:可以!在處理異常的方法之前添加@ResponseBody註解,並且將方法的返回值調整為ResponseResult即可(需要事先添加Jackson依賴,配置註解驅動)

Q:使用@ExceptionHandler這種方式處理異常時,處理異常的方法可以作用於其它控制器類中處理請求方法嗎?

A:不可以!常規做法是定義BaseController類,在這個類中添加處理異常的方法,然後,項目中所有其它的控制器類都繼承自這個類!例如:

public abstract class BaseController {

    @ExceptionHandler(ServiceException.class)
    @ResponseBody
    public ResponseResult handleException(ServiceException e) {
        // 準備返回值
        ResponseResult rr = new ResponseResult();
        // 向返回結果中封裝錯誤信息
        rr.setMessage(e.getMessage());
        
        // 判斷異常
        if (e instanceof UserNotFoundException) {
            rr.setState(401);
        } else if (e instanceof PasswordNotMatchException) {
            rr.setState(402);
        } else if (e instanceof UpdateException) {
            rr.setState(500);
        } else {
            rr.setState(600);
        }
        
        // 返回
        return rr;
    }
    
}

2.6. 小結

在開發項目時,業務層會在出現各種業務錯誤的情況下拋出不同的業務異常,例如此前項目中的UserNotFoundExceptionPasswordNotMatchException……而控制器層調用業務層的方法時,就需要處理這些異常,而某些異常出現的次數可能較多,反復的使用try...catch不便於統一處理,代碼也顯得非常復雜!

SpringMVC提供的統一處理異常的方式有2種,分別是使用SimpleMappingExceptionResolver和使用@ExceptionHandler註解,前者在處理方面非常有局限性!一般對於業務異常的處理,推薦使用後者!

關於業務異常的處理,通常會在項目中創建BaseController,然後在這個類中編寫處理異常的方法,項目中實際使用的其它控制器類都應該繼承自BaseController

前端Ajax/JS/HTML+後端SpringMVC(二)