springboot 增加自定义参数解析器

有些时候我们需要在后台处理一些常用的通用参数,

如:获取客户端ip,又比如 用户登录完成后,后台返回前天一个登陆成功后的token,每次调用接口都在header或者url中带上token,后台根据这个token去校验用户(登录、权限等等)

这个时候,在后台添加一个注解,并对该注解通过参数解析器进行处理,可以很好的解决上上述问题。

扩展:为什么不用过滤器、拦截器或者切面来实现? 

——过滤器一般用于过滤web请求,是用来处理servlet的,一般用来处理web页面相关的设置

——拦截器用于拦截action,即后台action方法,拦截器会拦截所有的action,而上述问题可能涉及到只有部分接口需要解析某个参数

——切面,切面通过设置pointcut切入点,切入方法,理论上可以解决上述问题,但有点大材小用

 参考:

https://www.cnblogs.com/2YSP/p/10253927.html

https://www.jianshu.com/p/5790ea68f522

https://www.jianshu.com/p/838cd9956a14

https://www.jianshu.com/p/f4653fe8c935

以增加ip解析器为例

实现

创建IP地址获取工具类IpUtil.java

package com.flysand.demo.util;

import org.apache.commons.lang3.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.net.InetAddress;
import java.net.UnknownHostException;

/**
 * @author flysand
 **/
public class IpUtil {

    private static final String LOCALHOST = "127.0.0.1";

    private static final String INTERNAL_HOST = "0:0:0:0:0:0:0:1";

    private static final String UNKNOWN = "unknown";

    public static String getIp(HttpServletRequest request) {
        String ipAddress;
        try {
            ipAddress = request.getHeader("x-forwarded-for");
            if (ipAddress == null || ipAddress.length() == 0 || UNKNOWN.equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getHeader("Proxy-Client-IP");
            }
            if (ipAddress == null || ipAddress.length() == 0 || UNKNOWN.equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getHeader("WL-Proxy-Client-IP");
            }
            if (ipAddress == null || ipAddress.length() == 0 || UNKNOWN.equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getRemoteAddr();
                if (ipAddress.equals(LOCALHOST) || ipAddress.equals(INTERNAL_HOST)) {
                    // 根据网卡取本机配置的IP
                    InetAddress inetAddress = null;
                    try {
                        inetAddress = InetAddress.getLocalHost();
                    } catch (UnknownHostException e) {
                        e.printStackTrace();
                    }
                    ipAddress = inetAddress != null ? inetAddress.getHostAddress() : null;
                }
            }
            // 对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割
            if (StringUtils.isNotBlank(ipAddress) ) {
                ipAddress = ipAddress.split(",")[0];
            }
        } catch (Exception e) {
            ipAddress = "";
        }
        return ipAddress;
    }
}

增加ip注解Ip.java

package com.flysand.demo.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author flysand
 **/
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface Ip {
}

增加ip解析器——新增的参数解析器需要加入到spring容器中

IpAddressArgumentResolver.java ,需实现HandlerMethodArgumentResolver接口,并重写方法 

package com.flysand.demo.resolver;

import com.flysand.demo.annotation.Ip;
import com.flysand.demo.util.IpUtil;
import org.springframework.core.MethodParameter;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
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.http.HttpServletRequest;

/**
 * 自定义ip地址参数解析器
 *
 * @author flysand on 2019/07/12
 **/
@Component
public class IpAddressArgumentResolver implements HandlerMethodArgumentResolver {

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.hasParameterAnnotation(Ip.class);
    }

    /**
     * 返回ip
     * @param parameter
     * @param mavContainer
     * @param webRequest
     * @param binderFactory
     * @return
     * @throws Exception
     */
    @Override
    public String resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer, NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {
        HttpServletRequest request = (HttpServletRequest) webRequest.getNativeRequest();
        return IpUtil.getIp(request);
    }
}

自定义springmvc配置,加入ip参数解析器

package com.flysand.demo.config;

import com.flysand.demo.resolver.IpAddressArgumentResolver;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.web.PageableHandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.List;

/**
 * @author flysand
 **/

@Configuration
@EnableWebMvc
public class MyMvcConfig implements WebMvcConfigurer {

    @Autowired
    private IpAddressArgumentResolver ipAddressArgumentResolver;

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        resolvers.add(new PageableHandlerMethodArgumentResolver());
     // 加入ip解析器 resolvers.add(ipAddressArgumentResolver); } }

 

使用 - Controller代码片段

@GetMapping("/getIp")
    public String getIp(@Ip String ip) {
        return ip;
    }

 

执行过程:

启动springboot,spring容器加载新增的ip解析器,页面访问getIp接口,根据@ip注解,找到对应的ip解析器,返回ip

 

posted @ 2019-07-12 15:22  飞沙流年  阅读(806)  评论(0)    收藏  举报