注解参数解析器,设置参数至请求上下文

         很多情况下,需要通过外部方法获取业务特定的公共的实例信息,例如在集成用户信息时,无状态协议下从缓存中获取用户认证信息等等,这里介绍一种自定义注解方式获取用户认证信息,这样在集成用户信息时,只要在web请求上使用一个注解就能获取.示例如下:

1:定义一个注解

import java.lang.annotation.*;

/**
 * token获取用户Java对象注解类.
 *
 * @author Hohn
 */
@Documented
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface Token4User {
    //需要转换的类
   // Class<?> requireClass();
}
2:定义一个类,.实现springframework的  HandlerMethodArgumentResolver方法,这里要封装自己解析对应的实例参数方法,这里需要注意的是在获取需要的实例信息时应该抛出一个要自定义一个异常,避免参数解析器方法出现业务异常或获取不到实例时告诉程序,否则在web请求上使用注解出现异常导致程序挂断.

import com.ahies.common.exception.ItsmUnauthorizedException;
import com.ahies.stater.redis.service.StringRedisServiceImpl;
import com.google.gson.Gson;
import org.apache.commons.lang.StringUtils;
import org.springframework.core.MethodParameter;
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;
import java.util.Map;
/**
 * 用于方法参数上加Token4User标签获取当前登录用户的信息.
 * <p>
 *
 * @author Hohn
 */
@Component
public class UserBeanArgumentResolver implements HandlerMethodArgumentResolver {

    private static final String USER_TOKEN = "Token";

    /**
     * =======用户id=====================================================
     */
    private static final String USER_ID = "id";

    /**
     * =======用户姓名=====================================================
     */
    private static final String USER_NAME = "userName";


    /**
     * =======登录id=====================================================
     */
    private static final String USER_LOGIN_NAME = "loginName";


