java querystring_搞定queryString

querystring字面上的意思就是查询字符串,一般是对http请求所带的数据进行解析。querystring模块只提供4个方法:

querystring.parse

querystring.stringify

querystring.escape

querystring.unescape

这4个方法是相对应的。

首先,使用querystring模块之前,需要require进来:

const querystring = require("querystring");

其次,就可以使用模块下的方法了:

1 querystring.parse(str,separator,eq,options)

parse这个方法是将一个字符串反序列化为一个对象。

参数:

str指需要反序列化的字符串;

separator(可省)指用于分割str这个字符串的字符或字符串,默认值为"&";

eq(可省)指用于划分键和值的字符或字符串,默认值为"=";

options(可省)该参数是一个对象,里面可设置maxKeys和decodeURIComponent这两个属性:

maxKeys:传入一个number类型,指定解析键值对的最大值,默认值为1000,如果设置为0时,则取消解析的数量限制;

decodeURIComponent:传入一个function,用于对含有%的字符串进行解码,默认值为querystring.unescape。在官方API的例子中,使用gbkDecodeURIComponent这个方法会报错,显示gbkDecodeURIComponent is no defined,这是因为在使用这个gbkDecodeURIComponent这个方法之前需要先进行定义。在API中也写了Assuming gbkDecodeURIComponent function already exists...这句话的意思是”假设这个gbkDecodeURIComponent方法已经存在”。

例子1,querystring.parse

1 querystring.parse("name=whitemu&sex=man&sex=women");2 /*3 return:

4 { name: 'whitemu', sex: [ 'man', 'women' ] }

5*/

6 querystring.parse("name=whitemu#sex=man#sex=women","#",null,{maxKeys:2});7 /*8 return:

9 { name: 'whitemu', sex: 'man' }

10*/

2 querystring.stringify(obj,separator,eq,options)

stringify这个方法是将一个对象序列化成一个字符串,与querystring.parse相对。

参数:

obj指需要序列化的对象

separator(可省)用于连接键值对的字符或字符串,默认值为"&";

eq(可省)用于连接键和值的字符或字符串,默认值为"=";

options(可省)传入一个对象,该对象可设置encodeURIComponent这个属性:

encodeURIComponent:值的类型为function,可以将一个不安全的url字符串转换成百分比的形式,默认值为querystring.escape()。

例子2,querystring.stringify

querystring.stringify({name: 'whitemu', sex: [ 'man', 'women'] });/*return:

'name=whitemu&sex=man&sex=women'*/querystring.stringify({name:'whitemu', sex: [ 'man', 'women' ] },"*","$");/*return:

'name$whitemu*sex$man*sex$women'*/

3 querystring.escape(str)

escape可使传入的字符串进行编码

例子3,querystring.escape

querystring.escape("name=慕白");/*return:

'name%3D%E6%85%95%E7%99%BD'*/

4 querystring.unescape(str)

unescape方法可将含有%的字符串进行解码

例子4,querystring.unescape

querystring.unescape('name%3D%E6%85%95%E7%99%BD');/*return:

'name=慕白'*/

小结:

querystring这个模块相对的还是比较简单,仅有4个方法。

querystring.stringify序列化;

querystring.parse反序列化;

querystring.escape编码;

querystring.unescape解码;

进阶版

可以写一个函数,专门用于做转换

private object ConvertParameter(string name, object defaultValue, bool isRequired)

我们甚至还可以把它抽象出来一个方法。

提取抽象方法

用Attribute和反射的思想,首先给变量设置HttpQueryString的属性,绑定上相应的QueryString,然后由Page基类来读取相应的QueryString信息。

属性这么写(HttpQueryStringAttribute.cs):

[AttributeUsage(AttributeTargets.Field)]public sealed classHttpQueryStringAttribute : Attribute {privatestring _name;privateobject _defaultValue;privatebool _isRequired;publicHttpQueryStringAttribute(string name) {

_name=name;

_defaultValue= null;

_isRequired= true;

}publicHttpQueryStringAttribute(string name, object defaultValue) {

_name=name;

_defaultValue=defaultValue;

_isRequired= false;

}publicstring Name {

get {return_name; }

}publicobject DefaultValue {

get {return_defaultValue; }

}publicbool IsRequired

{

get {return_isRequired; }

}

}

页面基类是这样的(PageBase.cs):

public classPageBase : Page

{protected override voidOnLoad(System.EventArgs e) {

ParameterInitialize();

base.OnLoad(e);

}private voidParameterInitialize() {

Type type= this.GetType();

FieldInfo[] fields=type.GetFields();

foreach (FieldInfo field in fields)

{

HttpQueryStringAttribute attribute=(HttpQueryStringAttribute)Attribute.GetCustomAttribute(field, typeof(HttpQueryStringAttribute));if (attribute != null)

{

SetField(field, attribute);

}

}

}private voidSetField(FieldInfo field, HttpQueryStringAttribute attribute)

{if(attribute.IsRequired)

{if (Request.QueryString[attribute.Name] != null)

{

SetFieldValue(field,this, attribute.Name, field.FieldType);

}else{throw new Exception(string.Format("Query string /"{0}/" is required", attribute.Name), newNullReferenceException());

}

}else{if (attribute.DefaultValue == null || field.FieldType ==attribute.DefaultValue.GetType())

{if (Request.QueryString[attribute.Name] == null || Request.QueryString[attribute.Name] ==string.Empty)

{

field.SetValue(this, attribute.DefaultValue);

}else{

SetFieldValue(field,this, attribute.Name, field.FieldType);

}

}else{throw new Exception(string.Format("Invalid default value of query string /"{0}/"({1})", attribute.Name, field.Name), newNullReferenceException());

}

}

}private voidSetFieldValue(FieldInfo field, object obj, string name, Type conversionType) {try{

field.SetValue(obj, Convert.ChangeType(Request.QueryString[name], conversionType));

}catch(Exception ex)

{throw new Exception(string.Format("The given value of query string /"{0}/" can not be convert to {1}", name, conversionType), ex);

}

}

}

在页面里,这样写就OK了(Default.aspx.cs):

public partial class_Default : PageBase

{

[HttpQueryString("Name", "Anonymous")]publicstring name;

[HttpQueryString("UserId")]public intuserId;protected voidPage_Load(object sender, EventArgs e)

{

Response.Write(string.Format("Name is {0}
", name));

Response.Write(string.Format("UserId is {0}
", userId));

}

}

讨论

根据定义的变量的数据类型自动转换对应的QueryString,可以省去以后在页面里处理Query String的代码。

反过来想,QueryString 的处理没必要上升到反射的高度,复杂的实现也许会丧失一定的灵活性。比如我某个值忽然要改为从 Form 里面得到呢?从 Session 得到呢?这时候就可以比较出哪种做法更适合敏捷的适应需求。

页面里的 QueryString 的处理,之所以大家都很痛恨手工写编码,无非是因为这么几点:

需要判断是否 == null 才敢用 .ToString(), 很不爽。稍微不注意,就会抛出异常导致页面错误。

整形,double 等值类型从 QueryString 里面获取的时候,不知道是否为合法的数值,因此 Parse 的时候总是要写重复的处理异常的代码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值