Feign反序列化错误
起因:在导出excel的时候, 发现有的字段不能正常输出。
其中对应的字段是 cPremium和cPopularizeFee,但是按照这样的命名却读不到数据。debug发现数据源的字段数据变成了cpremium和cpopularizeFee,好神奇啊。。为啥嘞?
在反复的测试中,总结下,通过feign后key的转换关系如下:
- aaAAAAA->aaAAAAA
 - aAA->aaa
 - aA->aa
 - A->a
 
最后总结 :变量的前两个字母要么全部大写,要么全部小写。
参考:
https://blog.csdn.net/john1337/article/details/105077234
https://blog.csdn.net/u011742227/article/details/42425065/?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_title-5&spm=1001.2101.3001.4242
麻烦的spring-security
为了设计而设计的spring-security, 把用户验证大致分为两步:校验用户是否存在->校验密码。
    @Override
    public void configure(AuthenticationManagerBuilder auth) {
        auth.authenticationProvider(authenticationProvider1());
    }
    @Bean
    public DaoAuthenticationProvider authenticationProvider1() {
        DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
        provider.setHideUserNotFoundExceptions(false);
        provider.setUserDetailsService(loginUserService);
        provider.setPasswordEncoder(passwordEncoder());
        return provider;
    }
第一个坑:loginUserService校验用户是否存在,不存在的话会抛UsernameNotFoundException异常,如果存在就进行下一步密码的校验。但是实际情况是第一步抛了异常,第二步还是会走,解决方法是在第二步进行特殊的判断:
 //这一行是可以抛出 UsernameNotFoundException关键 否则永远会屏蔽 loginUserService中抛出的此异常
            @Override
            public boolean matches(CharSequence rawPassword, String encodedPassword) {
                //这一行是可以抛出 UsernameNotFoundException关键 否则永远会屏蔽 loginUserService中抛出的此异常
                if ("userNotFoundPassword".equals(encodedPassword)) {
                    return true;
                }
            }
第二个坑:UsernameNotFoundException异常抛了,但是我们密码校验需要修改,加一个参数,但是org.springframework.security.crypto.password.PasswordEncoder#matches方法是写死的2个参数,一个新的,一个旧的做密码对比。最终解决方法是在这个类里,注入了HttpServletRequest,然后用它来获取新加的参数。感觉还是用org.springframework.web.servlet.HandlerInterceptor的老方法,拦截器来处理比较清晰明了,用security,要配置更多,写更多的类,学习成本比较高,有问题还比较难解决。
循环依赖报错
项目启动时报错:
Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'orderServiceImpl': Bean with name 'orderServiceImpl' has been injected into other beans [weChatNotifyServiceImpl] in its raw version as part of a circular reference, but has eventually been wrapped. This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.
应该是bean循环引用的问题 weChatNotifyServiceImpl中 引入了 orderServiceImpl
然后orderServiceImpl 中也引入了 weChatNotifyServiceImpl。
说好的不是spring bean依赖注入的时候不会出现循环引用的问题了吗?
- 通过2级缓存,避免了普通
bean循环引用。 - 通过3级缓存,避免
Aop中代理类循环引用问题。 
原来在因为开启了@EnableAsync异步调用,bean注入时和aop一样会生成新的代理类,此时如果出现循环引用还是或出现问题。
解决方案: 加@Lazy注解
加入日志的traceId
- 
项目日志中添加
实现很简单在拦截器中,利用MDC添加到日志: 
    public static void addLogTraceId(HttpServletRequest request) {
        String ipAddress = getIpAddress(request);
        String uuid = ParamUtil.toString(UUID.randomUUID()).replaceAll("-", "");
        MDC.put("requestId", "[TraceID:" + uuid + ",IP:" + ipAddress + "]");
    }
然后添加日志配置:
 logging:
  pattern:
    console: '[%d{yyyy-MM-dd HH:mm:ss.SSS} %5p %t] [%c{1}] %M:%L - %X{requestId} %m%n'
    file: '[%d{yyyy-MM-dd HH:mm:ss.SSS} %5p %t] [%c{1}] %M:%L - %X{requestId} %m%n'
日志中就会这样打印:
[2022-02-10 15:00:30.009 DEBUG pool-6-thread-1] [c.b.b.d.o.O.selectSynList] debug:159 - [TraceID:6f62d621ea82443c890d45bb5924e8a2,IP:] ==> Parameters: 2022-02-10 14:50:
- 异步线程保持一致
 
//相关的异步方法比较少,所以简单实现
String logId = MDC.get("requestId");
executorService.execute(() -> orderService.orderPush(requestJsonStr, logId));
executorService.shutdown();
- 
微服务保持一致
思路是放到header里,然后下游的服务从header中取就可以了。 
- 上游添加利用
feign的拦截器去批量添加: 
@Component
public class FeignConfiguration implements RequestInterceptor {
    @Override
    public void apply(RequestTemplate requestTemplate) {
        requestTemplate.header("request-id", MDC.get("requestId"));
    }
}
- 下游获取,在拦截器中添加到
MDC: 
@Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) {
        String requestId = httpServletRequest.getHeader("request-id");
        addLogTraceId(requestId);
        return true;
    }
当然了还有spring cloud sleuth+zipkin的方案,可以在网页直观的查看,请求的调用链路,以及访问时间。还有基于javaagent的skywalking,0入侵代码。










网友评论