收藏

记一些问题处理

2022-02-10  本文已影响0人  go_2021

Feign反序列化错误

起因:在导出excel的时候, 发现有的字段不能正常输出。

其中对应的字段是 cPremium和cPopularizeFee,但是按照这样的命名却读不到数据。debug发现数据源的字段数据变成了cpremium和cpopularizeFee,好神奇啊。。为啥嘞?
在反复的测试中,总结下,通过feign后key的转换关系如下:

最后总结 :变量的前两个字母要么全部大写,要么全部小写。

参考:
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依赖注入的时候不会出现循环引用的问题了吗?

原来在因为开启了@EnableAsync异步调用,bean注入时和aop一样会生成新的代理类,此时如果出现循环引用还是或出现问题。

解决方案: 加@Lazy注解

参考:https://segmentfault.com/a/1190000018835760

加入日志的traceId

  1. 项目日志中添加
    实现很简单在拦截器中,利用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:
  1. 异步线程保持一致
//相关的异步方法比较少,所以简单实现
String logId = MDC.get("requestId");
executorService.execute(() -> orderService.orderPush(requestJsonStr, logId));
executorService.shutdown();
  1. 微服务保持一致
    思路是放到header里,然后下游的服务从header中取就可以了。
@Component
public class FeignConfiguration implements RequestInterceptor {
    @Override
    public void apply(RequestTemplate requestTemplate) {
        requestTemplate.header("request-id", MDC.get("requestId"));
    }
}
@Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) {
        String requestId = httpServletRequest.getHeader("request-id");
        addLogTraceId(requestId);
        return true;
    }

当然了还有spring cloud sleuth+zipkin的方案,可以在网页直观的查看,请求的调用链路,以及访问时间。还有基于javaagentskywalking,0入侵代码。

上一篇 下一篇

猜你喜欢

热点阅读