搞定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 class HttpQueryStringAttribute : Attribute {
private string _name;
private object _defaultValue;
private bool _isRequired;
public HttpQueryStringAttribute(string name) {
_name = name;
_defaultValue = null;
_isRequired = true;
}
public HttpQueryStringAttribute(string name, object defaultValue) {
_name = name;
_defaultValue = defaultValue;
_isRequired = false;
}
public string Name {
get { return _name; }
}
public object DefaultValue {
get { return _defaultValue; }
}
public bool IsRequired
{
get { return _isRequired; }
}
}
页面基类是这样的(PageBase.cs):
public class PageBase : Page
{
protected override void OnLoad(System.EventArgs e) {
ParameterInitialize();
base.OnLoad(e);
} private void ParameterInitialize() {
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 void SetField(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), new NullReferenceException());
}
}
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), new NullReferenceException());
}
}
} private void SetFieldValue(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")]
public string name; [HttpQueryString("UserId")]
public int userId; protected void Page_Load(object sender, EventArgs e)
{
Response.Write(string.Format("Name is {0}<br/>", name));
Response.Write(string.Format("UserId is {0}<br/>", userId));
}
}
讨论
根据定义的变量的数据类型自动转换对应的QueryString,可以省去以后在页面里处理Query String的代码。
反过来想,QueryString 的处理没必要上升到反射的高度,复杂的实现也许会丧失一定的灵活性。比如我某个值忽然要改为从 Form 里面得到呢?从 Session 得到呢?这时候就可以比较出哪种做法更适合敏捷的适应需求。
页面里的 QueryString 的处理,之所以大家都很痛恨手工写编码,无非是因为这么几点:
- 需要判断是否 == null 才敢用 .ToString(), 很不爽。稍微不注意,就会抛出异常导致页面错误。
- 整形,double 等值类型从 QueryString 里面获取的时候,不知道是否为合法的数值,因此 Parse 的时候总是要写重复的处理异常的代码。
搞定queryString的更多相关文章
- 【开源】简单4步搞定QQ登录,无需什么代码功底【无语言界限】
说17号发超简单的教程就17号,qq核审通过后就封装了这个,现在放出来~~ 这个是我封装的一个开源项目:https://github.com/dunitian/LoTQQLogin ————————— ...
- 对百度WebUploader开源上传控件的二次封装,精简前端代码(两句代码搞定上传)
前言 首先声明一下,我这个是对WebUploader开源上传控件的二次封装,底层还是WebUploader实现的,只是为了更简洁的使用他而已. 下面先介绍一下WebUploader 简介: WebUp ...
- 教你怎么半天搞定Docker
首先,不要把docker想的那么高大,它不就是先做个镜像,然后通过docker像虚拟机一样跑起来嘛...docker其实在真实业务场景中还是非常有局限性的.Dockerfile脚本也没那么好写,有些应 ...
- 用ORM的思想操作XML文档,一个对象就搞定不要太简单。滚蛋吧!XmlDocument、XmlNode、Xml***……
大家有没有这样的感受,一涉及XML文档操作就得百度一遍.是不是非!常!烦!.各种类型,各种方法,更别提为了找到一个节点多费劲.本来想写个XML操作的工具方法,写了两行一想既然XML文档是有规律的,如果 ...
- JS组件系列——又一款MVVM组件:Vue(一:30分钟搞定前端增删改查)
前言:关于Vue框架,好几个月之前就听说过,了解一项新技术之后,总是处于观望状态,一直在犹豫要不要系统学习下.正好最近有点空,就去官网了解了下,看上去还不错的一个组件,就抽空研究了下.最近园子里vue ...
- JS组件系列——BootstrapTable+KnockoutJS实现增删改查解决方案(三):两个Viewmodel搞定增删改查
前言:之前博主分享过knockoutJS和BootstrapTable的一些基础用法,都是写基础应用,根本谈不上封装,仅仅是避免了html控件的取值和赋值,远远没有将MVVM的精妙展现出来.最近项目打 ...
- 如何让两个div在同一行显示?一个float搞定
最近在学习div和css,遇到了一些问题也解决了很多以前以为很难搞定的问题.比如:如何让两个div显示在同一行呢?(不是用table表格,table对SE不太友好)其实,<div> 是一个 ...
- 3小时搞定一个简单的MIS系统案例Northwind,有视频、有源代码下载、有真相
一.瞎扯框架.架构 楼主自从1998年从C语言.MASM.Foxbase开始学计算机开始接触这个行当16年以来,2001年干第一份与程序.软件.然后是各种屌的东西开始,差不多干了13年了,这13年来, ...
- 前端实战Demo:一张图片搞定一页布局
对前端程序员来说,从设计师的手中拿过设计图和素材之后根据需要进行切图是必要的基本功,但是一般的程序员可能对切图并非那么熟悉,所以可能有很多时间都花在使用Photoshop上,那么这里就有一种方法可以减 ...
随机推荐
- web.xml配置Servlet出错(DispatcherServlet)
想当然的把servlet-mapping当成servlet的属性 后台也不报错,但是输入url,就是死活不执行那个servlet servlet和servlet-mapping是同一级的对象
- elasticsearch技术解析与实战(一) 入门和索引
GET _cat/nodes GET _cat/health GET _cat/shards GET http://10.37.84.124:9200/secisland?pretty { " ...
- 05基于python玩转人工智能最火框架之TensorFlow基础知识
从helloworld开始 mkdir mooc # 新建一个mooc文件夹 cd mooc mkdir 1.helloworld # 新建一个helloworld文件夹 cd 1.helloworl ...
- 为什么 PCB 生产时推荐出 Gerber 给工厂?
为什么 PCB 生产时推荐出 Gerber 给工厂? 事情是这样的,有一天电工王工,画了一块 PCB,发给 PCB 板厂. 过了几天 PCB 回来了,一看不对呀,这里的丝印怎么少了,那里怎么多了几条线 ...
- 短信验证登陆-中国网建提供的SMS短信平台
一.JAVA发送手机短信常见的有三种方式(如下所列): 使用webservice接口发送手机短信,这个可以使用sina提供的webservice进行发送,但是需要进行注册 使用短信mao的方式进行短信 ...
- 我 支持 使用 async await
这篇文章原来的 标题 是 <我 反对 使用 async await>, 但经过后来的一些研究, 发现 async await 是 良性 的, 所以 我把 标题 改成了 <我 支持 使 ...
- storage 事件监听
在公司的一次内部分享会上, 偶然知道了这个H5的新事件, 解决了我之前的一个bug. 事情是这样的, 第A网页上显示的数量的总和, 点击去是B页面, 可以进行管理, 增加或者删除, 当用户做了增删操作 ...
- 30-seconds-of-css
你可以再30秒或者更短的时间内读懂的有用的CSS代码片段的精选. github地址 不过代码不在github上面 官网地址 上面有详细的介绍和演示 下面是我读到的一些个人认为比较实用的片段 1. 等宽 ...
- mysql 不允许分组的问题
异常信息:this is incompatible with sql_mode=only_full_group_by 解决办法: 找到 my.cnf find / -name my.cnf 然后在 ...
- RedHat6.5安装Spark单机
版本号: RedHat6.5 RHEL 6.5系统安装配置图解教程(rhel-server-6.5) JDK1.8 http://blog.csdn.net/chongxin1/arti ...