在Spring MVC Controller中选择JsonView [英] Select JsonView in the Spring MVC Controller

查看:111
本文介绍了在Spring MVC Controller中选择JsonView的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在使用Jackson(2.4.0-rc3)和spring mvc(4.0.3)编写REST api,我正在努力使其安全。

I'm currently writing a REST api using Jackson (2.4.0-rc3) and spring mvc (4.0.3), and I'm trying to make it secure.

通过这种方式,我尝试使用JsonView来选择可以序列化的对象部分。

In this way, I try to use JsonView to select the parts of the objects that can be serialized.

我找到了解决方案(不适合我)用我想要的视图注释我的Controller方法。但是我想动态选择控制器内部的视图。

I've found the solution (which is not for me) to annotate my Controller method with the view I want. But I'd like to select on the fly the view inside the controller.

是否可以扩展ResponseEntity类以指定我想要的JsonView?

Is it possible to extend the ResponseEntity class in order to specify which JsonView I want ?

一小段代码:

这是帐户类

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<Account> getById(@PathVariable(value = "accountId") Long accountId) {
        try {
            return new ResponseEntity<Account>(this.getAccountSrv().getById(accountId), HttpStatus.OK);
        } catch (ServiceException e) {
            return new ResponseEntity<Account>(HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    @Override
    @RequestMapping(value = "/get_by_mail_address/{mail_address}", method = RequestMethod.GET, headers = "Accept=application/json")
    public ResponseEntity<Account> getByMailAddress(@PathVariable(value = "mail_address") String mailAddress) {
        try {
            return new ResponseEntity<Account>(this.getAccountSrv().getByMailAddress(mailAddress), HttpStatus.OK);
        } catch (ServiceException e) {
            return new ResponseEntity<Account>(HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    @Override
    @RequestMapping(value = "/authenticate/{mail_address}/{password}", method = RequestMethod.GET, headers = "Accept=application/json")
    public ResponseEntity<Account> authenticate(@PathVariable(value = "mail_address") String mailAddress, @PathVariable(value = "password") String password) {
        return new ResponseEntity<Account>(HttpStatus.NOT_IMPLEMENTED);
    }
}


推荐答案

我已经解决了我的问题,扩展了ResponseEntity,如下所示:

I've solved my problem extending ResponseEntity like this :

public class ResponseViewEntity<T> extends ResponseEntity<ContainerViewEntity<T>> {

    private Class<? extends BaseView> view;

    public ResponseViewEntity(HttpStatus statusCode) {
        super(statusCode);
    }

    public ResponseViewEntity(T body, HttpStatus statusCode) {
        super(new ContainerViewEntity<T>(body, BaseView.class), statusCode);
    }

    public ResponseViewEntity(T body, Class<? extends BaseView> view, HttpStatus statusCode) {
        super(new ContainerViewEntity<T>(body, view), statusCode);
    }

}

和ContainerViewEntity封装了对象和选择的视图

and ContainerViewEntity encapsulate the object and the selected view

public class ContainerViewEntity<T> {

    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;
    }
}

之后,我们只转换了对象好看。

After that, we have convert only the object with the good view.

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);
    }

}

要完成,我启用转换器

<mvc:annotation-driven>
    <mvc:message-converters>
        <bean class="wc.handler.view.JsonViewMessageConverter"/>
    </mvc:message-converters>
</mvc:annotation-driven>

就是这样,我可以在控制器中选择View

And that's it, I can select the View in the controller

@Override
@RequestMapping(value = "/get_by_id/{accountId}", method = RequestMethod.GET, headers = "Accept=application/json")
public ResponseViewEntity<Account> getById(@PathVariable(value = "accountId") Long accountId) throws ServiceException {
    return new ResponseViewEntity<Account>(this.getAccountSrv().getById(accountId), PublicView.class, HttpStatus.OK);
}

这篇关于在Spring MVC Controller中选择JsonView的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