将POJO作为JSON返回时的HttpMediaTypeNotAcceptableException

时间:2017-01-11 09:10:42

标签: java json spring

我遇到此问题:尝试将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)。

3 个答案:

答案 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以及与之相关的所有内容。在我做完之后,一切都开始起作用了。