springMVC 擴展點


SpringMVC擴展

流程圖

一般需要擴展的地方包括:

  • HandlerMethodArgumentResolver
    可以定制自己的參數接收方式 和@PathVariable同級
  • HandlerMethodReturnValueHandler
    定制返回方式,和@ResponseBody同級
  • MessageConverter
    如果采用@ResponseBody,可以根據不同的Class和MediaType定制不同的Converter

核心代碼

自定義HandlerMethodArgumentResolver


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.lexiaoyao.springmvc_config.pojo.Result;
import com.lexiaoyao.springmvc_config.pojo.annotations.ResultBody;
import org.apache.tomcat.util.http.fileupload.IOUtils;
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;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;

/**
 * 自定義HandlerMethodArgumentResolver
 * 用於處理被@ResultBody標記的變量
 */
public class ResultBodyArgumentHandler implements HandlerMethodArgumentResolver {

    /**
     * 處理@ResultBody注解
     *
     * @param methodParameter
     * @return
     */
    @Override
    public boolean supportsParameter(MethodParameter methodParameter) {
        return methodParameter.hasParameterAnnotation(ResultBody.class);
    }

    /**
     * 這個方法的返回值作為反射處理的參數
     *
     * @param methodParameter
     * @param modelAndViewContainer
     * @param nativeWebRequest
     * @param webDataBinderFactory
     * @return
     * @throws Exception
     */
    @Override
    public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {
        //獲取HttpServletRequest類
        HttpServletRequest request = (HttpServletRequest) nativeWebRequest.getNativeRequest();
        int length = request.getContentLength();
        if (length == 0) return null;

        //從inputStream中獲取字節流
        ServletInputStream inputStream = request.getInputStream();
        byte[] bytes = new byte[length];
        //通過工具類讀取
        IOUtils.readFully(inputStream, bytes);

        //將byte[]轉為javabean
        Result o = JSON.parseObject(bytes, Result.class);
        JSONObject jsonObject = (JSONObject) o.getData();
        //將jsonObject轉換為實際的javaBean
        //methodParameter.getParameterType() 獲取參數class
        return jsonObject.toJavaObject(methodParameter.getParameterType());
    }
}
      @Configuration
      public class SpringMVCConfig implements WebMvcConfigurer
    /**
     * 注冊新的參數處理器
     *
     * @param resolvers
     */
    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        resolvers.add(new ResultBodyArgumentHandler());
    }

定義Converter

注入FastJsonHttpMessageConverter


import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import com.lexiaoyao.springmvc_config.handler.ResultBodyArgumentHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.nio.charset.Charset;
import java.util.List;

@Configuration
public class SpringMVCConfig implements WebMvcConfigurer {

    //跨域設置
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        //針對的映射
        registry.addMapping("/**")
                //針對的origin域名
                .allowedOrigins("*")
                //針對的方法
                .allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS")
                //是否允許發送Cookie
                .allowCredentials(true)
                //從預檢請求得到相應的最大時間,默認30分鍾
                .maxAge(3600)
                //針對的請求頭
                .allowedHeaders("*");
    }

    /**
     * 注冊新的參數處理器
     *
     * @param resolvers
     */
    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        resolvers.add(new ResultBodyArgumentHandler());
    }

//    /**
//     * 如果是json的MediaType,不能使用這種方式,應該使用直接注入的方式
//     *
//     * @param converters
//     */
//    @Override
//    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
//        converters.add(getFastJsonHttpMessageConverter());
//    }

    /**
     * 采用fastJson來處理json轉換
     *
     * @return
     */
    @Bean
    public FastJsonHttpMessageConverter fastJsonHttpMessageConverter() {
        return getFastJsonHttpMessageConverter();
    }

    /**
     * 定制化FastJsonHttpMessageConverter
     *
     * @return
     */
    private FastJsonHttpMessageConverter getFastJsonHttpMessageConverter() {
        FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter();
        fastJsonHttpMessageConverter.setFastJsonConfig(getFastJsonConfig());
        fastJsonHttpMessageConverter.setDefaultCharset(Charset.forName("UTF-8"));
        return fastJsonHttpMessageConverter;
    }

    private FastJsonConfig getFastJsonConfig() {
        FastJsonConfig fastJsonConfig = new FastJsonConfig();
        fastJsonConfig.setSerializerFeatures(SerializerFeature.WriteNullStringAsEmpty);
        return fastJsonConfig;
    }
}

note

建議采用直接將converter注入的方式來新增converter。
因為在springMVC中,實際上維護着一個converter的list,默認是按照從上往下,如果有滿足條件的converter就采用這個當前的converter來處理當前值。
我們自己定義的converter,如果是FastJsonHttpMessageConverter,通過實現WebMvcConfig接口,實現extendMessageConverters的方式擴展,那么MappingJackson2HttpMessageConverter在這個隊列的靠前的位置,所有會優先於FastJsonHttpMessageConverter處理json的數據返回。

git

https://github.com/lexiaoyao1995/springmvcdemo


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM