Spring MVC + Spring Data Rest를 혼합하면 홀수 MVC 응답이 발생합니다.
두 개의 JPA 엔티티가 있습니다. 하나는 SDR 내보낸 저장소, 다른 하나는 Spring MVC 컨트롤러 및 내보내지 않은 저장소입니다.
MVC 노출 엔티티는 SDR 관리 엔티티에 대한 참조를 가지고 있습니다.코드 참조는 아래를 참조하십시오.
이 문제는 검색할 때 발생합니다.UserUserControllerSDR 관리 엔티티가 직렬화되지 않고 Spring이 응답에 HATOAS 참조를 사용하려고 하는 것 같습니다.
이것이 무엇입니까?GET.User다음과 같은 모양:
{
"username": "foo@gmail.com",
"enabled": true,
"roles": [
{
"role": "ROLE_USER",
"content": [],
"links": [] // why the content and links?
}
// no places?
]
}
어떻게 하면 쉽게 반품할 수 있습니까?UserSDR 관리 엔티티가 내장된 컨트롤러의 엔티티?
Spring MVC 관리
독립체
@Entity
@Table(name = "users")
public class User implements Serializable {
// UID
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@JsonIgnore
private Long id;
@Column(unique = true)
@NotNull
private String username;
@Column(name = "password_hash")
@JsonIgnore
@NotNull
private String passwordHash;
@NotNull
private Boolean enabled;
// No Repository
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER)
@NotEmpty
private Set<UserRole> roles = new HashSet<>();
// The SDR Managed Entity
@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinTable(name = "user_place",
joinColumns = { @JoinColumn(name = "users_id") },
inverseJoinColumns = { @JoinColumn(name = "place_id")})
private Set<Place> places = new HashSet<>();
// getters and setters
}
레포
@RepositoryRestResource(exported = false)
public interface UserRepository extends PagingAndSortingRepository<User, Long> {
// Query Methods
}
컨트롤러
@RestController
public class UserController {
// backed by UserRepository
private final UserService userService;
@Autowired
public UserController(UserService userService) {
this.userService = userService;
}
@RequestMapping(path = "/users/{username}", method = RequestMethod.GET)
public User getUser(@PathVariable String username) {
return userService.getByUsername(username);
}
@RequestMapping(path = "/users", method = RequestMethod.POST)
public User createUser(@Valid @RequestBody UserCreateView user) {
return userService.create(user);
}
// Other MVC Methods
}
SDR 관리
독립체
@Entity
public class Place implements Serializable {
// UID
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@NotBlank
private String name;
@Column(unique = true)
private String handle;
@OneToOne(cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "address_id")
private Address address;
@OneToOne(cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "contact_info_id")
private ContactInfo contactInfo;
// getters and setters
}
레포
public interface PlaceRepository extends PagingAndSortingRepository<Place, Long> {
// Query Methods
}
요약하자면, Spring Data REST 및 Spring HATEOAS는 ObjectMapper를 하이잭킹하고 리소스 간의 관계를 리소스를 포함하지 않고 링크로 표현하고자 합니다.
일대일 관계를 가진 엔티티를 다른 엔티티와 함께 사용합니다.
@Entity
public class Person {
private String firstName;
private String lastName;
@OneToOne private Address address;
}
SDR/HATEOAS에서 주소를 링크로 반환합니다.
{
"firstName": "Joe",
"lastName": "Smith",
"_links": {
"self": { "href": "http://localhost:8080/persons/123123123" },
"address": { "href": "http://localhost:8080/addresses/9127391273" }
}
}
기본 형식은 클래스 경로에 있는 내용에 따라 변경될 수 있습니다.SDR과 HATEOAS를 포함할 때 기본값인 HAL이 이 예를 들어 HAL이라고 생각합니다.해당 구성에 따라 다르지만 유사할 수 있습니다.
은 봄은이할것다입니을것▁when다▁will▁do 때 이것을 할 것입니다.AddressSDR에서 관리합니다. SDR에서 관리하지 않으면 전체 주소 개체가 응답에 포함됩니다.당신이 보고 있는 행동은 그것만으로도 설명이 될 것 같습니다.
역할
에 대한 정보를 UserRole하지만 당신의 코드에 따르면 외부에서 관리되지 않는 것으로 보입니다.User등록된 Spring Data 저장소가 없습니다.만약 이것이 그것이 내장된 이유라면, '연결'할 다른 저장소가 없습니다.
그content그리고.links언더롤은 스프링이 그것을 시리즈화하려고 노력하는 것처럼 보입니다.Page으로.일반적으로.content 및 "는 다음과 같이 표시됩니다.links 리소스에 자체' 또는 다른 리소스에 대한 링크가 있습니다.저는 무엇이 그것을 유발하는지 확신할 수 없습니다.
장소
Place는 자체적인 Spring Data 저장소를 보유하고 있으므로 관리 엔티티로 취급되며 내장된 것이 아니라 에 연결됩니다.저는 당신이 찾고 있는 것이 투영이라고 의심합니다.투영에 대한 Spring 문서를 확인하십시오.다음과 같이 표시됩니다.
@Projection(name = "embedPlaces", types = { User.class })
interface EmbedPlaces {
String getUsername();
boolean isEnabled();
Set<Place> getPlaces();
}
그러면 사용자 이름, 활성화된 역할 및 역할이 직렬화되고 다른 모든 항목이 생략됩니다.저는 아직 개인적으로 프로젝션을 사용한 적이 없기 때문에 얼마나 잘 작동하는지 장담할 수 없지만 설명서에는 이것이 해결책입니다.
편집: 이 작업은 리소스를 만들거나 업데이트하는 경우에도 적용됩니다.Spring은 리소스를 URL로 예상합니다. 따라서 사용자/주소 예를 들어, 내가 새로운 사용자를 생성할 때 내 몸은 다음과 같이 보일 수 있습니다.
{
"firstName": "New",
"lastName": "Person",
"address": "http://localhost:8080/addresses/1290312039123"
}
방대한, 방대한, 방대한, 방대한, 방대한 대부분의 "REST" API는 REST가 아니며 SDR/HATEOAS는 REST에 대해 확고한 견해를 가지고 있기 때문에 이러한 사실을 잊기 쉽습니다(예: REST여야 합니다).
컨트롤러에서 @ResponseEntity를 잘 사용한 다음 ResponseEntity에서 사용자 개체를 설정할 수 있습니다.
아래의 예를 참조하십시오.
ResponseEntity<User> respEntity = new ResponseEntity<User>(user, HttpStatus.OK);
그럼 고객 쪽에서 전화해 보세요restTemplate.getForEntity
아래의 restTemplate 설명서를 참조하십시오.
언급URL : https://stackoverflow.com/questions/37232377/mixing-spring-mvc-spring-data-rest-results-in-odd-mvc-responses
'programing' 카테고리의 다른 글
| 파이썬의 파이프 문자 (0) | 2023.09.10 |
|---|---|
| Swift에서 파일/URL을 한 줄씩 읽기 (0) | 2023.09.10 |
| MariaDB 10.0, innodb: 조건부 고유 제약 조건? (0) | 2023.09.05 |
| 자바스크립트를 위한 단순(비보안) 해시 함수? (0) | 2023.09.05 |
| 도커 호스트 OS와 컨테이너 기본 이미지 OS 간의 관계는 무엇입니까? (0) | 2023.09.05 |