在URL参数中传递复杂对象

假设您要传递原始数据类型,例如复杂的Java对象
java.util.Data,java.lang.List,泛型类,数组以及通过URL参数所需的所有内容,以便在页面加载后在任何网页上预设默认值。 共同的任务? 是的,但是可用的解决方案主要限于java.lang.String的编码/解码。 我将展示的方法对数据类型没有任何限制。 URL大小的限制只有一个限制。 长度超过2083个字符的URL在旧的IE版本中可能无法正常工作。 现代Firefox,Opera和Safari可以处理URL中的至少80000个字符。

如果我们将对象序列化为JSON并在服务器端反序列化它们,则可以通过URL参数传递任何类型的对象。 编码的JSON字符串具有有效的
格式,这是一种方法! 好吧,但是有一个问题。 如果对象是非通用类型,则从JSON格式序列化/反序列化可以正常工作。 但是,如果对象属于通用类型,则通用类型信息会因为Java Type Erasure而丢失。 在这种情况下该怎么办? 我要演示的解决方案不仅仅限于JSF,而是在开发Java / Web前端时,我正在这个圈子中旋转……所以,让我们开始吧。 首先,我们需要一个适当的转换器来接收JSON格式的URL参数,并将其转换回Java。 PrimeFaces扩展提供了一个– JsonConverter.java。 怎么运行的? 以下示例显示如何将JsonConverter应用于f:viewParam,以将JSON格式的字符串列表转换为Java中的列表。

<f:metadata>
    <f:viewParam name='subscriptions' value='#{subscriptionController.subscriptions}'>
        <pe:convertJson type='java.util.List<java.lang.String>' />
    </f:viewParam>
</f:metadata>

<h:selectManyCheckbox value='#{subscriptionController.subscriptions}'>
    <f:selectItem id='item1' itemLabel='News' itemValue='1' />
    <f:selectItem id='item2' itemLabel='Sports' itemValue='2' />
    <f:selectItem id='item3' itemLabel='Music' itemValue='3' />
</h:selectManyCheckbox>

JsonConverter具有一种可选的属性类型。 我们不需要为诸如boolean或int之类的原语提供数据类型信息。 但是通常,类型信息是必要的属性。 它指定值对象的数据类型。 支持任何原始类型,数组,非通用或通用类型。 该类型由完全限定的类名(原始类型除外)组成。 例子:

'long[]'
'java.lang.String'
'java.util.Date'
'java.util.Collection<java.lang.Integer>'
'java.util.Map<java.lang.String, com.prime.FooPair<java.lang.Integer, java.util.Date>>'
'com.prime.FooNonGenericClass'
'com.prime.FooGenericClass<java.lang.String, java.lang.Integer>'
'com.prime.FooGenericClass<int[], com.prime.FooGenericClass<com.prime.FooNonGenericClass, java.lang.Boolean>>'

该类型的字符串在运行时进行解析。 JsonConverter的代码在这里可用 (供有兴趣的读者使用)。 JsonConverter基于其他三个类: ParameterizedTypeImpl.java
GsonConverter.javaDateTypeAdapter.java 。 最后一个是用于日期的特殊适配器,因为java.util.Date应该转换为毫秒长,然后再转换回java.util.Date。 到目前为止,一切都很好。 但是,如何在Java端准备这些值作为URL参数呢? 我将展示一个可用于该目的的实用程序类。 请阅读评论,它们是不言自明的。

import org.apache.log4j.Logger;
import org.primefaces.extensions.converter.JsonConverter;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpServletRequest;

/**
 * Builder for request parameters.
 */
public class RequestParameterBuilder {

    private Logger LOG = Logger.getLogger(RequestParameterBuilder.class);

    private StringBuilder buffer;
    private String originalUrl;
    private JsonConverter jsonConverter;
    private String encoding;
    private boolean added;

