我目前正在使用Jackson(2.4.0-rc3)和spring mvc(4.0.3)编写REST api,我正在尝试使其安全.
通过这种方式,我尝试使用JsonView来选择可以序列化的对象部分.
我找到了解决方案(不适合我)用我想要的视图注释我的Controller方法.但我想动态选择控制器内部的视图.
是否可以扩展ResponseEntity类以指定我想要的JsonView?
一小段代码:
这是帐户类
public class Account {
@JsonProperty(value = "account_id")
private Long accountId;
@JsonProperty(value = "mail_address")
private String mailAddress;
@JsonProperty(value = "password")
private String password;
@JsonProperty(value = "insert_event")
private Date insertEvent;
@JsonProperty(value = "update_event")
private Date updateEvent;
@JsonProperty(value = "delete_event")
private Date deleteEvent;
@JsonView(value = PublicView.class)
public Long getAccountId() {
return accountId;
}
@JsonView(value = PublicView.class)
public void setAccountId(Long accountId) {
this.accountId = accountId;
}
@JsonView(value = OwnerView.class)
public String getMailAddress() {
return mailAddress;
}
@JsonView(value = OwnerView.class)
public void setMailAddress(String mailAddress) {
this.mailAddress = mailAddress;
}
@JsonIgnore
public String getPassword() {
return password;
}
@JsonView(value = OwnerView.class)
public void setPassword(String password) {
this.password = password;
}
@JsonView(value = AdminView.class)
public Date getInsertEvent() {
return insertEvent;
}
@JsonView(value = AdminView.class)
public void setInsertEvent(Date insertEvent) {
this.insertEvent = insertEvent;
}
@JsonView(value = AdminView.class)
public Date getUpdateEvent() {
return updateEvent;
}
@JsonView(value = AdminView.class)
public void setUpdateEvent(Date updateEvent) {
this.updateEvent = updateEvent;
}
@JsonView(value = AdminView.class)
public Date getDeleteEvent() {
return deleteEvent;
}
@JsonView(value = OwnerView.class)
public void setDeleteEvent(Date deleteEvent) {
this.deleteEvent = deleteEvent;
}
@JsonProperty(value = "name")
public abstract String getName();
}
这是帐户控制器
@RestController
@RequestMapping("/account")
public class AccountCtrlImpl implements AccountCtrl {
@Autowired
private AccountSrv accountSrv;
public AccountSrv getAccountSrv() {
return accountSrv;
}
public void setAccountSrv(AccountSrv accountSrv) {
this.accountSrv = accountSrv;
}
@Override
@RequestMapping(value = "/get_by_id/{accountId}", method = RequestMethod.GET, headers = "Accept=application/json")
public ResponseEntity getById(@PathVariable(value = "accountId") Long accountId) {
try {
return new ResponseEntity(this.getAccountSrv().getById(accountId), HttpStatus.OK);
} catch (ServiceException e) {
return new ResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
@Override
@RequestMapping(value = "/get_by_mail_address/{mail_address}", method = RequestMethod.GET, headers = "Accept=application/json")
public ResponseEntity getByMailAddress(@PathVariable(value = "mail_address") String mailAddress) {
try {
return new ResponseEntity(this.getAccountSrv().getByMailAddress(mailAddress), HttpStatus.OK);
} catch (ServiceException e) {
return new ResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
@Override
@RequestMapping(value = "/authenticate/{mail_address}/{password}", method = RequestMethod.GET, headers = "Accept=application/json")
public ResponseEntity authenticate(@PathVariable(value = "mail_address") String mailAddress, @PathVariable(value = "password") String password) {
return new ResponseEntity(HttpStatus.NOT_IMPLEMENTED);
}
}
解决方法:
我已经解决了扩展ResponseEntity的问题,如下所示:
public class ResponseViewEntity extends ResponseEntity> {
private Class extends BaseView> view;
public ResponseViewEntity(HttpStatus statusCode) {
super(statusCode);
}
public ResponseViewEntity(T body, HttpStatus statusCode) {
super(new ContainerViewEntity(body, BaseView.class), statusCode);
}
public ResponseViewEntity(T body, Class extends BaseView> view, HttpStatus statusCode) {
super(new ContainerViewEntity(body, view), statusCode);
}
}
和ContainerViewEntity封装对象和选定的视图
public class ContainerViewEntity {
private final T object;
private final Class extends BaseView> view;
public ContainerViewEntity(T object, Class extends BaseView> view) {
this.object = object;
this.view = view;
}
public T getObject() {
return object;
}
public Class extends BaseView> getView() {
return view;
}
public boolean hasView() {
return this.getView() != null;
}
}
之后,我们只转换具有良好视图的对象.
public class JsonViewMessageConverter extends MappingJackson2HttpMessageConverter {
@Override
protected void writeInternal(Object object, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException {
if (object instanceof ContainerViewEntity && ((ContainerViewEntity) object).hasView()) {
writeView((ContainerViewEntity) object, outputMessage);
} else {
super.writeInternal(object, outputMessage);
}
}
protected void writeView(ContainerViewEntity view, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException {
JsonEncoding encoding = this.getJsonEncoding(outputMessage.getHeaders().getContentType());
ObjectWriter writer = this.getWriterForView(view.getView());
JsonGenerator jsonGenerator = writer.getFactory().createGenerator(outputMessage.getBody(), encoding);
try {
writer.writeValue(jsonGenerator, view.getObject());
} catch (IOException ex) {
throw new HttpMessageNotWritableException("Could not write JSON: " + ex.getMessage(), ex);
}
}
private ObjectWriter getWriterForView(Class> view) {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, false);
return mapper.writer().withView(view);
}
}
为了完成,我启用了转换器
就是这样,我可以在控制器中选择View
@Override
@RequestMapping(value = "/get_by_id/{accountId}", method = RequestMethod.GET, headers = "Accept=application/json")
public ResponseViewEntity getById(@PathVariable(value = "accountId") Long accountId) throws ServiceException {
return new ResponseViewEntity(this.getAccountSrv().getById(accountId), PublicView.class, HttpStatus.OK);
}
标签:java,spring-mvc,spring,jackson
来源: https://codeday.me/bug/20190713/1449688.html