记录

首先贴上今天发现的牛皮的springcloud文章

https://blog.csdn.net/qq_42046105

 

使用springcloud框架feign组件时:

1 标识是前端调用还是feign内部调用的解决办法:自定义FeignDefaultConfiguration类,实现RequestInterceptor接口中的apply方法,该接口会拦截feign调用内部服务的请求,首先根据项目需求把字段重新设置一遍,比如token;然后在请求头里面设置一个标识当前请求为内部请求的值即可。

@Configuration
@Slf4j
public class FeignDefaultConfiguration implements RequestInterceptor {
    /**
     * 携带token参数调用feign服务
     *
     * @param requestTemplate
     */
    @Override
    public void apply(RequestTemplate requestTemplate) {
        try {
            //当前请求
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            //根据当前请求获取token
            String tokenFromRequest = HttpRequestUtil.getTokenFromRequest(request);
            requestTemplate.header("Authorization", "Bearer " + tokenFromRequest);
        } catch (Exception e) {
            log.error("拦截器封装token失败,URL:"+requestTemplate.url(), e);
        } finally {
            //区分当前请求是否为内部调用
            requestTemplate.header(BaseConstant.FEIGN_SERVER_REQUEST_KEY, "true");
        }
    }

}

2 feign服务之前调用发生异常时,可以自定义FeignErrorDecoder实现ErrorDecoder接口的decode方法

@Configuration
@Slf4j
public class FeignErrorDecoder implements ErrorDecoder {


    @Override
    public Exception decode(String s, Response response) {
        try {
            if (response.body() != null) {
                String body = Util.toString(response.body().asReader());
                Map mapType = JSON.parseObject(body, Map.class);
                Object trace = mapType.get("trace");
                if (trace != null) {
                    log.error(trace.toString());
                }
                String message = mapType.get("message").toString();
                String exceptionClass = mapType.get("exception").toString();
                Class exClass = Class.forName(exceptionClass);
                //根据参数类型获取相应的构造函数
                Constructor constructor = exClass.getConstructor(String.class);
                Exception ex = (Exception) constructor.newInstance(message);
                if(ex instanceof FeignServerException) {
                	return new ServiceException(ex.getMessage());
                }
                return ex;
            }
            return new ServiceException("远程未返回数据");
        } catch (Exception e) {
            return new ServiceException(e.getMessage());
        }
    }
}

3 如果服务A调用服务B,B发生异常,处理流程如下(实现准备好全局异常处理类@ControllerAdvice):

   a. 异常被B服务的全局异常处理器捕获,判断请求头中是否有标识为内部请求的信息

   b. 发现当前请求内部请求时,B服务不处理异常,选择直接抛出异常

   c. 异常被第二步中的处理机制处理,封装成对应的异常对象抛到A服务

   d. 异常对象被A服务的全局异常处理器捕获,根据异常的种类返回对应信息给前端

 @ExceptionHandler(HystrixRuntimeException.class)
    @ResponseBody
    public Object hystrixRuntimeException(HystrixRuntimeException e) throws Exception {
        log.error("调用feign服务业务逻辑异常", e);
        Throwable throwable = e.getCause();
        if (throwable instanceof RuntimeException) {
            RuntimeException runtimeException = (RuntimeException) throwable;
            if (runtimeException instanceof BeanValidateException
                    || runtimeException instanceof ParseExcelException
                    || runtimeException instanceof CheckParamLogicException
                    || runtimeException instanceof IllegalArgumentException
                    ) {
                return paramValidateExceptionHandler(runtimeException);
            }
            if (runtimeException instanceof TokenInvalidException) {
                return tokenInvalidExceptionHandler(runtimeException);
            }
            if (runtimeException instanceof ServiceException) {
                return serviceException(runtimeException);
            }
        }
        return new ApiResult(ApiResultCodeEnum.E0000);
    }

 

4 项目启动后的初始化操作:自定义类实现CommandLineRunner接口的run方法

5 JWT身份验证流程(JWT介绍请移步http://www.ruanyifeng.com/blog/2018/07/json_web_token-tutorial.html

   a 用户输入用户名,密码登陆,后台接收到请求,验证用户信息

   b 验证通过后,设置过期时间,用户信息(如username,注意不要吧密码填充进jwt字符串中)等,生成一个jwt字符串标识(3个部分,用.分隔)

   c 把jwt字符串存入缓存,用username作为key存入缓存,并放在header中返回给前端

   d 前端每次请求都带上这个jwt字符串,后台每次接受到请求的时候,判断请求头中或者cookie中是否有token,如果有,就根据解析出token中的信息,比如username,然后用username从缓存中获取token

   e 如果取到了不为空,就放行,并且重新设置redis中的token过期时间,否则就返回验证未通过。

 

 

 

 

1  在项目中的实体类中,一定要检查有没有set方法,很多莫名其妙的错误或者意料之外的结果都是因为这个

2   在mybatis项目中。字段定义的时候能少用下划线就少用下划线,别等到写xml的时候后悔

3  但实际结构确实截然不同 com.immer.monitor.persistence 是单个文件夹 而 com/immer/monitor/persistence 是一个文件夹嵌套 会  导致资源文件not found 的问题,而且很难排查得到

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值