    /**
     * Creates a builder instance by the current request URL.
     */
    public RequestParameterBuilder() {
        this(((HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest()).getRequestURL()
            .toString());
    }

    /**
     * Creates a builder instance by the given URL.
     *
     * @param url URL
     */
    public RequestParameterBuilder(String url) {
        buffer = new StringBuilder(url);
        originalUrl = url;
        jsonConverter = new JsonConverter();

        encoding = FacesContext.getCurrentInstance().getExternalContext().getRequestCharacterEncoding();
        if (encoding == null) {
            encoding = 'UTF-8';
        }
    }

    /**
     * Adds a request parameter to the URL without specifying a data type of the given parameter value.
     * Parameter's value is converted to JSON notation when adding. Furthermore, it will be encoded
     * according to the acquired encoding.
     *
     * @param name name of the request parameter
     * @param value value of the request parameter
     * @return RequestParameterBuilder updated this instance which can be reused
     */
    public RequestParameterBuilder paramJson(String name, Object value) throws UnsupportedEncodingException {
        return paramJson(name, value, null);
    }

    /**
     * Adds a request parameter to the URL with specifying a data type of the given parameter value. Data type is sometimes
     * required, especially for Java generic types, because type information is erased at runtime and the conversion to JSON
     * will not work properly. Parameter's value is converted to JSON notation when adding. Furthermore, it will be encoded
     * according to the acquired encoding.
     *
     * @param name name of the request parameter
     * @param value value of the request parameter
     * @param type data type of the value object. Any primitive type, array, non generic or generic type is supported.
     *             Data type is sometimes required to convert a value to a JSON representation. All data types should be
     *             fully qualified.
     * @return RequestParameterBuilder updated this instance which can be reused
     */
    public RequestParameterBuilder paramJson(String name, Object value, String type)
        throws UnsupportedEncodingException {
        jsonConverter.setType(type);

        String jsonValue;
        if (value == null) {
            jsonValue = 'null';
        } else {
            jsonValue = jsonConverter.getAsString(null, null, value);
        }

        if (added || originalUrl.contains('?')) {
            buffer.append('&');
        } else {
            buffer.append('?');
        }

        buffer.append(name);
        buffer.append('=');
        buffer.append(URLEncoder.encode(jsonValue, encoding));

        // set a flag that at least one request parameter was added
        added = true;

        return this;
    }

    /**
     * Adds a request parameter to the URL. This is a convenient method for primitive, plain data types.
     * Parameter's value will not be converted to JSON notation when adding. It will be only encoded
     * according to the acquired encoding. Note: null values will not be added.
     *
     * @param name name of the request parameter
     * @param value value of the request parameter
     * @return RequestParameterBuilder updated this instance which can be reused
     */
    public RequestParameterBuilder param(String name, Object value) throws UnsupportedEncodingException {
        if (value == null) {
            return this;
        }

        if (added || originalUrl.contains('?')) {
            buffer.append('&');
        } else {
            buffer.append('?');
        }

        buffer.append(name);
        buffer.append('=');
        buffer.append(URLEncoder.encode(value.toString(), encoding));

        // set a flag that at least one request parameter was added
        added = true;

        return this;
    }

    /**
     * Builds the end result.
     *
     * @return String end result
     */
    public String build() {
        String url = buffer.toString();

        if (url.length() > 2083) {
            LOG.error('URL ' + url + ' is longer than 2083 chars (' + buffer.length() +
                '). It may not work properly in old IE versions.');
        }

        return url;
    }

    /**
     * Resets the internal state in order to be reused.
     *
     * @return RequestParameterBuilder reseted builder
     */
    public RequestParameterBuilder reset() {
        buffer = new StringBuilder(originalUrl);
        jsonConverter.setType(null);
        added = false;

        return this;
    }
}

通常,使用RequestParameterBuilder的bean通过调用paramJson(…)或param(…)提供参数化的URL。

import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;

/**
 * UrlParameterProvider bean.
 */
@ManagedBean
@SessionScoped
public class UrlParameterProvider implements Serializable {

    private String parametrizedUrl;

    @PostConstruct
    protected void initialize() {
        RequestParameterBuilder rpBuilder = new RequestParameterBuilder('/views/examples/params.jsf');
        try {
            List<String> subscriptions = new ArrayList<String>();
            tableBlockEntries.add('2');
            tableBlockEntries.add('3');

            // add the list to URL parameters with conversion to JSON
            rpBuilder.paramJson('subscriptions', subscriptions, 'java.util.List<java.lang.String>');

            // add int values to URL parameters without conversion to JSON (just for example)
            rpBuilder.param('min', 20);
            rpBuilder.param('max', 80);   
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }

        parametrizedUrl = rpBuilder.build();
    }

    public String getParametrizedUrl() {
        return parametrizedUrl;
    }
}

在XHTML中使用– h:outputLink示例

<h:outputLink value='#{urlParameterProvider.parametrizedUrl}'>
    Parametrized URL
</h:outputLink>

一旦用户单击链接并以相对路径/视图/示例/params.jsf登陆目标页面,他/她将看到一个预先检查的h:selectManyCheckbox。 现实世界更加复杂。 实际上,我已经写了很多内置JsonConverter的自定义转换器。 因此,附加了自定义转换器,而不是<pe:convertJson type ='…'/>。 这个主题超出了这篇文章。

参考:来自JCG合作伙伴 Oleg Varaksin的URL参数中的复杂对象传递, 位于软件开发博客上。

翻译自: https://www.javacodegeeks.com/2013/03/passing-complex-objects-in-url-parameters.html

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用JSON.stringify()将对象转换为字符串,并使用encodeURI()对字符串进行编码,然后将编码后的字符串作为参数添加到URL。例如,假设有一个名为objDemo的对象,可以使用以下代码将其作为参数传递URL: ```javascript let objDemo = { name: "zdd", age: 12, content: "abc" }; let jsonObj = JSON.stringify(objDemo); jsonObj = encodeURI(jsonObj); let url = "http://localhost:8080/demo?id=" + jsonObj; console.log(url); ``` 这样,objDemo对象就会被转换为字符串并编码后作为参数添加到URL。在接收端,可以使用decodeURI()对参数进行解码,并使用JSON.parse()将字符串转换回对象。例如: ```javascript jsonObj = decodeURI(jsonObj); jsonObj = JSON.parse(jsonObj); console.log(jsonObj); ``` 这样就可以将URL参数对象还原为原始的JavaScript对象。 #### 引用[.reference_title] - *1* [url怎么转递对象参数](https://blog.csdn.net/baidu_39812199/article/details/104492133)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [url传递对象参数_在URL参数传递复杂对象](https://blog.csdn.net/dnc8371/article/details/107270157)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值