最近、プロジェクトが分割されたので、ちなみに他のプロジェクトのコードを見てみると、まだ使っていないものがいくつかあることに気付きました. @ControllerAdvice アノテーションなど。
@ControllerAdvice アノテーションの紹介
この注釈は、コントローラーの機能拡張であるコントローラーで最初に使用されます。これは aop のアイデアの実装です. インターセプト ルールに従って, このアノテーションは、ルールに準拠するコントローラーをブロックし、いくつかの機能強化を行うのに役立ちます. このアノテーションは通常、次の 3 つのアノテーションと連携するか、これらの 3 つのアノテーションが 3 つの機能を実現し@ExceptionHandler
ます@InitBinder
強化 @ModelAttribute
。
まず、この注釈のソース コードを見てください。
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package org.springframework.web.bind.annotation;
import java.lang.annotation.Annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;
import org.springframework.stereotype.Component;
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface ControllerAdvice {
@AliasFor("basePackages")
String[] value() default {};
@AliasFor("value")
String[] basePackages() default {};
Class<?>[] basePackageClasses() default {};
Class<?>[] assignableTypes() default {};
Class<? extends Annotation>[] annotations() default {};
}
basePackages 属性で傍受するコントローラーを指定できることがソースコードからわかります。属性を追加しないと、すべてのコントローラーがインターセプトされます。インターセプト ルールを記述する方法はいくつかあります。
@ControllerAdvice//拦截所有controller
@ControllerAdvice("com.lsl.mylsl")//拦截com.lsl.mylsl包及子包下的controller
@ControllerAdvice(basePackages = "com.lsl.mylsl")//同上
@ControllerAdvice(basePackages = {"com.lsl.mylsl","com.lsl.mjx"})//拦截多个不同包下的controller
@ControllerAdvice(annotations={CustomAnnotation.class})//如果自定义一个注解@CustomAnnotation,拦截有这个注解的controoler
@ControllerAdvice アノテーションの使用
最初にコードに行きましょう。これはコントローラーの傍受構成クラスです
package com.lsl.mylsl.config;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.beans.propertyeditors.StringTrimmerEditor;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@ControllerAdvice//拦截所有controller
public class ControllerHandlerConfig {
/**
* 对所有controller中的方法报HttpRequestMethodNotSupportedException异常就行全局处理
* @return
*/
@ResponseBody
@ExceptionHandler(value = {HttpRequestMethodNotSupportedException.class})
public Map exception405(){
Map exMessage = new HashMap();
exMessage.put("code",405);
exMessage.put("message","请求类型错误");
return exMessage;
}
/**
* 预设全局数据一
* @param request
* @return
*/
@ModelAttribute(name = "userType")
public String preParam(HttpServletRequest request){
String name = request.getHeader("type");
return name;
}
/**
* 预设全局数据二
* @return
*/
@ModelAttribute(name = "userMap")
public Map preParamMap (){
Map<String , Object> map = new HashMap<>();
map.put("stuName","lsl");
map.put("stuAge","21");
return map;
}
/**
* 请求参数预处理
* 把string参数左右两边的空格去掉
* 把日期格式"2022-10-28"转换成date类型输出
* @param dataBinder
*/
@InitBinder
public void processParam(WebDataBinder dataBinder){
/*
* 创建一个字符串微调编辑器
* 参数{boolean emptyAsNull}: 是否把空字符串("")视为 null
*/
StringTrimmerEditor trimmerEditor = new StringTrimmerEditor(true);
/*
* 注册自定义编辑器
* 接受两个参数{Class<?> requiredType, PropertyEditor propertyEditor}
* requiredType:所需处理的类型
* propertyEditor:属性编辑器,StringTrimmerEditor就是 propertyEditor的一个子类
*/
dataBinder.registerCustomEditor(String.class, trimmerEditor);
//同上,这里就不再一步一步讲解了
dataBinder.registerCustomEditor(Date.class,
new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), false));
}
}
これがコントローラークラスのコードです
package com.lsl.mylsl.controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/api/mylsl")
public class MyHandlerController {
@ResponseBody
@PostMapping(value = "handler",produces = "application/json;charset=UTF-8")
public Map handlerTest(@ModelAttribute("userType") String userType1, Model model){
Map result = new HashMap();
System.out.println("userType="+userType1);
result.put("userType",userType1);
Map<String, Object> asMap = model.asMap();
Map userMap = (Map) asMap.get("userMap");
String stuName = userMap.get("stuName").toString();
String stuAge = userMap.get("stuAge").toString();
System.out.println("stuName=" + stuName + ",stuAge=" +stuAge);
result.put("stuName",stuName);
result.put("stuAge",stuAge);
return result;
}
@ResponseBody
@GetMapping("prParam")
public Map<String, Object> test(String str, Date date) throws Exception {
Map<String, Object> map = new HashMap<String, Object>();
map.put("str", str);
map.put("data", date);
return map;
}
}
1.グローバル例外を処理し、 グローバル例外処理@ControllerAdvice
に協力する @ExceptionHandler
MyHandlerController のコードを見ると、handlerTest() メソッドが post リクエストであることがわかります. postman を使用して get リクエストを送信すると、ControllerHandlerConfig の exception405() によって処理されます.
2.グローバルデータをプリセットします。@ControllerAdvice
プリセットされたグローバル データと連携します @ModelAttribute
。
ControllerHandlerConfig の preParam() と preParamMap() は、MyHandlerController の handlerTest() で取得されるプリセット グローバル データを書き込む 2 つの方法を提供します。
3. リクエスト パラメータの前処理。@ControllerAdvice
連携して @InitBinder
リクエストパラメータの前処理を実現
下図の get リクエストを実行すると、str の dhk の前後にスペースがあり、date の日付形式が 2022-10-28 であることがわかります.最終出力はスペースを削除し、日付形式は date- になります。出力形式を入力します。