我遇到此问题:尝试将Cart对象作为JSON返回时出现HttpMediaTypeNotAcceptableException。有什么奇怪的,json映射正在工作,我在这里可以看到: json working
显然我没有为Cart工作,我把所有的getter都放在Cart类中,但仍然有同样的问题。 这是我的控制器方法:
@RequestMapping(value="/{cartId}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public @ResponseBody Cart read(@PathVariable String cartId) {
return cartService.read(cartId);
}
以下是我在pom.xml中添加的依赖项:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.8.5</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.8.5</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.8.5</version>
</dependency>
这是我的购物车类:
@Getter
@Setter
@EqualsAndHashCode
public class Cart implements Serializable {
private static final long serialVersionUID = -4045729241960416615L;
private String cartId;
private Map<String,CartItem> cartItems;
private BigDecimal grandTotal;
public Cart() {
cartItems = new HashMap<String, CartItem>();
grandTotal = new BigDecimal(0);
}
public Cart(String cartId) {
this();
this.cartId = cartId;
}
public void addCartItem(CartItem item) {
String productId = item.getProduct().getId();
if(cartItems.containsKey(productId)) {
CartItem existingCartItem = cartItems.get(productId);
existingCartItem.setQuantity(existingCartItem.getQuantity()+ item.getQuantity());
cartItems.put(productId, existingCartItem);
}
else {
cartItems.put(productId, item);
}
updateGrandTotal();
}
public void removeCartItem(CartItem item) {
String productId = item.getProduct().getId();
cartItems.remove(productId);
updateGrandTotal();
}
public void updateGrandTotal() {
grandTotal= new BigDecimal(0);
for(CartItem item : cartItems.values()){
grandTotal = grandTotal.add(item.getTotalPrice());
}
}
}
这是我的配置
@Configuration
@EnableWebMvc
@ComponentScan("pl.edu.pwr")
public class WebConfig extends WebMvcConfigurerAdapter {
public static final String RESOURCES_LOCATION = "/resources/";
public static final String RESOURCES_HANDLER = RESOURCES_LOCATION + "**";
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(performanceMonitorInterceptor());
registry.addInterceptor(auditingInterceptor());
registry.addInterceptor(promoCodeInterceptor());
}
@Bean
PromoCodeInterceptor promoCodeInterceptor() {
return new PromoCodeInterceptor("OF3RTA", "invalidPromoCode", "products");
}
@Bean
AuditingInterceptor auditingInterceptor() {
return new AuditingInterceptor();
}
@Bean
PerformanceMonitorInterceptor performanceMonitorInterceptor() {
return new PerformanceMonitorInterceptor();
}
/*
* Configure ContentNegotiationManager
*/
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.ignoreAcceptHeader(true).defaultContentType(
MediaType.TEXT_HTML);
}
/*
* Configure ContentNegotiatingViewResolver
*/
@Bean
public ViewResolver contentNegotiatingViewResolver(ContentNegotiationManager manager) {
ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver();
resolver.setContentNegotiationManager(manager);
// Define all possible view resolvers
List<ViewResolver> resolvers = new ArrayList<>();
resolvers.add(jaxb2MarshallingXmlViewResolver());
resolvers.add(jsonViewResolver());
resolvers.add(jspViewResolver());
resolver.setViewResolvers(resolvers);
return resolver;
}
@Bean(name = "filterMultipartResolver")
public CommonsMultipartResolver filterMultipartResolver() {
return new CommonsMultipartResolver();
}
@Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
resolver.setExposeContextBeansAsAttributes(true);
return resolver;
}
/*
* Configure View resolver to provide XML output Uses JAXB2 marshaller to
* marshall/unmarshall POJO's (with JAXB annotations) to XML
*/
@Bean
public ViewResolver jaxb2MarshallingXmlViewResolver() {
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setClassesToBeBound(Product.class);
return new Jaxb2MarshallingXmlViewResolver(marshaller);
}
/*
* Configure View resolver to provide JSON output using JACKSON library to
* convert object in JSON format.
*/
@Bean
public ViewResolver jsonViewResolver() {
return new JsonViewResolver();
}
/*
* Configure View resolver to provide HTML output This is the default format
* in absence of any type suffix.
*/
@Bean
public ViewResolver jspViewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
@Bean
public CharacterEncodingFilter characterEncodingFilter() {
CharacterEncodingFilter filter = new CharacterEncodingFilter();
filter.setEncoding("UTF-8");
filter.setForceEncoding(true);
return filter;
}
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
@Override
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
registry.addResourceHandler(RESOURCES_HANDLER).addResourceLocations(RESOURCES_LOCATION);
}
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
UrlPathHelper urlPathHelper = new UrlPathHelper();
urlPathHelper.setRemoveSemicolonContent(false);
configurer.setUrlPathHelper(urlPathHelper);
}
}
这是POJO的作用:
@Data
@EqualsAndHashCode
@ToString
@XmlRootElement(name="product")
@Getter
@Setter
public class Product {
@Pattern(regexp = "P[0-9]+", message = "Błędny indentyfikator produktu")
@ProductId
private String id;
@Size(min=4, max=50, message="Błędna nazwa produktu. Powinna mieć od {min} do {max} znaków")
private String name;
@Min(value=0, message="Błędna cena produktu. Cena nie może być ujemna.")
@Digits(integer = 8, fraction = 2, message="Błędna cena produktu. Cena powinna składać się z 8 " +
"liczb reprezentujących część całkowitą i 2 cyfr reprezentujących część ułamkową")
@NotNull(message = "Błędna cena produktu. Cena nie może być pusta.")
private BigDecimal unitPrice;
private String description;
private String manufacturer;
@NotNull(message = "Kategoria nie może być pusta")
@Category
private String category;
@Min(value=0, message="Liczba przedmiotów musi być większa lub równa 0.")
private long unitsInStock;
private long unitsInOrder;
private boolean discontinued;
private String condition;
@JsonIgnore
private MultipartFile productImage;
public Product() {
}
public Product(String id, String name, BigDecimal unitPrice) {
this.id = id;
this.name = name;
this.unitPrice = unitPrice;
}
@XmlElement()
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public BigDecimal getUnitPrice() {
return unitPrice;
}
public void setUnitPrice(BigDecimal unitPrice) {
this.unitPrice = unitPrice;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getManufacturer() {
return manufacturer;
}
public void setManufacturer(String manufacturer) {
this.manufacturer = manufacturer;
}
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
public long getUnitsInStock() {
return unitsInStock;
}
public void setUnitsInStock(long unitsInStock) {
this.unitsInStock = unitsInStock;
}
public long getUnitsInOrder() {
return unitsInOrder;
}
public void setUnitsInOrder(long unitsInOrder) {
this.unitsInOrder = unitsInOrder;
}
public boolean isDiscontinued() {
return discontinued;
}
public void setDiscontinued(boolean discontinued) {
this.discontinued = discontinued;
}
public String getCondition() {
return condition;
}
public void setCondition(String condition) {
this.condition = condition;
}
@XmlTransient
public MultipartFile getProductImage() {
return productImage;
}
public void setProductImage(MultipartFile productImage) {
this.productImage = productImage;
}
}
导致问题的原因是什么?
更新 我读到Content Negoatiating View Resolver与@ResponseBody无关。它是适用于Product.java POJO的Content Negoatiating View Resolver,它的@ResponseBody还没有为Cart.java工作。我不知道他们彼此无关。也许现在有人会做什么,以使@ResponseBody工作(返回JSON)。
答案 0 :(得分:0)
我认为您应该尝试使用produce = MediaType.APPLICATION_JSON_VALUE指定返回类型。所以你的代码应该是
@RequestMapping(value="/{cartId}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Cart> read(@PathVariable String cartId) {
Cart cart= cartService.read(cartId);
return new ResponseEntity<>(cart, HttpStatus.OK);
}
答案 1 :(得分:0)
<强>更新强> 你的购物车POJO没有Getters and Setters, 所以你需要:
getCartId setCartId getCartitems setCartitems getGrandTotal setGrandTotal
你可以辩论Cart是否真的是POJO。在我看来,你必须在对象中有很多业务逻辑。我的建议是创建一个CartServices或类似的东西,它管理所有的逻辑。在这种情况下,你可以保持购物车清洁,作为一个真正的POJO。所以只有属性及其吸气剂和制定者。
我相信序列化需要这些getter和setter。
你试过了吗?
@RequestMapping(value="/{cartId}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public @ResponseBody Cart read(@PathVariable String cartId) {
return cartService.read(cartId);
}
答案 2 :(得分:0)
<强>更新强>: 我找到了解决方案。我要做的是删除contentNegotiatingViewResolver以及与之相关的所有内容。在我做完之后,一切都开始起作用了。