springboot自定義註解解析HandlerMethodArgumentResolver通過反射賦值返回

  • HandlerMethodArgumentResolver類似於攔截器,是一個參數解析器,我們可以通過寫一個類實現HandlerMethodArgumentResolver接口來實現對COntroller層中方法參數的修改。

自定義解析器需要實現HandlerMethodArgumentResolver接口,HandlerMethodArgumentResolver接口包含兩個接口函數:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package org.springframework.web.method.support;

import org.springframework.core.MethodParameter;
import org.springframework.lang.Nullable;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;

public interface HandlerMethodArgumentResolver {
    boolean supportsParameter(MethodParameter var1);

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

當supportsParameter返回True時,纔會調用supportsParameter。

自定義一個解析器  其中CurrentStudent.class是我自定義的註解

package com.yitianren.yitiantestspringboot.service.impl;

import com.yitianren.yitiantestspringboot.util.CurrentStudent;
import org.springframework.core.MethodParameter;
import org.springframework.stereotype.Service;
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;

import java.lang.reflect.*;
import java.util.*;

/**
 * @Description 攔截所有訪問,自定義自己需要的業務邏輯
 * @Author yitianRen
 * @Date 2019/9/17 14:33
 * @Version 1.0
 **/
@Service
public class CurrentStudentMethodArgumentResolver implements HandlerMethodArgumentResolver {

    public CurrentStudentMethodArgumentResolver() {
    }

    @Override
    public boolean supportsParameter(MethodParameter methodParameter) {

        if (methodParameter.hasParameterAnnotation(CurrentStudent.class)) {
            System.out.println(methodParameter.toString() + ":存在註解CurrentStudent");
            return true;
        }
/*
        if(methodParameter.getParameterType().isAssignableFrom(StudentVo.class)){
            System.out.println(methodParameter.getParameterType()+":有StrudentVo類");
            return true;
        }*/

        return false;
    }

    @Override
    public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {
        // 獲取Controller中參數的類型
        Class clazz = methodParameter.getParameterType();
        Object target = clazz.newInstance();
        Field f = clazz.getDeclaredField("createDate");
        f.setAccessible(true);
        f.set(target, new Date());
        return target;
    }


}

自定義註解:

package com.yitianren.yitiantestspringboot.util;

import java.lang.annotation.*;

/**
 * @Author: yitianRen
 * @Description:
 * 註解的作用範圍:@Target
 * 生命週期:@Retention
 * 作用範圍:包、類、字段、方法、方法的參數、局部變量
 * 生命週期:源文件SOURCE、編譯CLASS、運行RUNTIME
 * @Date: 14:24 2019/9/17
 * @Param:
 * @Return:
*/

@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)//
@Documented
public @interface CurrentStudent {

    String value() default "尼古拉斯趙四";//默認值爲 尼古拉斯趙四

}

在使用自定義解析器時,需要把解析器註冊到spring容器中,配置文件註冊一下:

package com.yitianren.yitiantestspringboot.config;

import com.yitianren.yitiantestspringboot.service.impl.CurrentStudentMethodArgumentResolver;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;

import java.util.List;

/**
 * @Description TODO
 * @Author yitianRen
 * @Date 2019/9/17 15:41
 * @Version 1.0
 **/
@SpringBootApplication
public class WebConfig extends WebMvcConfigurationSupport {

    @Override
    protected void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {

        // 註冊CurrentStudentMethodArgumentResolver的參數分解器
        argumentResolvers.add(new CurrentStudentMethodArgumentResolver());
    }
}

實體類

package com.yitianren.yitiantestspringboot.entity;

import java.util.Date;
import com.baomidou.mybatisplus.annotations.TableField;
import com.baomidou.mybatisplus.annotations.TableName;

import java.io.Serializable;

/**
 * <p>
 * 
 * </p>
 *
 * @author yitianren
 * @since 2019-09-10
 */
@TableName(value = "STUDENT")
public class StudentVo implements Serializable {

    private static final long serialVersionUID = 1L;

    @TableField("SId")
    private String SId;
    @TableField("Sname")
    private String Sname;
    @TableField("Sage")
    private Date Sage;
    @TableField("Ssex")
    private String Ssex;

    @TableField(exist = false)
    private Date createDate;

    public Date getCreateDate() {
        return createDate;
    }

    public void setCreateDate(Date createDate) {
        this.createDate = createDate;
    }

    public String getSId() {
        return SId;
    }

    public void setSId(String SId) {
        this.SId = SId;
    }

    public String getSname() {
        return Sname;
    }

    public void setSname(String Sname) {
        this.Sname = Sname;
    }

    public Date getSage() {
        return Sage;
    }

    public void setSage(Date Sage) {
        this.Sage = Sage;
    }

    public String getSsex() {
        return Ssex;
    }

    public void setSsex(String Ssex) {
        this.Ssex = Ssex;
    }

    @Override
    public String toString() {
        return "Student{" +
        ", SId=" + SId +
        ", Sname=" + Sname +
        ", Sage=" + Sage +
        ", Ssex=" + Ssex +
        "}";
    }
}

Controller:

package com.yitianren.yitiantestspringboot.controller;


import com.yitianren.yitiantestspringboot.entity.StudentVo;
import com.yitianren.yitiantestspringboot.service.StudentService;
import com.yitianren.yitiantestspringboot.util.CurrentStudent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author yitianren
 * @since 2019-09-10
 */
@RestController
public class StudentController {

    @Autowired
    private StudentService studentService;

    @RequestMapping("/student")
    public @ResponseBody Object hello() {
        return studentService.findAllStudent();
    }

    @RequestMapping(value = "/testAnnotation")
    public @ResponseBody Object testAnnotation(@CurrentStudent StudentVo studentVo) {
        return studentVo;
    }

}

結果:這裏沒有對時間進行格式化

目錄結構

我們可以通過實現HandlerMethodArgumentResolver接口來實現對自定義的參數進行解析。
比如可以解析自定義的時間格式、自定義解析Map對象等這些spring原本不支持的對象格式。

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