10

Spring REST コントローラーが提供する JSON リソースに HATEOAS リンクを追加しようとしています。

https://github.com/spring-projects/spring-hateoasで説明されているように、リソース アセンブラーを使用する必要があるようです。

この例では、Person クラスと PersonResource クラスが表示されます。

PersonResource クラスが次のように定義されていることを理解しています。

public class PersonResource extends ResourceSupport {
}

Person クラスとは何ですか? それはデータドメインクラスですか?

私の場合、REST ドメイン クラスである Admin クラスを定義し、それをリソース サポートを持つものとして指定しました。

public class Admin extends ResourceSupport {

    private String firstname;
    private String lastname;
    private String email;
    private String login;
    private String password;
    private String passwordSalt;

    public Admin() {
    }

    public String getFirstname() {
        return this.firstname;
    }

    public void setFirstname(String firstname) {
        this.firstname = firstname;
    }

    public String getLastname() {
        return this.lastname;
    }

    public void setLastname(String lastname) {
        this.lastname = lastname;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getLogin() {
        return this.login;
    }

    public void setLogin(String login) {
        this.login = login;
    }

    public String getPassword() {
        return this.password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getPasswordSalt() {
        return passwordSalt;
    }

    public void setPasswordSalt(String passwordSalt) {
        this.passwordSalt = passwordSalt;
    }

    public EventAdmin toEventAdmin() {
        EventAdmin eventAdmin = new EventAdmin();

        BeanUtils.copyProperties(this, eventAdmin);

        return eventAdmin;
    }

    public static Admin fromEventAdmin(EventAdmin eventAdmin) {
        Admin admin = new Admin();

        BeanUtils.copyProperties(eventAdmin, admin);

        return admin;
    }

}

私の REST コントローラーは、REST ドメイン クラスであるため、この Admin クラスのみを認識します。データドメインクラスを認識していませんし、認識すべきではありません。

そこで、ここでリソース アセンブラ サポートをどのように使用するのだろうか。

ここに追加のデータ ドメイン管理者クラスが必要な理由がわかりません。

敬具、

ここでマイクの答えに従うと、私のコントローラーは次のようになります。

@RequestMapping(method = RequestMethod.POST, produces = "application/json; charset=utf-8")
@ResponseBody
public ResponseEntity<Admin> add(@RequestBody Admin admin, UriComponentsBuilder builder) {
    AdminCreatedEvent adminCreatedEvent = adminService.add(new CreateAdminEvent(admin.toEventAdmin()));
    HttpHeaders responseHeaders = new HttpHeaders();
    responseHeaders.add("Content-Type", "application/json; charset=utf-8");
    responseHeaders.setLocation(builder.path("/admin/{id}").buildAndExpand(adminCreatedEvent.getAdminId()).toUri());
    Admin createdAdmin = adminResourceAssembler.toResource(adminCreatedEvent.getEventAdmin());
    ResponseEntity<Admin> responseEntity = new ResponseEntity<Admin>(createdAdmin, responseHeaders, HttpStatus.CREATED);
    return responseEntity;
}

以前は、リソース アセンブラを使用する代わりに、次のことを行っていました。

Admin createdAdmin = Admin.fromEventAdmin(adminCreatedEvent.getEventAdmin());
createdAdmin.add(linkTo(methodOn(AdminController.class).add(createdAdmin, builder)).withSelfRel());

しかし、URL にリソース ID が表示されませんでした。

4

1 に答える 1

9

実装ResourceAssemblerでは、データ ドメイン クラスと REST ドメイン クラスの両方を認識する必要があります。これは、前者を後者に変換することがその役割であるためです。

データクラスの知識をコントローラーから外したい場合は、リポジトリからデータを取得し、を使用しResourceAssemblerてコントローラーが認識できるリソースに変換するリソース変換サービスを作成できます。

@Component
public class AdminResourceAssembler extends ResourceAssemblerSupport<Admin, AdminResource> {
    public AdminResourceAssembler() {
        super(AdminController.class, AdminResource.class);
    }

    public AdminResource toResource(Admin admin) {
        AdminResource adminResource = createResourceWithId(admin.getId(), admin); // adds a "self" link
        // TODO: copy properties from admin to adminResource
        return adminResource;
    }
}

@Service
public class AdminResourceService {
    @Inject private AdminRepository adminRepository;
    @Inject private AdminResourceAssembler adminResourceAssembler;

    @Transactional
    public AdminResource findOne(Long adminId) {
        Admin admin = adminRepository.findOne(adminId);
        AdminResource adminResource = adminResourceAssembler.toResource(admin);
        return adminResource;
    }
}

@Controller
@RequestMapping("/admins")
public class AdminController {
    @Inject private AdminResourceService adminResourceService;

    @RequestMapping(value="/{adminId}", method=RequestMethod.GET)
    public HttpEntity<AdminResource> findOne(@PathVariable("adminId") Long adminId) {
        AdminResource adminResource = adminResourceService.findOne(adminId);
        return new ReponseEntity<>(adminResource, HttpStatus.OK);
    }
}
于 2013-11-18T19:28:27.653 に答える