SpringMVC 擴充套件

GrowthRoad發表於2024-08-17

SpringMVC 擴充套件

1. RESTFul 風格

RESTFul是一種基於 HTTP 和標準化設計原則的軟體架構風格,用於設計和實現可靠、可擴充套件和易於整合的 Web 服務和應用程式。

要求:

  • 每一個URI 代表一種資源,是名詞,也就是 url中不要帶動作

  • 客戶端使用 GET、POST、PUT、DELETE 表示操作方式的動詞對服務端資源進行操作,GET獲取資源,進行查詢操作。POST進行插入操作,PUT進行更新操作,DELETE 進行刪除操作。

使用 RESTFul 風格,url可能是相同的,但是透過 請求方式的不同可以區別不同的請求

操作 傳統風格 REST風格
儲存 /crud/saveEmp url:/crud/emp 請求方式:POST
刪除 /crud/deleteEmp?id=1 url:/crud/emp/1 請求方式:DELETE
更新 /crud/updateEmp url:/crud/emp 請求方式:PUT
查詢 /crud/selectEmp?id=1 url:/crud/emp/1 請求方式:GET

RESTFul 並不是只能用 路徑傳參。在某些情況下也可以使用 param傳參

當查詢的是一個單一的資源,傳入的是一個id值,這時候可以用 路徑傳參,比如根據id 查詢一個使用者

當查詢的是一個集合資源,傳入的是一個範圍值,這時可以用 param傳參,比如分頁查詢或多條件模糊查詢等

而POST 和 PUT 用 請求體傳參即可,即json資料

2. 全域性異常處理

當出現異常時,有兩種解決方案:

  • 程式設計式異常處理:在業務邏輯程式碼中顯示地進行異常處理,用try catch

  • 宣告式異常處理:將業務邏輯程式碼與異常處理分離,透過配置進行統一的管理,互不干擾

步驟:

  1. 宣告異常處理控制器類

    定義一個類,在類上使用 @ControllerAdvice 或 @RestControllerAdvice 註解,捕捉全域性異常

  2. 在這個類中,宣告異常處理handler方法,透過 @ExceptionHandler 註解指定相應的異常

當出現異常時,就會走對應的handler方法

@ControllerAdvice 和 @RestControllerAdvice 的區別是:前者可以返回檢視,可以重定向和轉發。後者返回字串

@RestController
@RequestMapping("exception")
public class ExceptionController {
    @GetMapping("data")
    public String data(){
        String name = null;
        name.toString();
        return name;
    }
}

上面會出現空指標異常

@RestControllerAdvice
public class GlobalExceptionHandler {
​
    @ExceptionHandler(NullPointerException.class)
    public Object NullPointerException(NullPointerException e){
        return e.getMessage();
    }
}

定義了一個全域性異常處理類,裡面透過 @ExceptionHandler 指定了 如果出現 NullPointerException異常就會走下面的方法,在該方法中處理異常即可。

注意:需要保證 @RestControllerAdvice 被掃描到

3. 攔截器

攔截器可以在執行handler 之前和之後或者在DispatcherServlet返回時執行一些程式碼,加上一些功能,如登入校驗等。和Filter功能類似。

攔截器和過濾器的區別:

相似點:

  • 攔截:必須把請求攔住,才能執行後續操作

  • 過濾:攔截器或過濾器存在的意義就是對請求進行統一處理

  • 放行:對請求執行了必要操作後,放請求過去,讓它訪問原本想要訪問的資源

不同點:

  • 工作平臺不同

    • 過濾器工作在Servlet容器中

    • 攔截器工作在SpringMVC 的基礎上

  • 攔截的範圍

    • 過濾器能夠攔截到的最大範圍是整個web應用

    • 攔截器能夠攔截到的最大範圍是整個SpringMVC 負責的請求

  • IOC 容器支援

    • 想得到過濾器ioc容器需要呼叫專門的工具方法,spring並沒有支援

    • 攔截器就放在ioc容器中,可以直接從ioc容器中裝配元件,可以直接得到ioc容器的支援

