簡體   English   中英

MessageBodyWriter的結果未發送到瀏覽器

[英]Result from MessageBodyWriter is not sent to browser

這是我的Resource類:

@Component
@Path("forum/categories")
@Produces(MediaType.APPLICATION_JSON)
public class ForumCategoryResource {

@Context
UriInfo uriInfo;

@Resource(name="forumService")
private ForumService forumService;

@GET
@Path("tree/{rootId}")
@Produces(MediaType.APPLICATION_JSON)
public Response getCategoryTreeById(@PathParam("rootId") Integer rootId) {

    System.out.println("Got request for tree by id: " + rootId);

    Tree<ForumCategory> tree = forumService.getCategoryTreeById(rootId);

    return Response.ok(new GenericEntity<Tree<ForumCategory>>(
            tree, tree.getClass()
    )).build(); 
}

這是我的數據類型通用類:

public class Tree<T> {

    public interface Converter<T, S> {
        S convert (T t);
    }

    public enum IterationStrategy {
        PREORDER,
        LEVELORDER,
        POSTORDER
    }

    private T value;
    private Tree<T> parent;
    private List<Tree<T>> children;
    private int height;

    public Tree(Tree<T> tree) {

        this.value = tree.value;
        this.children = createListAdapterForHeightCalculation(tree.children);
        this.parent = tree.parent;
        this.height = tree.height;
    }

    public Tree(T value) {
        this.value = value;
        this.children = createListAdapterForHeightCalculation(Lists.<Tree<T>>newArrayList());
        this.height = 1;
    }

    public Tree<T> add(Tree<T> tree) {
        children.add(tree);
        tree.parent = this;
        calculateHeightToRoot(tree);
        return tree;
    }

    private ListAdapter<Tree<T>> createListAdapterForHeightCalculation(final List<Tree<T>> list) {
        return new ListAdapter<Tree<T>>(list) {

            @Override
            public Tree<T> remove(int index) {
                Tree<T> removedElement = super.remove(index);               
                int newMaxHeightAtThisLevel = getMaxHeight(list);
                removedElement.parent.height = newMaxHeightAtThisLevel + 1;
                calculateHeightToRoot(removedElement.parent);
                return removedElement;
            }

            private int getMaxHeight(List<Tree<T>> children) {

                int result = 0;

                for (Tree<T> tree : children) {
                    result = Math.max(tree.height, result);
                }

                return result;
            }
        };      
    }

    private void calculateHeight(Tree<T> parent, Tree<T> child) {
        int height = Math.max(parent.height, child.height + 1);
        parent.height = height;
    }

    private void calculateHeightToRoot(Tree<T> tree) {

        Tree<T> parent = tree.parent;
        Tree<T> child = tree;


        while ( ! child.isRoot() ) {
            calculateHeight(parent, child);
            parent = parent.parent;
            child = child.parent;
        }
    }

    public <S> Tree<S> convert(Converter<T, S> converter) {

        Tree<S> result = new Tree<S>(converter.convert(this.value));

        for (Tree<T> child : this.children) {
            result.add(child.convert(converter));
        }

        return result;
    }

    public Tree<T> add(T value) {
        return add(new Tree<T>(value));
    }

    public int getHeight() {
        return height;
    }

    public Tree<T> getParent() {
        return parent;
    }

    public T getValue() {
        return value;
    }

    public List<Tree<T>> getChildren() {
        return children;        
    }

    public boolean isRoot() {
        return parent == null;
    }

    public boolean isLeaf() {
        return children.isEmpty();
    }

    public boolean hasParent() {
        return ! isRoot();
    }

    public boolean hasChildren() {
        return ! isLeaf();
    }

    @Override
    public String toString() {
        return toString(this, null);
    }

    private String toString(Tree<T> tree, String prefix) {

        prefix = (prefix == null) ? "" : prefix;

        StringBuilder result = new StringBuilder(prefix + ObjectUtils.toString(tree.value) + ":" + tree.height);
        result.append("\n");

        for (Tree<T> child : tree.children) {
            String newPrefix;
            if (StringUtils.isEmpty(prefix)) {
                newPrefix = "|- ";
            }
            else {
                newPrefix = "| " + prefix;
            }
            result.append(toString(child, newPrefix));
        }

        return result.toString();
    }

