415不支持的媒体类型+弹簧

Joa*_*ena 1 java spring jackson

问题:
我正在尝试将请求作为POST参数发送:{id: 20, roleName: "ADMIN"}并收到此错误(415 不受支持的媒体类型)。

框架:
Spring 4.1.1

在我@Controller的服务器端,我有以下内容:

@RequestMapping("/role/add.action")
    @ResponseBody
    public Map<String,Object> addrole(@RequestBody Role role, 
            HttpServletRequest request,
            Authentication authentication,
            HttpServletResponse response) {
    //Code goes here..
}
Run Code Online (Sandbox Code Playgroud)

这 -->@RequestBody Role role适用于任何其他类型的对象,但是,因为Role我遇到了这个问题。

我的Role班级是:

@Entity
public class Role implements Serializable{


    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    @Id
    private int id;

    @Column
    private String roleName;

    @Fetch(FetchMode.SELECT)
    @OneToMany(mappedBy = "role", targetEntity = Users.class, fetch = FetchType.EAGER)
    @JsonManagedReference(value="role")
    private List<Users> users = new LinkedList<Users>();

    @Fetch(FetchMode.SELECT)
    @ManyToMany(fetch=FetchType.EAGER)
    @JoinTable(name="role_features",
            joinColumns=@JoinColumn(name="roleId"),
            inverseJoinColumns=@JoinColumn(name="featureId"))
    @OrderBy(clause="featureId")
    private Set<SystemFeature> features = new HashSet<SystemFeature>();

    @Fetch(FetchMode.SELECT)
    @ManyToMany(fetch=FetchType.EAGER)
    @JoinTable(name="role_menu",
            joinColumns=@JoinColumn(name="roleId"),
            inverseJoinColumns=@JoinColumn(name="menuId"))
    @OrderBy(clause="menuId")
    private Set<Menu> menus = new HashSet<Menu>();

    @Fetch(FetchMode.SELECT)
    @ManyToMany(fetch=FetchType.EAGER)
    @JoinTable(name="role_services_stations",
            joinColumns=@JoinColumn(name="roleId"),
            inverseJoinColumns=@JoinColumn(name="stationId"))
    @OrderBy(clause="stationId")
    private Set<ServiceStation> stations = new HashSet<ServiceStation>();

    //Constructors, getters and setters...

}
Run Code Online (Sandbox Code Playgroud)

这个类有java.util.Set属性,我认为这可能会导致问题。

我只发送两个属性:id 和 roleName。演员阵容应该有效,对吧?

PS:我已经设置了 Jackson message-converterbean,但是没有用。

    <mvc:annotation-driven>
        <mvc:message-converters register-defaults="true">
            <bean
                class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
                <property name="objectMapper">
                    <bean class="com.fasterxml.jackson.databind.ObjectMapper">
                        <property name="serializationInclusion">
                            <value type="com.fasterxml.jackson.annotation.JsonInclude.Include">NON_NULL</value>
                        </property>
                    </bean>
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>
Run Code Online (Sandbox Code Playgroud)

有人可以帮助我吗?xD

Joa*_*ena 6

我的问题基本上是在@JsonManagedReference 注释上。

我做了什么:

1)我将有效载荷更改为Map

public Map<String,Object> addRole(@RequestBody Map payload, 
            HttpServletRequest request,
            Authentication authentication,
            HttpServletResponse response) {
...
}
Run Code Online (Sandbox Code Playgroud)

2) 然后我尝试用 Jackson 的 ObjectMapper ( com.fasterxml.jackson.databind.ObjectMapper)来投射它:

ObjectMapper mapper = new ObjectMapper();

Role role = mapper.convertValue(payload, Role.class);
Run Code Online (Sandbox Code Playgroud)

然后调试器抛出了一个异常:

java.lang.IllegalArgumentException: Can not handle managed/back reference 'parent': no back reference property found from type [collection type; class java.util.Set, contains [simple type, class br.com.ttrans.samapp.model.Menu]]
Run Code Online (Sandbox Code Playgroud)

此异常有助于找到问题,即(在我的情况下)是 annotation @JsonManagedReference。从文档

用于指示被注释的属性是字段之间双向链接的一部分的注释;并且它的作用是“父”(或“转发”)链接。属性的值类型(类)必须有一个用 JsonBackReference 注释的兼容属性。链接的处理使得用这个注解注解的属性得到正常处理(正常序列化,反序列化没有特殊处理);它是需要特殊处理的匹配反向引用

这用于双向链接,我的有效载荷是单向的。所以..

3) ...我删除了@JsonManagedReference的注释,只保留@JsonBackReference在所有嵌套类中;

然后调试器又给我抛出了另一个异常,但这一次是: java.lang.IllegalArgumentException: Unrecognized field ...所以把@JsonIgnoreProperties(ignoreUnknown = true)所有的类都放在上面解决了我的问题。

所以毕竟我可以收到已经解析为的有效载荷Role

@RequestMapping("/role/add.action")
@ResponseBody
public Map<String,Object> addRole(@RequestBody Role role, 
            HttpServletRequest request,
            Authentication authentication,
            HttpServletResponse response) {

            ...
}
Run Code Online (Sandbox Code Playgroud)

希望能帮助到你!