首页 文章

使用Spring Data REST公开枚举

提问于
浏览
1

我正在使用Spring Boot 1.5.3,Spring Data REST,HATEOAS . 我有一个简单的实体模型:

@Entity
public class User extends AbstractEntity implements UserDetails {
private static final long serialVersionUID = 5745401123028683585L;
public static final PasswordEncoder PASSWORD_ENCODER = new BCryptPasswordEncoder();
@NotNull(message = "The name of the user cannot be blank")
@Column(nullable = false)
private String name;

/** CONTACT INFORMATION **/
private String landlinePhone;

private String mobilePhone;

@NotNull(message = "The username cannot be blank")
@Column(nullable = false, unique = true)
private String username;

@Email(message = "The email address is not valid")
private String email;

@JsonIgnore
private String password;

@Column(nullable = false)
private String timeZone = "Europe/Rome";

@JsonIgnore
private LocalDateTime lastPasswordResetDate;

@Column(nullable = false, columnDefinition = "BOOLEAN default true")
private boolean enabled = true;

@Type(type = "json")
@Column(columnDefinition = "json")
private Roles[] roles = new Roles[] {};

而我的枚举角色是:

public enum Roles {
ROLE_ADMIN, ROLE_USER, ROLE_MANAGER, ROLE_TECH;

@JsonCreator
public static Roles create(String value) {
    if (value == null) {
        throw new IllegalArgumentException();
    }
    for (Roles v : values()) {
        if (value.equals(v.toString())) {
            return v;
        }
    }
    throw new IllegalArgumentException();
}
}

我正在Angular 4中创建一个客户端.Spring Data REST很棒,暴露存储库很容易返回我的模型HATEOAS兼容:

{
  "_embedded": {
    "users": [
      {
        "name": "Administrator",
        "username": "admin",
        "roles": [
          "Amministratore"
        ],
        "activeWorkSession": "",
        "_links": {
          "self": {
            "href": "http://localhost:8080/api/v1/users/1"
          },
          "user": {
            "href": "http://localhost:8080/api/v1/users/1{?projection}",
            "templated": true
          }
        }
      },

就像你可以看到我也通过rest-messages.properties翻译我的枚举值 . 大!我的Angular页面现在需要完整的角色列表(枚举) . 我有一些问题:

  • 了解服务器返回角色列表的更好方法

  • 如何返回此列表

我的第一个尝试是创建一个RepositoryRestController,以便利用Spring Data REST提供的功能 .

@RepositoryRestController
@RequestMapping(path = "/api/v1")

public class UserController {

@Autowired
private EntityLinks entityLinks;

@RequestMapping(method = RequestMethod.GET, path = "/users/roles", produces = "application/json")
public Resource<Roles> findRoles() {
    Resource<Roles> resource = new Resource<>(Roles.ROLE_ADMIN);
    return resource;
}

不幸的是,由于某种原因,对此方法的调用返回404错误 . 我调试了并且资源是正确创建的,所以我猜问题是在JSON转换中的某个地方 .

2 回答

  • 0

    如何返回此列表?

    @RepositoryRestController
    @RequestMapping("/roles")
    public class RoleController {
    
        @GetMapping
        public ResponseEntity<?> getAllRoles() {
            List<Resource<Roles>> content = new ArrayList<>();
            content.addAll(Arrays.asList(
                    new Resource<>(Roles.ROLE1 /*, Optional Links */),
                    new Resource<>(Roles.ROLE2 /*, Optional Links */)));
            return ResponseEntity.ok(new Resources<>(content /*, Optional Links */));
        }
    }
    
  • 1

    我正在玩这个,并找到了几种方法来做到这一点 .

    假设您有一个前端表单,希望显示一个包含单个Todo优先级的组合框,例如 High, Medium, Low . 表单需要知道 primary key or id ,这是此实例中的枚举值,值应该是组合框应显示的可读格式化值 .

    如果您希望仅在一个位置自定义json响应,例如单个 endpoints ,那么我发现这很有用 . 秘诀是使用值对象 PriorityValue 允许您通过 @Relation 重命名json字段 .

    public enum Priority {
        HIGH("High"),
        NORMAL("Normal"),
        LOW("Low");
    
        private final String description;
    
        Priority(String description) {
            this.description = description;
        }
    
        public String getDescription() {
            return description;
        }
    
        public static List<Priority> orderedValues = new ArrayList<>();
    
        static {
            orderedValues.addAll(Arrays.asList(Priority.values()));
        }
    }
    
    
    @RepositoryRestController
    @RequestMapping(value="/")
    public class PriorityController {
    
        @Relation(collectionRelation = "priorities")
        @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
        private class PriorityValue {
            private String id;
            private String value;
    
            public PriorityValue(String id,
                                 String value) {
                this.id = id;
                this.value = value;
            }
        }
    
        @GetMapping(value = "/api/priorities", produces = MediaTypes.HAL_JSON_VALUE)
        public ResponseEntity<Resources<PriorityValue>> getPriorities() {
            List<PriorityValue> priorities = Priority.orderedValues.stream()
                    .map(p -> new PriorityValue(p.name(), p.getDescription()))
                    .collect(Collectors.toList());
    
            Resources<PriorityValue> resources = new Resources<>(priorities);
      resources.add(linkTo(methodOn(PriorityController.class).getPriorities()).withSelfRel());    
            return ResponseEntity.ok(resources);
        }
    
    }
    

    另一种方法是使用自定义 JsonSerializer . 使用此问题的唯一问题是在序列化优先级枚举的任何地方,您最终将使用此格式,这可能不是您想要的 .

    @JsonSerialize(using = PrioritySerializer.class)
    @Relation(collectionRelation = "priorities")
    public enum Priority {
        HIGH("High"),
        NORMAL("Normal"),
        LOW("Low");
    
        private final String description;
    
        Priority(String description) {
            this.description = description;
        }
    
        public String getDescription() {
            return description;
        }
    
        public static List<Priority> orderedValues = new ArrayList<>();
    
        static {
            orderedValues.addAll(Arrays.asList(Priority.values()));
        }
    }
    
    
    @RepositoryRestController
    @RequestMapping(value="/api")
    public class PriorityController {
    
        @GetMapping(value = "/priorities", produces = MediaTypes.HAL_JSON_VALUE)
        public ResponseEntity<Resources<Priority>> getPriorities() {
            Resources<Priority> resources = new Resources<>(Priority.orderedValues);
    
            resources.add(linkTo(methodOn(PriorityController.class).getPriorities()).withSelfRel());
    
            return ResponseEntity.ok(resources);
        }
    }
    
    
    public class PrioritySerializer extends JsonSerializer<Priority> {
        @Override
        public void serialize(Priority priority,
                              JsonGenerator generator,
                              SerializerProvider serializerProvider)
                throws IOException, JsonProcessingException {
            generator.writeStartObject();
    
            generator.writeFieldName("id");
            generator.writeString(priority.name());
    
            generator.writeFieldName("value");
            generator.writeString(priority.getDescription());
    
            generator.writeEndObject();
        }
    }
    

    http://localhost:8080/api/priorities 的最终json回复

    {
        "_embedded": {
            "priorities": [
                {
                    "id": "HIGH",
                    "value": "High"
                },
                {
                    "id": "NORMAL",
                    "value": "Normal"
                },
                {
                    "id": "LOW",
                    "value": "Low"
                }
            ]
        },
        "_links": {
            "self": {
                "href": "http://localhost:8080/api/priorities"
            }
        }
    }
    

相关问题