    /**
     * 过滤出符合条件的参数,这里指的是加了 Token4User 注解的参数
     *
     * @param parameter
     * @return
     */
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.hasParameterAnnotation(Token4User.class);
    }

    @Override
    public UserLoginInfo resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) {
        HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
        //从请求头中获取用户json
        //srping容器中注入bean  [HandlerMethodArgumentResolver没有被spring实例化的对象,不能被IoC容器管理, 使用@Autowired注解没有配置required=false的情况下spring发现没有该对象会直接抛出Exception]
        StringRedisServiceImpl redisService = SpringContextUtils.getBean(StringRedisServiceImpl.class);
        String token = servletRequest.getHeader(USER_TOKEN);
        if (StringUtils.isBlank(token)) {
            token = servletRequest.getParameter(USER_TOKEN);
        }
        if (StringUtils.isBlank(token)) {//解析异常抛出自定义异常

            throw new ItsmUnauthorizedException("请先授权登录,");
        }
        String userJson = null;
        try {
            //从缓存中获取用户信息
            userJson = redisService.get(token);
        } catch (Exception e) {
            e.printStackTrace();
        }

        if (StringUtils.isBlank(userJson)) {//解析异常抛出自定义异常

            throw new ItsmUnauthorizedException("请先授权登录");
        }
        if (StringUtils.isNotEmpty(userJson)) {
            //字符串转json Map对象
            Gson gs = new Gson();
            try {
                Map<String, Object> map = gs.fromJson(userJson, Map.class);
                UserLoginInfo userLoginInfo = new UserLoginInfo();

                if (map != null && map.size() > 0) {
                    //设置id
                    userLoginInfo.setId((String) map.get(USER_ID));
                    //设置token
                    userLoginInfo.setToken(token);
                    //设置登录id
                    userLoginInfo.setLoginName((String) map.get(USER_LOGIN_NAME));
                    //设置姓名
                    userLoginInfo.setUserName((String) map.get(USER_NAME));

                    return userLoginInfo;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        return null;
    }

}
 

3.自定义异常类

/**
 *
 * 自定义异常处理类
 */
public class ItsmUnauthorizedException extends RuntimeException{

    private static final long serialVersionUID = 1L;

    public ItsmUnauthorizedException(String message) {
        super(message);
    }
}

4.全局异常捕获类

import com.ahies.common.exception.ItsmUnauthorizedException;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.propertyeditors.StringTrimmerEditor;
import org.springframework.context.MessageSource;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@ControllerAdvice
public class ControllerSetup {

    @InitBinder
    public void initBinder(WebDataBinder binder){
        StringTrimmerEditor stringTrimmerEditor=new StringTrimmerEditor(true);
        binder.registerCustomEditor(String.class,stringTrimmerEditor);
    }

    private static Logger log = LoggerFactory.getLogger(ControllerSetup.class);

   /**
     * 处理org.springframework.validation.Validatororg.hibernate.validatorjavax.validation错误.
     *
     * @param request 请求.
     * @param bindException bindException.
     * @return Map.
     * @throws Exception
     */
    @ExceptionHandler(value = BindException.class)
    @ResponseBody
    public Map<String, Object> jsonErrorHandler(HttpServletRequest request, BindException bindException) throws Exception {
        Map<String, Object> map = Maps.newHashMapWithExpectedSize(2);

        List<FieldError> errors = bindException.getBindingResult().getFieldErrors();

        List<Map<String, String>> messageList = Lists.newArrayListWithExpectedSize(errors.size());

        for(int i = 0, size = errors.size(); i < size; i++) {
            // 字段名称 - 提示信息.
            Map<String, String> fieldMap = Maps.newHashMapWithExpectedSize(2);
            FieldError fieldError = errors.get(i);
            fieldMap.put("field", fieldError.getField());
            fieldMap.put("prompt", fieldError.getDefaultMessage());

            messageList.add(fieldMap);
        }
        map.put("status", HttpStatus.BAD_REQUEST.value());
        map.put("message", messageList);
        return map;
    }

    @ExceptionHandler(value = ItsmUnauthorizedException.class)
    @ResponseBody
    public Map<String, Object> jsonErrorHandler(ItsmUnauthorizedException e) throws Exception {
        log.info("系统异常", e);
        Map<String, Object> map = Maps.newHashMapWithExpectedSize(2);
        map.put("status", HttpStatus.FORBIDDEN.value());
        map.put("message", e.getMessage());
        return map;
    }

    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public Map<String, Object> jsonErrorHandler(HttpServletRequest request, Exception e) throws Exception {
        log.info("系统异常", e);
        Map<String, Object> map = Maps.newHashMapWithExpectedSize(2);
        map.put("status", HttpStatus.INTERNAL_SERVER_ERROR.value());
        map.put("message", e.getMessage());
        return map;
    }

}

注册自定义参数解析器

import com.ahies.common.pojo.UserBeanArgumentResolver;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

import java.util.List;

@Configuration
public class WebMvcConfigurerConfigure  extends WebMvcConfigurerAdapter {
    //实例化用户信息参数注解类
    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
        argumentResolvers.add(new UserBeanArgumentResolver());
        super.addArgumentResolvers(argumentResolvers);
    }
}

业务中有时需要将获取的参数再次封装,如再次获取会消耗系统大量内存或不必要的服务调用,此时,可以把参数设置到回话的上下文中:

RequestContextHolder.getRequestAttributes().setAttribute("User",userBean, RequestAttributes.SCOPE_REQUEST);//第三个参数设置参数在回话中的位置

Object user = RequestContextHolder.getRequestAttributes().getAttribute("User", RequestAttributes.SCOPE_REQUEST);

set方法第三个参数用来指定参数保存在上下文中的位置:

/**
 * Constant that indicates request scope.
 */
int SCOPE_REQUEST = 0;

/**
 * Constant that indicates session scope.
 * <p>This preferably refers to a locally isolated session, if such
 * a distinction is available (for example, in a Portlet environment).
 * Else, it simply refers to the common session.
 */
int SCOPE_SESSION = 1;

/**
 * Constant that indicates global session scope.
 * <p>This explicitly refers to a globally shared session, if such
 * a distinction is available (for example, in a Portlet environment).
 * Else, it simply refers to the common session.
 */
int SCOPE_GLOBAL_SESSION = 2;


附类似的转载博文:

http://blog.csdn.net/u010187242/article/details/73647670



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值