相关文章推荐
心软的芒果  ·  mysql索引 大数据表 ...·  1 年前    · 
傻傻的吐司  ·  library ...·  1 年前    · 
本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《 阿里云开发者社区用户服务协议 》和 《 阿里云开发者社区知识产权保护指引 》。如果您发现本社区中有涉嫌抄袭的内容,填写 侵权投诉表单 进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

项目场景:


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

问题描述


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

Swagger调试的内容如下:

image.png

image.png

从控制台的截图可以看到数据库中的数据正常返回以及前端传递的参数正常接收

控制台报错如下:

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 Security UserDetails 的接口字段有一些是不需要返回给前端的

对应的 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;
 * @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 方法返回的内容不出现在返回结果中

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

image.png

总结:


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

  1. 作用:在 JSON 序列化时将 Java Bean 中的⼀些属性忽略掉,序列化和反序列化都受影响
  2. 使⽤场景: ⼀般标记在属性或者⽅法上 ,返回的 Json 数据即不包含该属性
No qualifying bean of type ‘org.springframework.boot.autoconfigure.http.HttpMessageConverters‘ avail
No qualifying bean of type ‘org.springframework.boot.autoconfigure.http.HttpMessageConverters‘ avail
kkoneone11 Failed to meta-introspect annotation interface org.springframework.web.bind.annotation.RequestBody:
Failed to meta-introspect annotation interface org.springframework.web.bind.annotation.RequestBody:
Moresweet猫甜 The superclass "javax.servlet.http.HttpServlet" was not found on the Java Build Path类似问题简单解决方案
The superclass "javax.servlet.http.HttpServlet" was not found on the Java Build Path类似问题简单解决方案
rothschild666 required a bean of type ‘org.springframework.web.client.RestTemplate‘ that could not be found.
required a bean of type ‘org.springframework.web.client.RestTemplate‘ that could not be found.
牛哄哄的柯南8151 The superclass “javax.servlet.http.HttpServlet“ was not found on the Java Build Path的解决方案
The superclass “javax.servlet.http.HttpServlet“ was not found on the Java Build Path的解决方案
java.lang.IllegalStateException: Cannot load configuration class: org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration
java.lang.IllegalStateException: Cannot load configuration class: org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration报错问题处理
六月的雨在钉钉