mcfly1992
2021-10-22 13:24
采纳率: 0%
浏览 248
已结题

RestTemplate get请求偶尔会报空指针

使用RestTemplate调用公司用户服务接口,发送get请求,偶尔会报空指针,非必现。用户服务框架为:nodejs+mongodb,请求参数为 mongodb 聚合查询语句。
代码如下:

public HttpEntity createHttpEntity(String body){
        // 解决响应数据可能出现的中文乱码问题
        List<HttpMessageConverter<?>> converterList = restTemplate.getMessageConverters();
        // 移除原来的转换器
        converterList.remove(1);
        // 设置字符编码为utf-8
        HttpMessageConverter<?> converter = new StringHttpMessageConverter(StandardCharsets.UTF_8);
        // 添加新的转换器
        converterList.add(1,converter);
        // 选择性设置请求头信息
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.add("Ocp-Apim-Subscription-Key", "xxxxxxxxxxxxx");
        // Get请求,创建HttpEntity时,请求体传入null即可
        String httpBody = body;
        HttpEntity<String> httpEntity = new HttpEntity<String>(httpBody, httpHeaders);
        return httpEntity;
    }

public MDSUser userInfo(String username) {
        log.info("用户名:"+username);
        MDSUser mdsUser = null;
        HttpEntity httpEntity = createHttpEntity(null);
        String url = EMPLOYEES_BASE + "agg={param}";
        Map<String, String> paramMap = new HashMap<>();
        paramMap.put("param", "[{$match:{$or:[{CommonName:/^"+username+"$/i},{sAMAccountName:/^"+username+"$/i},{userPrincipalName:/^"+username+"$/i}]}},{$project:{Clones:0,Sum:0}},{$limit:1}]");
        log.info("url:"+url);
        UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url);
        URI uri = builder.build().encode().toUri();
        ResponseEntity<JSONArray> response = restTemplate.exchange(url, HttpMethod.GET, httpEntity, JSONArray.class, paramMap);
        JSONArray list = response.getBody();
        if(list.size() > 0){
            mdsUser = JSON.parseObject(JSON.toJSONString(list.get(0)), new TypeReference<MDSUser>(){});
        }
        return mdsUser;
    }

报错信息如下:

2021-10-22 13:07:52.349 [http-nio-8593-exec-1] ERROR o.a.c.c.C.[.[.[.[dispatcherServlet]:175 - Servlet.service() for servlet [dispatcherServlet] in context with path [/purchase-to-pay] threw exception [org.apache.shiro.authc.AuthenticationException: Token失效,请重新登录] with root cause
java.lang.NullPointerException: null
    at org.springframework.web.client.RestTemplate$AcceptHeaderRequestCallback.canReadResponse(RestTemplate.java:862)
    at org.springframework.web.client.RestTemplate$AcceptHeaderRequestCallback.lambda$doWithRequest$0(RestTemplate.java:847)
    at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:174)
    at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1374)
    at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
    at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
    at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
    at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
    at org.springframework.web.client.RestTemplate$AcceptHeaderRequestCallback.doWithRequest(RestTemplate.java:851)
    at org.springframework.web.client.RestTemplate$HttpEntityRequestCallback.doWithRequest(RestTemplate.java:911)
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:733)
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:710)
    at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:598)
    at com.epiroc.purchasetopay.service.impl.UserClientServiceImpl.getUserInfo(UserClientServiceImpl.java:135)
    at com.epiroc.purchasetopay.shiro.authc.ShiroRealm.checkUserTokenIsEffect(ShiroRealm.java:146)
    at com.epiroc.purchasetopay.shiro.authc.ShiroRealm.doGetAuthenticationInfo(ShiroRealm.java:119)
    at org.apache.shiro.realm.AuthenticatingRealm.getAuthenticationInfo(AuthenticatingRealm.java:571)
    at org.apache.shiro.authc.pam.ModularRealmAuthenticator.doSingleRealmAuthentication(ModularRealmAuthenticator.java:180)
    at org.apache.shiro.authc.pam.ModularRealmAuthenticator.doAuthenticate(ModularRealmAuthenticator.java:267)
    at org.apache.shiro.authc.AbstractAuthenticator.authenticate(AbstractAuthenticator.java:198)
    at org.apache.shiro.mgt.AuthenticatingSecurityManager.authenticate(AuthenticatingSecurityManager.java:106)
    at org.apache.shiro.mgt.DefaultSecurityManager.login(DefaultSecurityManager.java:274)
    at org.apache.shiro.subject.support.DelegatingSubject.login(DelegatingSubject.java:260)
    at com.epiroc.purchasetopay.shiro.authc.aop.JwtFilter.executeLogin(JwtFilter.java:53)
    at com.epiroc.purchasetopay.shiro.authc.aop.JwtFilter.isAccessAllowed(JwtFilter.java:39)
    at org.apache.shiro.web.filter.AccessControlFilter.onPreHandle(AccessControlFilter.java:162)
    at org.apache.shiro.web.filter.PathMatchingFilter.isFilterChainContinued(PathMatchingFilter.java:203)
    at org.apache.shiro.web.filter.PathMatchingFilter.preHandle(PathMatchingFilter.java:178)
    at com.epiroc.purchasetopay.shiro.authc.aop.JwtFilter.preHandle(JwtFilter.java:73)
    at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:131)
    at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
    at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:66)
    at org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:449)
    at org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiroFilter.java:365)
    at org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90)
    at org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83)
    at org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:387)
    at org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:362)
    at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at com.alibaba.druid.support.http.WebStatFilter.doFilter(WebStatFilter.java:124)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.boot.actuate.web.trace.servlet.HttpTraceFilter.doFilterInternal(HttpTraceFilter.java:90)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:92)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:117)
    at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:106)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:200)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:834)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1415)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:745)

