/companyId/userId/ticket
我们提供包含assigneeId
的票证正文:
{ " assigneeId":10 }
我们需要验证assigneeId
属于公司网址 - companyId
路径变量
@RequestMapping(value="/{companyId}/{userId}/ticket", method=POST)
public void createTicket(@Valid @RequestBody Ticket newTicket, @PathVariable Long companyId, @PathVariable Long userId) {
...
}
TicketValidator
)(即使是依赖项)并验证Ticket
实例companyId
传递给此验证器!我们需要验证ticket.assigneeId
属于公司companyId
。任何想法如何在这里实现所需的输出?
答案 0 :(得分:2)
如果我们假设我们的自定义验证器知道所需的属性名称,那么我们可以这样做:
接近一个方法:
1)我们可以将这个获取路径变量逻辑移动到某种基本验证器:
public abstract class BaseValidator implements Validator {
@Override
public boolean supports(Class<?> clazz)
{
// supports logic
}
@Override
public void validate(Object target, Errors errors)
{
// some base validation logic or empty if there isn't any
}
protected String getPathVariable(String name) {
// Getting current request (Can be autowired - depends on your implementation)
HttpServletRequest req = HttpServletRequest((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
if (req != null) {
// getting variables map from current request
Map<String, String> variables = req.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
return variables.get(name);
}
return null;
}
}
2)使用TicketValidator
实施进行扩展:
public class TicketValidator extends BaseValidator {
@Override
public void validate(Object target, Errors errors)
{
// Getting our companyId var
String companyId = getPathVariable("companyId");
...
// proceed with your validation logic. Note, that all path variables
// is `String`, so you're going to have to cast them (you can do
// this in `BaseValidator` though, by passing `Class` to which you
// want to cast it as a method param). You can also get `null` from
// `getPathVariable` method - you might want to handle it too somehow
}
}
方法二:
我认为值得一提的是,您可以使用@PreAuthorize
注释与SpEL进行此类验证(您可以传递路径变量并向其请求正文)。如果验证通过,您将获得HTTP 403
代码,因此我认为它并不是您想要的。
答案 1 :(得分:1)
您可以随时执行此操作:
@Controller
public class MyController {
@Autowired
private TicketValidator ticketValidator;
@RequestMapping(value="/{companyId}/{userId}/ticket", method=POST)
public void createTicket(@RequestBody Ticket newTicket,
@PathVariable Long companyId, @PathVariable Long userId) {
ticketValidator.validate(newTicket, companyId, userId);
// do whatever
}
}
修改以回应评论:
当Ticket
的有效性取决于companyId
时,独立于Ticket
验证companyId
是没有意义的。
如果您无法使用上述解决方案,请考虑在DTO中将Ticket
与companyId
分组,并更改映射,如下所示:
@Controller
public class MyController {
@RequestMapping(value="/{userId}/ticket", method=POST)
public void createTicket(@Valid @RequestBody TicketDTO ticketDto,
@PathVariable Long userId) {
// do whatever
}
}
public class TicketDTO {
private Ticket ticket;
private Long companyId;
// setters & getters
}