英文:
@RequestMapping doesn't map correctly
问题
问题是当我在CommentController
类上方使用我的注释@RequestMapping("/adverts/{id}")
时,我可以通过两种方式访问该类,即:localhost:8080/adverts/1/comments
和localhost:8080/comments
。我如何禁止访问localhost:8080/comments
?谢谢。
英文:
My problem is that when I use my annotation @RequestMapping("/adverts/{id}")
above my CommentController class, I can reach this class using both (i.e): localhost:8080/adverts/1/comments
and localhost:8080/comments
. How I can disable reaching localhost:8080/comments
? Thank you.
@RestController
class CommentController {
private final CommentRepository commentRepository;
private final AdvertRepository advertRepository;
private final CommentModelAssembler assembler;
CommentController(CommentRepository commentRepository, AdvertRepository advertRepository, CommentModelAssembler assembler) {
this.commentRepository = commentRepository;
this.advertRepository = advertRepository;
this.assembler = assembler;
}
@GetMapping("/adverts/{advertId}/comments")
CollectionModel<EntityModel<Comment>> all() {
List<EntityModel<Comment>> comments =
commentRepository.findAll().stream()
.map(assembler::toModel)
.collect(Collectors.toList());
return CollectionModel.of(comments,
linkTo(methodOn(CommentController.class).all()).withSelfRel());
}
@PostMapping("/adverts/{advertId}/comments")
Comment newComment(@RequestBody Comment newComment) {
return commentRepository.save(newComment);
}
@GetMapping("/adverts/{advertId}/comments/{id}")
EntityModel<Comment> one(@PathVariable Long id) {
Comment comment = commentRepository.findById(id)
.orElseThrow(() -> new CommentNotFoundException(id));
return assembler.toModel(comment);
}
@PutMapping("/adverts/{advertId}//comments/{id}")
Comment replaceComment(@RequestBody Comment newComment,
@PathVariable Long id) {
return commentRepository.findById(id)
.map(comment -> {
comment.setAdvertId(newComment.getAdvertId());
comment.setComment(newComment.getComment());
return commentRepository.save(comment);
})
.orElseGet(() -> {
newComment.setId(id);
return commentRepository.save(newComment);
});
}
@DeleteMapping("/adverts/{advertId}/comments/{id}")
void deleteComment(@PathVariable Long id) {
commentRepository.deleteById(id);
}
}
@Component
public class CommentModelAssembler implements RepresentationModelAssembler<Comment, EntityModel<Comment>> {
@Override
public EntityModel<Comment> toModel(Comment comment) {
return EntityModel.of(comment,
linkTo(methodOn(CommentController.class).one(comment.getId())).withSelfRel(),
linkTo(methodOn(CommentController.class).all()).withRel("comments"));
}
}
@RestController
class UserController {
private final UserRepository repository;
private final UserModelAssembler assembler;
UserController(UserRepository repository, UserModelAssembler assembler) {
this.repository = repository;
this.assembler = assembler;
}
@GetMapping("/users")
CollectionModel<EntityModel<User>> all() {
List<EntityModel<User>> users =
repository.findAll().stream()
.map(assembler::toModel)
.collect(Collectors.toList());
return CollectionModel.of(users,
linkTo(methodOn(UserController.class).all()).withSelfRel());
}
@PostMapping("/users")
User newUser(@RequestBody User newUser) {
return repository.save(newUser);
}
@GetMapping("/users/{id}")
EntityModel<User> one(@PathVariable Long id) {
User user = repository.findById(id)
.orElseThrow(() -> new UserNotFoundException(id));
return assembler.toModel(user);
}
@PutMapping("/users/{id}")
User replaceUser(@RequestBody User newUser,
@PathVariable Long id) {
return repository.findById(id)
.map(user -> {
user.setName(newUser.getName());
user.setRole(newUser.getRole());
user.setBoughtVehicles(newUser.getBoughtVehicles());
user.setSoldVehicles(newUser.getSoldVehicles());
return repository.save(user);
})
.orElseGet(() -> {
newUser.setId(id);
return repository.save(newUser);
});
}
@DeleteMapping("/users/{id}")
void deleteUser(@PathVariable Long id) {
repository.deleteById(id);
}
}
@RestController
class AdvertController {
private final AdvertRepository repository;
private final AdvertsModelAssembler assembler;
AdvertController(AdvertRepository repository, AdvertsModelAssembler assembler) {
this.repository = repository;
this.assembler = assembler;
}
@GetMapping("/adverts")
CollectionModel<EntityModel<Advert>> all() {
List<EntityModel<Advert>> adverts =
repository.findAll().stream()
.map(assembler::toModel)
.collect(Collectors.toList());
return CollectionModel.of(adverts,
linkTo(methodOn(AdvertController.class).all()).withSelfRel());
}
@PostMapping("/adverts")
Advert newAdvert(@RequestBody Advert newAdvert) {
return repository.save(newAdvert);
}
@GetMapping("/adverts/{id}")
EntityModel<Advert> one(@PathVariable Long id) {
Advert advert = repository.findById(id)
.orElseThrow(() -> new AdvertNotFoundException(id));
return assembler.toModel(advert);
}
@PutMapping("/adverts/{id}")
Advert replaceAdvert(@RequestBody Advert newAdvert,
@PathVariable Long id) {
return repository.findById(id)
.map(advert -> {
advert.setAutoCategory(newAdvert.getAutoCategory());
advert.setAutoName(newAdvert.getAutoName());
advert.setAutoModel(newAdvert.getAutoModel());
advert.setComments(newAdvert.getComments());
return repository.save(advert);
})
.orElseGet(() -> {
newAdvert.setId(id);
return repository.save(newAdvert);
});
}
@DeleteMapping("/adverts/{id}")
void deleteAdvert(@PathVariable Long id) {
repository.deleteById(id);
}
}
localhost:8080/comments
result:
{
"_embedded" : {
"comments" : [ {
"advertId" : 1,
"comment" : "That's a nice car!",
"_links" : {
"self" : {
"href" : "http://localhost:8080/comments/3"
},
"comment" : {
"href" : "http://localhost:8080/comments/3"
}
}
}, {
"advertId" : 2,
"comment" : "What a nice color of the car!",
"_links" : {
"self" : {
"href" : "http://localhost:8080/comments/4"
},
"comment" : {
"href" : "http://localhost:8080/comments/4"
}
}
} ]
},
"_links" : {
"self" : {
"href" : "http://localhost:8080/comments"
},
"profile" : {
"href" : "http://localhost:8080/profile/comments"
}
},
"page" : {
"size" : 20,
"totalElements" : 2,
"totalPages" : 1,
"number" : 0
}
}
答案1
得分: 1
你的 localhost:8080/comments
API 似乎来自不同的控制器,而不是你所发布的控制器。
更新:
如果你只想看到每个用户的评论,你可以按照以下方式更改你的控制器定义,使其更通用和简单:
@RestController
@RequestMapping("/adverts")
class CommentController {
更新 2:
你需要更新你的控制器 URL 映射。通常,我们为特定的控制器/目的定义一个公共的 URL 名称。比如你的 CommonController
,你可以这样做:
@RestController
@RequestMapping("/common")
class CommentController {
注意这个名字 /common
。然后,在这个控制器下,你可以添加其他的 API,比如 /comments/all
、/comments/{id}
、/comments/others
。要访问这些控制器方法,你必须按照这个层次结构,比如:
/common/comments/all
或者 /common/comments/1
类似地,对于 AdvertController:
@RestController
@RequestMapping("/advert")
class AdvertController {
同样,检查一下常见的 URL 名称 /advert
。在这个控制器下的 API 将会有这样的命名:
/all
、/{id}
。要访问这个控制器方法,使用的 URL 形式如下:
/advert/all
、/advert/1
这应该能够清楚地解释你的问题。
需要注意的是,我在示例 URL 中排除了基本的 localhost:8080
部分,请记得添加上这部分。
希望这能够达到你的目的。
英文:
Your localhost:8080/comments
API seems to come from different controller, not from this one you have posted.
Update:
If you want to see only each user's comment, you can change your controller definition following way to make it more generic and simple:
@RestController
@RequestMapping("/adverts")
class CommentController {
Update 2:
You need to update your controller-url mapping. Generally, we define a common url-name for a specific controller/purpose. Like for your CommonController
you can do this:
@RestController
@RequestMapping("/common")
class CommentController {
See the name /commom
. Then, under this controller, you add other API like /comments/all
, /comments/{id}
, /comments/others
. To access these controller method, you must follow this hierarchy like:
/common/comments/all
or /common/comments/1
Similarly for AdvertController:
@RestController
@RequestMapping("/advert")
class AdvertController {
Again, check the common url-name /advert
. API under this controller will have naming like this:
/all
, '/{id}'. To access this controller method use URL this way:
/advert/all
, /advert/1
This should clear your idea.
One thing, I have excluded the base-url localhost:8080
part from the url-example I have shown, mind adding this.
Hope, this will server your purpose.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论