Подресурсы в spring REST

Я пытаюсь создать приложение мессенджера.

Я должен вызвать CommentResource из MessageResource.

Я хочу отдельные MessageResources и CommentResources.

Я делаю что-то вроде этого:

MessageResource.java

@RestController
@RequestMapping("/messages")
public class MessageResource {

    MessageService messageService = new MessageService();

    @RequestMapping(value = "/{messageId}/comments")
    public CommentResource getCommentResource() {
        return new CommentResource();
    }
}

CommentResource.java

@RestController
@RequestMapping("/")
public class CommentResource {

    private CommentService commentService = new CommentService();

    @RequestMapping(method = RequestMethod.GET, value="/abc")
    public String test2() {
        return "this is test comment";
    }
}

я хочу

HTTP://локальный: 8080/сообщения /1/комментарии/а

вернуть "это тестовый комментарий".

Любая идея??

PS: одним словом, я хочу знать реализацию эквивалента JAX-RS sub-resource в spring-rest

Ответ 1

Ваш URL (http://localhost: 8080/messages/1/comments/abc) предполагает, что в сообщение вложены комментарии. Ваш контроллер должен выглядеть так:

@RestController
@RequestMapping("/messages")
public class MessageResource {

    @RequestMapping(value = "/{messageId}")
    public String getCommentResource(@PathVariable("messageId") String messageId) {
        //test
        return messageId;
    }

    @RequestMapping(value = "/{messageId}/comments/{commentsContent}")
    public String getCommentResource(
                      @PathVariable("messageId") String messageId, 
                      @PathVariable("commentsContent") String commentsContent) {
        //test
        return messageId + "/" + commentsContent;
    }
}

Я не совсем уверен, что вы хотите сделать в своем классе MessageResource, но идея есть.

Отдых - HTTP методы

На данный момент это использование запросов Get. Однако вы должны рассмотреть возможность использования соответствующего метода Http:

  • Получить: прочитать ресурс
  • Пост: создать ресурс
  • Поставить: обновить
  • Удалить: удалить :)

Взгляните на это: http://www.restapitutorial.com/lessons/httpmethods.html

Пример с сообщением:

@RequestMapping(method=RequestMethod.POST, value = "/{messageId}/comments/{commentsContent}")
    public ResponseEntity<String> getCommentResource(
                                  @PathVariable("messageId") String messageId, 
                                  @RequestBody Comment comment) {
        //fetch the message associated with messageId
        //add the comment to the message
        //return success
        return new ResponseEntity<String>(HttpStatus.OK);
 }

Имена классов

Кроме того, я бы лично переименовал эти классы в MessageController и CommentController.

Редактировать после комментариев - Сплит контроллеры

Вы можете буквально разделить контроллеры (ближе к тому, что у вас было):

@RestController
@RequestMapping("/messages")
public class MessageResource {

    @RequestMapping(value = "/{messageId}")
    public String getCommentResource(@PathVariable("messageId") String messageId) {
        //test
        return messageId;
    }
}

@RestController
@RequestMapping("/messages")
public class CommentResource {

    @RequestMapping(value = "/{messageId}/comments/{commentsContent}")
    public String getCommentResource(
                      @PathVariable("messageId") String messageId, 
                      @PathVariable("commentsContent") String commentsContent) {
        //test
        return messageId + "/" + commentsContent;
    }
}

Ответ 2

То, что вы ищете, поддерживается в реализациях JAX-RS, таких как Jersey и называется Sub-Resources. При создании больших API-интерфейсов, которые становятся вложенными в природу, вспомогательные ресурсы являются чрезвычайно полезной функцией.

Spring Реализация загрузки по умолчанию загрузки не является JAX-RS, но SpringMVC. Хотя можно использовать Джерси в Spring Boot, это немного связано с попыткой настроить его и, по-видимому, не используется и не используется в сообществе.

На боковой ноте DropWizard является удивительным!

Ответ 3

Я тоже принудительно перешел из JAX-RS в Spring -MVC.

Я все еще ищу элегантный способ сделать это так же, как и с JAX-RS.

Я делюсь тем, что я пробовал.

@RestController
@RequestMapping("parents")
public class ParentsController {

    @RequestMapping(method = RequestMethod.GET,
                    produces = {MediaType.APPLICATION_JSON_VALUE})
    public ResponseEntity<List<Parent>> read() {
    }

    @RequestMapping(method = RequestMethod.GET,
                    path = "/{id:\\d+}",
                    produces = {MediaType.APPLICATION_JSON_VALUE})
    public ResponseEntity<Parent> read(@PathVariable("id") final long id) {
    }
}

И ChildrenController.

@RestController
@RequestMapping("/parents/{parentId:\\d+}/children")
public class ChildrenController {

    @RequestMapping(method = RequestMethod.GET,
                    produces = {MediaType.APPLICATION_JSON_VALUE})
    @ResponseBody
    public List<Child> read(@PathVariable("parentId") final long parentId) {
    }

    @RequestMapping(method = RequestMethod.GET, path = "/{id:\\d+}",
                    produces = {MediaType.APPLICATION_JSON_VALUE})
    @ResponseBody
    public Child read(@PathVariable("parentId") final long parentId,
                     @PathVariable("id") final long id) {
    }
}

Две проблемы, которые я нашел,

@PathVariable не применим к полям.

Я просто не могу сделать @PathVariable("parentId") private long parentId;

Нет свободной воли для множественного отображения для ChildrenController

Красота JAX-RS заключается в том, что мы можем отображать ChildrenController для разных путей, например, даже ChildrenController имеет с ним класс @Path.

@Path("/children");
public class ChildrenResource {
}

@Path("/parents")
public class ParentsResource {

    @Path("/{id}/children")
    public ChildrenResource resourceChildren() {
    }
}


/children
/parents/{id}/children

Ответ 4

Просто создайте два класса и используйте константу для ссылки на дочерний ресурс с родительским ресурсом. Это помогает установить связь между двумя классами и заставить разработчика понять взаимосвязь между ними.

Так:

@RequestMapping(value= MessageController.URL)
public class MessageController {
    public static final String URL= "/messages";
}

А также:

@RequestMapping(value = MessageController.URL + "/{idMessage}/comments")
public class CommentController {

}

Вы также можете разделить контроллеры на разные пакеты, показывая эту иерархию и в вашей организации пакетов:

com.company.web.message.MessageController
com.company.web.message.comment.CommentController