1. 程式人生 > 實用技巧 >springboot自定義引數解析HandlerMethodArgumentResolver

springboot自定義引數解析HandlerMethodArgumentResolver

自定義解析器需要實現HandlerMethodArgumentResolver介面,HandlerMethodArgumentResolver介面包含兩個介面函式:

public interface HandlerMethodArgumentResolver {
    boolean supportsParameter(MethodParameter var1);

    @Nullable
    Object resolveArgument(MethodParameter var1, @Nullable ModelAndViewContainer var2, NativeWebRequest var3, @Nullable WebDataBinderFactory var4) throws Exception;
}

自定義一個解析器CurrentUserMethodArgumentResolver

我們在解析器中返回一個固定的UserBeannew UserBean(1L,"admin"),實際情況是從Session、資料庫或者快取中查。

import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

/**
 * 用於繫結@CurrentUser的方法引數解析器
 *
 * @author lism
 */
public class CurrentUserMethodArgumentResolver implements HandlerMethodArgumentResolver {

    public CurrentUserMethodArgumentResolver() {
    }

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        if (parameter.getParameterType().isAssignableFrom(UserBean.class) && parameter.hasParameterAnnotation(CurrentUser.class)) {
            return true;
        }
        return false;
    }

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
        CurrentUser currentUserAnnotation = parameter.getParameterAnnotation(CurrentUser.class);
        //從Session 獲取使用者
        Object object = webRequest.getAttribute(currentUserAnnotation.value(), NativeWebRequest.SCOPE_SESSION);
//從  accessToken獲得使用者資訊
       if (object == null) {
            String token = webRequest.getHeader("Authorization");
            if (token == null) {
                token = webRequest.getParameter("accessToken");
            }
            //為了測試先寫死使用者名稱
            //TODO: 取真實使用者
            return new UserBean(1L,"admin");
        }
        return object;
    }
}

自定義註解@CurrentUser

import java.lang.annotation.*;

/**
 * <p>綁定當前登入的使用者</p>
 * <p>不同於@ModelAttribute</p>
 *
 * @author lism
 */
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CurrentUser {

    /**
     * 當前使用者在request中的名字
     *
     * @return
     */
    String value() default "user";

}

在控制器中使用@CurrentUser

在控制器方法上加入@CurrentUser UserBean userBean即可自動注入userBean的值

@RestController
@RequestMapping(value = "/test")
public class TestController  {

    /**
     * 根據name查詢
     *
     * @param request
     * @return
     */
    @RequestMapping(value = "/testCurrentUser", method = RequestMethod.POST, produces = "application/json", consumes = "application/json")
    @ResponseBody
    public void test(@CurrentUser UserBean userBean, @RequestBody SubjectRequest request) {
        String createdBy = userBean.getUsername();
        log.info(createdBy);
    }
}

User實體UserBean

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserBean implements Serializable {
    private Long id;
    private String username;
}

總結

我們可以通過實現HandlerMethodArgumentResolver介面來實現對自定義的引數進行解析。
比如可以解析自定義的時間格式、自定義解析Map物件等這些spring原本不支援的物件格式。