如何在 Spring Boot 中解决“提取类型 [class com.*] 的响应时出错”?
Posted
技术标签:
【中文标题】如何在 Spring Boot 中解决“提取类型 [class com.*] 的响应时出错”?【英文标题】:How to solve "Error while extracting response for type [class com.*" in Spring Boot? 【发布时间】:2020-05-02 08:28:40 【问题描述】:您可能想跳到下面的我的更新 2
我有一个可以工作的 RestController,因为当我直接从浏览器访问它时,它会返回一个 JSON 响应。但是,当我在不同的有界上下文中从服务发送请求时,我收到错误:
"timestamp":1579095291446,"message":"Error while extracting response for type
[class com.path.to.contexttwo.client.dto.WorkerDetails] and content type [application/json]; nested exception is
org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error:
Unexpected character ('<' (code 60)): expected a valid value (JSON String, Number, Array, Object or token 'null', 'true' or 'false');
nested exception is com.fasterxml.jackson.core.JsonParseException:
Unexpected character ('<' (code 60)):
expected a valid value (JSON String, Number, Array, Object or token 'null', 'true' or 'false')\n at [Source: (PushbackInputStream);
line: 1, column: 2]","details":"uri=/context-two/register-new"
这是我的代码:
RestController
package com.path.to.contextone.aplication.presentation;
@RestController
@RequestMapping(path = "/iacess", produces = "application/json")
@CrossOrigin(origins = "*")
public class IAccessRestController
UserRepository userRepo;
IAcessService iaccessService;
EntityLinks entityLinks;
@Autowired
public IAccessRestController(
UserRepository userRepo,
IAcessService iaccessService,
EntityLinks entityLinks)
this.userRepo = userRepo;
this.iaccessService= iaccessService;
this.entityLinks = entityLinks;
@GetMapping("/get-worker-details/userName")
public WorkerDetails getWorkerDetails(@PathVariable String userName)
User user = userRepo.findByUsername(userName);
WorkerDetails workerDetails = new WorkerDetails();
workerDetails.setUserId(userId);
workerDetails.setGender(user.gender());
workerDetails.setFirstName(user.getFirstName());
workerDetails.setLastName(user.getLastName());
workerDetails.setPhoneNumber(user.getPhoneNumber());
if (workerDetails != null)
return workerDetails;
return null;
RestClient
package com.path.to.contexttwo.client;
// imports omitted, as well as other code
@Service
public class IAcessRestClientImpl implements IAcessRestClient
private final RestTemplate restTemplate;
@Autowired
public IAcessRestClientImpl(
final RestTemplate restTemplate
)
this.restTemplate = restTemplate;
@Override
public WorkerDetails getWorkerDetailsByName(final String userName) throws URISyntaxException
Map<String,String> urlVariables = new HashMap<>();
urlVariables.put("userName", userName);
return restTemplate.getForObject(
"http://localhost:8080/iacess/get-worker-details/userName",
WorkerDetails.class,
urlVariables
);
配置
package com.path.to.contexttwo.configuration;
@Configuration
@EnableWebMvc
public class RestClientConfig
@Bean
public RestTemplate restTemplate()
final RestTemplate restTemplate = new RestTemplate();
List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
List<MediaType> mediaTypes = new ArrayList<MediaType>();
mediaTypes.add(MediaType.APPLICATION_JSON);
converter.setSupportedMediaTypes(mediaTypes);
messageConverters.add(converter);
restTemplate.setMessageConverters(messageConverters);
restTemplate.getInterceptors().add(new JsonInterceptor());
return restTemplate;
工人详情
package com.path.to.contexttwo.client.dto;
import java.io.Serializable;
import java.util.Objects;
public class WorkerDetails implements Serializable
private long userId;
private String gender;
private String firstName;
private String lastName;
private String phoneNumber;
public WorkerDetails()
this.userId = -1;
this.gender = null;
this.firstName = null;
this.lastName = null;
this.phoneNumber = null;
// omitted all args constructor, getters, setters, equals, hascode, toString for simplicity
WorkerDetails 也存在于包 com.path.to.contextone.ohs_pl 中;
我已经尝试了3天,阅读和调试,无济于事。调试器似乎显示当 RestTemplate 分析 WorkerDetails.class 时发生错误。
我也尝试在所有配置类中使用 ComponentScan,因为文件位于单独的包(有界上下文)中,但没有成功。
我可以只使用调用 IAcessRestClient 的类中的 UserDetailsRepository 来获取 WorkerDetails,但这会使两个不同的有界上下文依赖于同一个数据库架构。
任何帮助将不胜感激。 我可以根据请求发布附加代码。
提前致谢
更新 @SB 要求输入参数。这是发送参数的类:
CompanyServiceImpl
package com.path.to.contexttwo.domain.services;
// imports
@Service
public class CompanyServiceImpl implements CompanyService
private CompanyRepository companyRepository;
private CompanyWorkerRepositoery companyWorkerRepositoery;
private WorkerDetailsClient workerDetailsClient;
private WebApplicationContext applicationContext;
@Autowired
CompanyServiceImpl (
CompanyRepository companyRepository,
CompanyWorkerRepositoery companyWorkerRepositoery,
WorkerDetailsClient workerDetailsClient,
WebApplicationContext applicationContext
)
this.companyRepository = companyRepository;
this.companyWorkerRepositoery = companyWorkerRepositoery;
this.workerDetailsClient = workerDetailsClient;
this.applicationContext = applicationContext;
@Transactional
public Company criateCompany(CompanyDTO dto) throws URISyntaxException
if (dto.getLegalyAuthorized() == true && dto.getTerms() == true)
Company company = new Company(
dto.getCompanyName(),
dto.getStateId()
);
company = CompanyRepository.save(company);
// when saving the company, we also need some details from the current logged in user which can be
// retrieved from the idendity and access bounded context. We need those details to be saved in this context
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
String name = auth.getName();
WorkerDetails workerDetails = WorkerDetailsClient.getWorkerDetailsByName(
name
);
// ... we can't reach the rest of the code anyway, so we omitted
这是我直接访问 RestController 时得到的响应:
"userId":127,"gender":"M","firstName":"Primeiro","lastName":"Último","phoneNumber":"922222222"
更新 2
注释掉 .anyRequest().authenticated() 并且一切运行正常!因此,它一直与 Spring Security 有关。多可惜。现在将尝试在启用安全性的情况下使事情正常进行。由于重定向到登录页面,我收到了 html 作为响应。正确实施了身份验证(带有基本身份验证的令牌请求)并且一切正常。
谢谢大家!
【问题讨论】:
您是否尝试将 username 替换为用户名的实际值:“localhost:8080/iacess/get-worker-detailsuserName”? 请分享您的输入参数和预期响应(当您从浏览器运行请求时有效。 @JavaBoy,是的,我尝试使用硬编码的 URI,但得到了同样的错误。其实调试的时候,url是正确的。 @SB,请查看我对问题的更新。谢谢! 根据错误,似乎有一些 HTML 代码是响应的一部分。您能否检查响应数据中的特殊字符? 【参考方案1】:试试:
return restTemplate.getForObject(
"http://localhost:8080/iacess/get-worker-details/" + userName,
WorkerDetails.class);
【讨论】:
谢谢,JavaBoy!这实际上是我的第一次尝试。我很高兴按照书中的示例更改为当前形式。现在将恢复。以上是关于如何在 Spring Boot 中解决“提取类型 [class com.*] 的响应时出错”?的主要内容,如果未能解决你的问题,请参考以下文章
Spring Boot 2.0:Spring Boot 如何解决项目启动时初始化资源
在测试中运行应用程序时如何解决 GOOGLE_APPLICATION_CREDENTIALS,Spring Boot?
如何解决tomcat的问题? Spring-Boot“扫描失败”
ControllerAdvice 的异常处理程序在使用 Spring Boot 的 Rest API 获取请求中不起作用。如何解决?