使用

  1. 建立一個類,實現 HandlerInterceptor 介面,重寫三個方法

    • preHandler 在處理請求的目標Handler方法之前執行,返回true就是放行,返回false攔截

    • postHandler 在目標handler方法之後執行,如果handler報錯則不執行

    • afterCompletion 渲染檢視後執行(在最後)一定執行

  2. 將攔截器加入到 ioc容器中

    在配置類裡重寫 addInterceptor 方法,呼叫 引數 InterceptorRegistry的 registry方法,傳入的引數是 new

    攔截器類

public class MyInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return HandlerInterceptor.super.preHandle(request, response, handler);
    }
​
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }
​
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }
}

引數:request 請求物件、response 響應物件、handler 呼叫的物件方法、modelAndView 返回的檢視和共享域物件、Exception 異常物件

@Configuration
@ComponentScan({"com.ztone.controller","com.ztone.error"})
@EnableWebMvc
public class MvcConfig implements WebMvcConfigurer {
​
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new MyInterceptor());
    }
}

必須繼承 WebMvcConfigurer

上面這種方式是攔截了所有的請求,如果想要攔截指定請求可以追加呼叫 addPathPatterns

@Override
public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(new MyInterceptor()).addPathPatterns("/user/data");
}

也可以排除攔截某些請求,呼叫 excludePathPatterns

@Override
public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(new MyInterceptor())
            .addPathPatterns("/user/**").excludePathPatterns("/user/data");
}

如果有多個攔截器,那麼先宣告的攔截器優先順序高,優先順序高的在外層,也就是 優先順序高的攔截器先執行 preHandler,後執行 postHandler 和 afterCompletion

4.引數校驗註解

jsr303 是Java為Bean資料合法性校驗提供的標準框架

註解 規則
@Null 標註值必須為null
@NotNull 標註值不可null
@AssertTrue 標註值必須為true
@AssertFalse 標註值必須為false
@Max(value) 標註值必須小於等於value
@Min(value) 標註值必須大於等於value
@DecimalMin(value) 標註值必須大於等於value
@DecimalMax(value) 標註值必須小於等於value
@Size(max,min) 標註值必須在max和min範圍內
@Digits(integer,fratction) 標註值必須是數字,並且在可接受的範圍內
@Past 標註值只能用於日期型,且必須是過去的日期
@Future 標註值只能用於日期型,且必須是未來的日期
@Pattern(value) 標註值必須符合指定的正規表示式
@Email 標註值必須是格式正確的Email
@Length 標註值字串大小必須在指定的範圍內
@NotEmpty 標註集合長度不為空
@Range 標註值必須在指定的範圍內
@NotBlank 標註值字串不為null,且不是空字串

使用:

  1. 需要匯入依賴

    <dependency>
        <groupId>org.hibernate.validator</groupId>
        <artifactId>hibernate-validator</artifactId>
        <version>8.0.0.Final</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator-annotation-processor -->
    <dependency>
        <groupId>org.hibernate.validator</groupId>
        <artifactId>hibernate-validator-annotation-processor</artifactId>
        <version>8.0.0.Final</version>
    </dependency>
  2. 在實體類的屬性上使用註解

    @Data
    public class User {
    ​
        @NotBlank
        private String name;
    ​
        @Length(min = 6, max = 12)
        private String password;
    ​
        @Min(0)
        private int age;
    }
  3. 在接收引數的地方使用 @Validated

    @Controller
    public class UserController {
    
        @GetMapping("data")
        public String data(@Validated @RequestBody User user){
            return null;
        }
    }

當傳來的引數沒有透過校驗,那麼就會直接向前端報異常

如果想要自定義向前端的輸出,可以在引數的後面緊挨著一個 引數 BindingResult

在handler中呼叫 該物件的 hasErrors方法,一旦報錯就會返回 true

@Controller
public class UserController {

    @GetMapping("data")
    public String data(@Validated @RequestBody User user, BindingResult bindingResult){
        if (bindingResult.hasErrors()) {
            //處理向前端的返回資料
        }
        return null;
    }
}

相關文章