    public List<T> getPathFromRoot() {
        List<T> result = getPathToRoot();
        Collections.reverse(result);
        return result;
    }

    public List<T> getPathToRoot() {
        List<T> result = new ArrayList<T>();

        Tree<T> pathElement = this;

        while ( ! pathElement.isRoot() ) {
            result.add(pathElement.value);
            pathElement = pathElement.parent;
        }

        result.add(pathElement.value);
        return result;
    }

    public boolean containsChildWithValue(T value) {
        for (Tree<T> child : children) {
            if (ObjectUtils.equals(value,child.getValue())) return true;
        }
        return false;
    }

    public Tree<T> findFirst(T value) {
        return findFirst(value, IterationStrategy.PREORDER);
    }

    public Tree<T> findFirst(T value, IterationStrategy strategy) {

        switch (strategy) {

            case PREORDER: return findFirstPreOrder(this, value);
            case LEVELORDER: return findFirstLevelOrder(Arrays.asList(this), value);
            case POSTORDER: return findFirstPostOrder(this, value);
        }

        return null;
    }

    private Tree<T> findFirstLevelOrder(List<Tree<T>> treeList, T value) {

        List<Tree<T>> treeListChildren = new ArrayList<Tree<T>>();

        for (Tree<T> tree : treeList) {
            if (tree.value.equals(value)) {
                return tree;
            }

            treeListChildren.addAll(tree.children);
        }

        if (treeListChildren.size() > 0) {
            return findFirstLevelOrder(treeListChildren, value);
        }

        return null;
    }

    private Tree<T> findFirstPostOrder(Tree<T> tree, T value) {

        for (Tree<T> child : tree.children) {
            Tree<T> result = findFirstPostOrder(child, value);
            if (result != null) {
                return result;
            }
        }

        if (tree.value.equals(value)) {
            return tree;
        }

        return null;
    }

    private Tree<T> findFirstPreOrder(Tree<T> tree, T value) {

        if (tree.value.equals(value)) {
            return tree;
        }

        for (Tree<T> child : tree.children) {
            Tree<T> result = findFirstPreOrder(child, value);
            if (result != null) return result;
        }

        return null;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result
                + ((children == null) ? 0 : children.hashCode());
        result = prime * result + height;
        result = prime * result + ((value == null) ? 0 : value.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        @SuppressWarnings("unchecked")
        Tree<T> other = (Tree<T>) obj;
        if (children == null) {
            if (other.children != null)
                return false;
        } else if (!children.equals(other.children))
            return false;
        if (height != other.height)
            return false;
        if (value == null) {
            if (other.value != null)
                return false;
        } else if (!value.equals(other.value))
            return false;
        return true;
    }

}

這是我的域類:

public class ForumCategory {

    private Integer forumCategoryId;
    private String nameKey;
    private String descriptionKey;

    public ForumCategory() {
    }

    public ForumCategory(String nameKey, String descriptionKey) {
        this.nameKey = nameKey;
        this.descriptionKey = descriptionKey;
    }

    @Override
    public int hashCode() {
        return new HashCodeBuilder().append(forumCategoryId).toHashCode();
    }

    @Override
    public boolean equals(Object obj) {

        if (this == obj) {
            return true;
        }

        if (obj == null) {
            return false;
        }

        if (getClass() != obj.getClass()) {
            return false;
        }

        ForumCategory other = (ForumCategory) obj;
        return new EqualsBuilder().append(this.forumCategoryId, other.forumCategoryId).isEquals();
    }

    public String getNameKey() {
        return nameKey;
    }

    public void setNameKey(String nameKey) {
        this.nameKey = nameKey;
    }

    public String getDescriptionKey() {
        return descriptionKey;
    }

    public void setDescriptionKey(String descriptionKey) {
        this.descriptionKey = descriptionKey;
    }

    public Integer getForumCategoryId() {
        return forumCategoryId;
    }

    public void setForumCategoryId(Integer forumCategoryId) {
        this.forumCategoryId = forumCategoryId;
    }