求解答

  • 好问题 提建议
  • 收藏

11条回答 默认 最新

  • kk1924 2021-10-22 13:43

    这是读取响应时没有反馈的空指针。

    看看你公司的服务是不是偶尔没有返回。

    评论
    解决 无用
    打赏 举报
  • 走一步-再走一步 2021-10-22 13:51

    Token失效,请重新登录

    评论
    解决 无用
    打赏 举报
  • 走一步-再走一步 2021-10-22 13:53

    2021-10-22 13:07:52.349 [http-nio-8593-exec-1] ERROR o.a.c.c.C.[.[.[.[dispatcherServlet]:175 - Servlet.service() for servlet [dispatcherServlet] in context with path [/purchase-to-pay] threw exception [org.apache.shiro.authc.AuthenticationException: Token失效,请重新登录] with root cause
    你看看这个报错信息,是你的token 失效,请求失败

    评论
    解决 无用
    打赏 举报
  • a1767028198 2021-10-22 14:33

    你找找token失效的原因吧

    评论
    解决 无用
    打赏 举报
  • wuli_滔滔 2021-10-22 14:40

    查mongo时候报的空指针么?打个断点看看是网络还是校验的数据有问题把

    评论
    解决 无用
    打赏 举报
  • 少林码农 2021-10-23 16:55
    ResponseEntity<JSONArray> response = restTemplate.exchange(url, HttpMethod.GET, httpEntity, JSONArray.class, paramMap);
        JSONArray list = response.getBody();
    

    初步判断可能是这里的问题,这里发起请求的时候如果出错,服务端没正常返回,response 可能是nil,这个时候调 response.getBody()就会出现空指针,可以在这里加一层异常判断。
    当然最好提供整个调用链的完整代码,这样根据异常中出现的行数也能定位到问题

    评论
    解决 无用
    打赏 举报
  • mcfly1992 2021-10-24 14:07
    
    @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken auth) throws AuthenticationException {
            String token = (String) auth.getCredentials();
            if (token == null) {
                log.info("————————身份认证失败——————————IP地址:  "+ oConvertUtils.getIpAddrByRequest(SpringContextUtils.getHttpServletRequest()));
                throw new AuthenticationException("token为空!");
            }
            // 校验token有效性
            MDSUser loginUser = null;
            try {
                loginUser = this.checkUserTokenIsEffect(token);
            } catch (IOException e) {
                e.printStackTrace();
            }
            return new SimpleAuthenticationInfo(loginUser, token, getName());
        }
    
        /**
         * 校验token的有效性
         *
         * @param token
         */
        public MDSUser checkUserTokenIsEffect(String token) throws AuthenticationException, IOException {
            // 解密获得username,用于和数据库进行对比
            String username = JwtUtil.getUsername(token);
            if (username == null) {
                throw new AuthenticationException("token非法无效!");
            }
    
            // 查询用户信息
            log.info("———校验token是否有效————checkUserTokenIsEffect——————— "+ token);
    
            MDSUser loginUser = userClientService.getUserInfo(username);
    
            if (loginUser == null) {
                throw new AuthenticationException("用户不存在!");
            }
            // 判断用户状态
            if (CommonConstant.DEL_INACTIVE_FLAG.toString().equals(loginUser.getEmpStatusDesc())) {
                throw new AuthenticationException("该用户已注销!");
            }
            // 校验token是否超时失效 & 或者账号密码是否错误
            if (!jwtTokenRefresh(token, username, CommonConstant.VIRTUAL_PASSWORD)) {
                throw new AuthenticationException("Token失效,请重新登录!");
            }
    
            // 查询系统中的 unit
            List<String> unitList = sysMapper.selectSysUnit();
            loginUser.setSysUnitList(unitList);
            Set<String> unitSet = new HashSet<>();
            for(String temp:unitList){
                if(CommonConstant.COUNTRY_HONG_KONG.equals(temp) || CommonConstant.COUNTRY_TAI_WAN.equals(temp)){
                    unitSet.add("HKK");
                }
                unitSet.add(temp);
            }
            List<String> realUnitList = new ArrayList<>(unitSet);
            loginUser.setUnitList(realUnitList);
            // 查询当前用户的 unit_id
            String unitId = sysMapper.getUnitId(loginUser.getUnit());
            loginUser.setUnitId(unitId);
            // 获取用户 role
            RolePojo role = sysMapper.selectRoleCodeByUserId(loginUser.getGuid());
            // 查询不到的都视为普通用户,CNN特殊处理
            String roleCode = "";
            String roleId = "";
            if(role == null){
                roleCode = "2";
                roleId = sysMapper.selectRoleIdByRoleCode(roleCode);
            } else {
                roleCode = role.getRoleCode();
                roleId = role.getRoleId();
            }
            if("HKK".equals(loginUser.getUnit())){
                String realUnit = "";
                if(CommonConstant.HKK_HK_TIMEZONE.equals(loginUser.getTimezone())){
                    realUnit = CommonConstant.COUNTRY_HONG_KONG;
                } else if(CommonConstant.HKK_TW_TIMEZONE.equals(loginUser.getTimezone())){
                    realUnit = CommonConstant.COUNTRY_TAI_WAN;
                }
                loginUser.setUnit(realUnit);
            }
    
            loginUser.setRoleId(roleId);
            loginUser.setRoleCode(roleCode);
            return loginUser;
        }
    
    评论
    解决 无用
    打赏 举报
  • 少林码农 2021-10-24 22:58

    // 校验token是否超时失效 & 或者账号密码是否错误
    if (!jwtTokenRefresh(token, username, CommonConstant.VIRTUAL_PASSWORD)) {
    throw new AuthenticationException("Token失效,请重新登录!");
    应该就是上面的第45行代码这里抛出的异常,在 throw之前打个log看看

    评论
    解决 无用
    打赏 举报
  • 涅米涅米 2021-10-26 18:00

    你贴的错误信息里报的是空指针异常,发生的条件是:

    如果a = b.c.d报空指针,则b或者c可能为null

    结合错误信息

    at com.epiroc.purchasetopay.service.impl.UserClientServiceImpl.getUserInfo(UserClientServiceImpl.java:135)
    

    你应该看UserClientServiceImpl.java的135行是否存在b.c.d这种代码,并看一下b或者c有没有可能在某些情况下为null

    评论
    解决 无用
    打赏 举报
  • LookOutThe 2021-10-28 12:19

    UserClientServiceImpl.java:135 这个代码沾出来看看,这种空指针异常打个断点,就知道那个是null了。

    评论
    解决 无用
    打赏 举报
  • oNuoyi 2021-10-29 13:29

    代码的135行获取用户信息空指针,可以进去 getUserInfo()方法打个断点看看为什么
    at com.epiroc.purchasetopay.service.impl.UserClientServiceImpl.getUserInfo(UserClientServiceImpl.java:135)

    评论
    解决 无用
    打赏 举报

相关推荐 更多相似问题