我正在使用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转换中的某个地方。
答案 0 :(得分:2)
如何返回此列表?
@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 :(得分:0)
我正在玩这个并找到了几种方法。
假设您有一个前端表单,希望显示一个包含单个Todo优先级的组合框,例如High, Medium, Low
。表单需要知道primary key or id
这个实例中的枚举值,值应该是组合框应该显示的可读格式化值。
如果您希望仅在一个位置自定义json响应,例如单个端点,那么我发现这很有用。秘诀就是使用值对象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
{
"_embedded": {
"priorities": [
{
"id": "HIGH",
"value": "High"
},
{
"id": "NORMAL",
"value": "Normal"
},
{
"id": "LOW",
"value": "Low"
}
]
},
"_links": {
"self": {
"href": "http://localhost:8080/api/priorities"
}
}
}