org.springframework.http.converter.HttpMessageNotWritableException...解决方法

2年前 (2022) 程序员胖胖胖虎阿
194 0 0

项目场景:

在进行在线使用Spring Security做为权限框架的办公系统的个人项目开发中,控制台输出的错误信息为无法写入JSON的错误,遇到了这个比较让人摸不着头脑的问题,我想应该不局限于当前项目场景,将目前遇到这种错误的解决方法进行记录,如果以后再遇到相同的错误,有不同解决方法时再回来记录。


问题描述

要实现的功能是获取管理员列表,向后端传递的参数和数据库中想要查询的内容也可以正常的获取到,但是在将查询到的数据返回到前端时就出现了报错

Swagger调试的内容如下:
org.springframework.http.converter.HttpMessageNotWritableException...解决方法
org.springframework.http.converter.HttpMessageNotWritableException...解决方法
从控制台的截图可以看到数据库中的数据正常返回以及前端传递的参数正常接收

控制台报错如下:

Resolved [org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: A granted authority textual representation is required; nested exception is com.fasterxml.jackson.databind.JsonMappingException: A granted authority textual representation is required (through reference chain: java.util.ArrayList[0]->net.csdn.server.pojo.Admin["authorities"])]

将问题进行翻译后可以知道内容为:

[org.springframework.http.converter.HttpMessageNotWritableException:无法写入 JSON:需要授予权限的文本表示; 嵌套异常是 com.fasterxml.jackson.databind.JsonMappingException:需要授予权限的文本表示(通过引用链:java.util.ArrayList[0]->net.csdn.server.pojo.Admin[“authorities”]) ]


原因分析:

出现了这种问题,首先可以在控制台中看到是Admin类中的某个字段需要授予权限,因此问题就在于Admin类中的字段上,首先能够想到考虑以下几点( 项目中引入了lombok, 同时Admin类实现了UserDetails接口

  1. lombok@Data注解没有加上,导致某些字段没有getter以及setter方法
  2. 对于Spring SecurityUserDetails的接口字段有一些是不需要返回给前端的

对应的Admin类代码如下:

package net.csdn.server.pojo;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 
 * </p>
 *
 * @author zhangrongkang
 * @since 2022-01-23
 */

@Data
@EqualsAndHashCode(callSuper = false)
@TableName("t_admin")
@ApiModel(value="Admin对象", description="")
public class Admin implements Serializable, UserDetails {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "id")
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;

    @ApiModelProperty(value = "姓名")
    private String name;

    @ApiModelProperty(value = "手机号码")
    private String phone;

    @ApiModelProperty(value = "住宅电话")
    private String telephone;

    @ApiModelProperty(value = "联系地址")
    private String address;

    @ApiModelProperty(value = "是否启用")
    private Boolean enabled;

    @ApiModelProperty(value = "用户名")
    private String username;

    @ApiModelProperty(value = "密码")
    private String password;

    @ApiModelProperty(value = "用户头像")
    private String userFace;

    @ApiModelProperty(value = "备注")
    private String remark;

    @ApiModelProperty(value = "角色")
    @TableField(exist = false)
    private List<Role> roles;

    /**
     * 通过角色名获取到对应的权限
     *
     * @return 与角色名对应的权限集合
     */
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        List<SimpleGrantedAuthority> authorities = roles
                .stream()
                .map(role -> new SimpleGrantedAuthority(role.getName()))
                .collect(Collectors.toList());
        return authorities;
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return enabled;
    }
}

可以看到在Admin类中是有@Data注解的,因此排除第一种可能的情况。对于第二种情况来说,发现重写的getAuthorities方法中返回的authorities与控制台中的报错字段一致,因此可以将问题缩小至前端不需要将authorities进行返回


解决方案:

在当前Admin类中的getAuthorities方法上添加@JsonIgnore注解,将getAuthorities方法返回的内容不出现在返回结果中

在添加该注解后,代码正常运行

org.springframework.http.converter.HttpMessageNotWritableException...解决方法

总结:

无法将JSON返回到前端有很多原因,这里的解决方法是对UserDetails的实现类中的方法添加注解,表示其返回到内容不需要返回到前端。对@JsonIgnore注解的使用进行一个小的总结

  1. 作用:在JSON序列化时将Java Bean中的⼀些属性忽略掉,序列化和反序列化都受影响
  2. 使⽤场景:⼀般标记在属性或者⽅法上,返回的Json数据即不包含该属性

相关文章

暂无评论

暂无评论...