Подресурсы в 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