    @Override
    public String toString() {
        return "ForumCategory [forumCategoryId=" + forumCategoryId
                + ", nameKey=" + nameKey + ", descriptionKey=" + descriptionKey
                + "]";
    }


}

這是我的Tree類的MessageBodyWriter:

@Provider
@Produces(MediaType.APPLICATION_JSON)
public class TreeWriter implements MessageBodyWriter<Tree<?>> {

    private static final Tree<?> NULL_TREE = new Tree<Object>((Object)null);
    private static final Charset CHARSET = Charset.forName("UTF-8");

    private ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public boolean isWriteable(Class<?> type, Type genericType,
            Annotation[] annotations, MediaType mediaType) {

        System.out.println("isWritable");
        return type == NULL_TREE.getClass();
    }

    @Override
    public long getSize(Tree<?> tree, Class<?> type, Type genericType,
        Annotation[] annotations, MediaType mediaType) {
        System.out.println("getSize");

        try {
            return getTreeAsJsonString(tree).length() * Character.SIZE / Byte.SIZE;
        } 
        catch (IOException e) {
            throw new WebApplicationException(e);
        }
    }

    @Override
    public void writeTo(Tree<?> tree, Class<?> type, Type genericType,
            Annotation[] annotations, MediaType mediaType,
            MultivaluedMap<String, Object> httpHeaders,
            OutputStream entityStream) throws IOException,
            WebApplicationException {

        System.out.println("writeTo");
        System.out.println(tree);
        String jsonString = getTreeAsJsonString(tree);
        System.out.println(jsonString);
        entityStream.write(jsonString.getBytes(CHARSET));
        entityStream.flush();
    }

    private String getTreeAsJsonString(Tree<?> tree) throws IOException {

        if (tree != null) {

            StringBuilder result = new StringBuilder();
            appendTree(result, tree);
            return result.toString();
        }

        return "null";
    }

    private void appendTree(StringBuilder result, Tree<?> tree) throws IOException {

        result.append("{");     
        appendTreeValue(result, tree);
        result.append(",");
        appendTreeChildren(result, tree);
        result.append(",");
        appendTreeHeight(result, tree);
        result.append("}");

    }

    private void appendTreeHeight(StringBuilder result, Tree<?> tree) {
        result.append("\"height\":");
        result.append(tree.getHeight());
    }

    private void appendTreeChildren(StringBuilder result, Tree<?> tree) throws IOException {

        result.append("\"children\":[");

        boolean hasChildren = false;

        for (Tree<?> child : tree.getChildren()) {
            appendTree(result, child);
            result.append(",");
            hasChildren = true;
        }

        if (hasChildren) {
            result.deleteCharAt(result.length() - 1);
        }

        result.append("]");
    }

    private void appendTreeValue(StringBuilder result, Tree<?> tree) throws IOException {
        result.append("\"value\":");
        result.append(objectMapper.writeValueAsString(tree.getValue()));        
    }
}

從System.out.println代碼中獲得以下輸出:

Got request for tree by id: 1
isWritable
getSize
writeTo
ForumCategory [forumCategoryId=1, nameKey=cat.name.a, descriptionKey=cat.desc.a]:2
|- ForumCategory [forumCategoryId=2, nameKey=a, descriptionKey=b]:1

{"value":{"forumCategoryId":1,"nameKey":"cat.name.a","descriptionKey":"cat.desc.a"},"children":[{"value":{"forumCategoryId":2,"nameKey":"a","descriptionKey":"b"},"children":[],"height":1}],"height":2}

問題是我的瀏覽器沒有任何顯示。 從普通的POJO接收json就像一個咒語。 我唯一的問題是從返回Tree <?>數據的其余服務獲得答案。

編輯:

我嘗試使用POSTMAN rest客戶端,但失敗,並顯示以下消息:

響應狀態為0。有關何時發生此事件的更多詳細信息,請查看W3C XMLHttpRequest Level 2規范。

W3C規范說:

status屬性必須返回運行以下步驟的結果:

如果狀態為未發送或已打開,則返回0並終止這些步驟。

如果設置了錯誤標志,則返回0並終止這些步驟。

返回HTTP狀態代碼。

我想到了。

首先,我嘗試從getSize返回0。

然后,我可能使用string.length()* Character.SIZE / Byte.SIZE錯誤地計算了長度。

然后,我嘗試從getSize返回-1,這使得jersey-json自行計算長度。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM