C#构造方法(函数)
一、概括
1.通常创建一个对象的方法如图:
通过 Student tom = new Student(); 创建tom对象,这种创建实例的形式被称为构造方法。
简述:用来初始化对象的,为类的成员赋值。
2.构造方法特点
a.方法名与类名相同;
b.没有返回值类型;
c.必须要通过new的形式调用;
3.语法
访问修饰符 类名([参数])
{
方法体
}
二、 无参构造方法
1.在默认情况下,系统将会给类分配一个无参构造方法,并且没有方法体。
通过反编译工具看出:
我们也可以自定义一个无参构造方法,在无参构造方法中对类的属性进行赋值等操作。
三、带参构造方法
如果仅仅局限于无参构造方法,那么属性赋值是固定的,没有对外的可变性。有了参数,给予可以根据业务逻辑,去针对性的赋值操作。
四、构造方法可以形成方法的重载
五、强制使用有参构造方法
上面描述了,系统在类没有构造方法的时候,会生成一个无参构造方法。一旦我们在类中编写了构造方法,那么这个自动生成的无参构造函数就不会生成。根据此特性,我们可以只定义有参构造方法,因此在创建对象的时候,就只能赋值使用有参的构造方法。
构造方法具有强制性的特点。
六、构造方法的复用
1.遵循面向对象思想,因此我们写代码的时候应该减少冗余,增强复用性。构造方法复用形式如下:
用”:this”调用自身其他构造方法。
2.this关键字
a.当成员变量和局部变量重名时使用this区分。
b.this表示当前类的对象,用于访问该类的成员变量或方法。
七、对象初始化器
1.初始化对象的形式
a.常规的“”对象名.属性名=值;“”
b.构造方法;
c.对象初始化器;
2.实现形式:
3.描述
对象初始化器是一种初始化对象的形式,本质上其实就是一种语法糖。它不具有像构造方法那样的强制性,在为属性赋值的时候不用遵守赋值的顺序和数量。
4.对象初始化器与构造方法的异同点
a.构造方法具有强制性,对象初始化器没有强制性。构造方法本质上是一种特性的方法,所有就要遵循方法的调用逻辑。
b.对象初始化器功能单一,智能完成对象属性初始化。而构造方法可以在方法体中灵活的分配,如对象创建时读取文件等需求。
c.顺序的不同,对象初始化器是在调用了构造方法才执行的属性赋值。而构造方法在new 的时候进行调用,并且逻辑代码都是在类里面的。
C#方法重载
一、 描述
在面向对象的语言中,允许我们在同一个类中定义多个方法名相同、参数列表(参数类型,参数个数)不同的方法,这样的形式我们称为方法重载。调用时编译器会根据实际传入参数的形式,选择与其匹配的方法执行。
二、 重载的分析
1.生活中的方法重载
2.将生活重载的表现形式,抽象成代码的形式:
3.构成方法重载的条件
a方法名相同。
b.方法参数类型不同或者参数个数不同。
c.在同一个类中。
三、 重载示例
1.我们实现一个薪水计算类,用重载的方法实现项目经理和程序员的薪水计算
1 class ComSalary 2 { 3 4 //项目经理的薪水计算:薪水=基础工资+项目奖金+分红 5 public static int Pay(PM pm) 6 { 7 return pm.BasePay + pm.MeritPay + pm.Bonus; 8 } 9 10 //程序员的薪水计算:薪水=基础工资+项目奖金 11 public static int Pay(SE se) 12 { 13 return se.BasePay + se.MeritPay; 14 } 15 16 } 17 18 static void Main(string[] args) 19 { 20 21 //实例化一个程序员对象 22 SE tom = new SE { Id="998", Name="汤姆", BasePay=6000, MeritPay=1000}; 23 24 //实例化一个项目经理对象 25 PM jack = new PM { Id = "110", Name = "杰克", BasePay = 9000, MeritPay = 2000, Bonus=1500}; 26 27 //计算工资 28 Console.WriteLine("程序员的薪水:"+ComSalary.Pay(tom)); 29 Console.WriteLine("项目经理的薪水:" + ComSalary.Pay(jack)); 30 31 }
运行结果:
2.示例解析:
通过Pay()方法重载计算项目经理和程序员的薪水。假如我们不用方法重载会怎么样呢?例如,计算程序员薪水写成PaySE(SE se)方法,而计算项目经理的薪水用PayPM(PM pm)方法。这样确实也能完成计算薪水的任务,但是不符合面向对象的思想,造成一些冗余形式。 大家可以想想,在实际开发中计算薪水的员工可能还有很多种角色,如股东等,我们夸张一点,将需要计算的角色设为上千个,那么将不得不写一百个不同的方法。此时,延伸出来的问题有:1.方法命名的困难;2.调用方法者调用方法选择的困难。因此,方法重载就解决了这样的麻烦。
四、重载的细节
1.无关返回值,图例:
结论:仅方法名相同参数列表相同,但返回值类型不同的方法不能构成重载。
2.类中的构造函数也可以实现重载,是方法重载的一种特殊形式。
C#字段和属性
一、浅谈访问修饰符
作用:设定访问权限,限制类中的成员(属性、方法等)可访问的范围,访问范围通常有,类的内部、类的外部。
最常用的类型:private(私有的,仅类的内部使用);public(公有的,没有访问限制)
注意:类的成员在定义的时候没有显示的写出访问修饰符,则默认是private。对应到字段和属性中,通常字段修饰为private,属性修饰为public。
二、字段的使用
1.关于字段
a.字段又称为:“成员变量”,一般在类的内部做数据交互使用。
b.字段命名规范:camel命名法(首单词字母小写)。
2.通俗的理解:
私有化:字段就好比我们的个人财产,仅供个人使用,所以一般是private修饰。
添加标准:根据程序的功能需求,具体来添加需要的不同类型的字段。
四、属性
1.属性的使用
作用:在面向对象设计中主要使用属性描述对象的静态特征。
要求:一般采用Pascal命名法(首字母大写),数据类型要和对应的字段要一致。
2.属性的理解
a.属性其实就是外界访问私有字段的入口,属性本身不保存任何数据,在对属性赋值和读取的时候其实就是操作的对应私有字段。
图例:
b.属性本质其实就是一个方法,通过get和set方法来操作对应的字段,通过反编译工具我们可以看出,如图:
3.属性的作用
A.避免出现非法数据,例如一个年龄属性,正常逻辑是年龄是不可以出现负数的,如果用户对年龄进行了负数的赋值,我们通过属性的set方法加入判断逻辑,从而排除这种非法数据。
示例:
B.限定属性只读或者只写,例如有些属性为了保护数据,我们只能读取,而不能赋值。具体使用的话,我们根据需要,屏蔽set或get方法达到只读和只写。
示例:
C.没有对应私有字段的属性,例如根据生日属性获取到年龄。
示例:
五、字段与属性比较
字段(成员变量)
a.字段主要是为类的内部做数据交互使用,字段一般是private。
b.字段可读可写。
c.当字段需要为外部提供数据的时候,请将字段封装为属性,而不是使用公有字段(public修饰符),这是面向对象思想所提倡的。
属性(方法)
a.属性一般是向外提供数据,主要用来描述对象的静态特征,所以,属性一般是public。
b.属性具备get和set方法,可以在方法里加入逻辑处理数据,灵活拓展使用。
六、自动属性
1.属性编写新语法(自动属性:.NET3.0及其后续版本)
示例:
快捷方式:prop+tab+tab
注意:没有特定业务逻辑的属性都可以简写成自动属性,自动属性的格式不能修改。自动属性对应的字段由编译器自动生成。
MUI实现上拉加载和下拉刷新
编写存储过程分页(此处使用T-SQL)
1 CREATE PROC [dbo].[Common_PageList] 2 ( 3 @tab nvarchar(max),---表名 4 @strFld nvarchar(max), --字段字符串 5 @strWhere varchar(max), --where条件 6 @PageIndex int, --页码 7 @PageSize int, --每页容纳的记录数 8 @Sort VARCHAR(255), --排序字段及规则,不用加order by 9 @IsGetCount bit --是否得到记录总数,1为得到记录总数,0为不得到记录总数,返回记录集 10 ) 11 AS 12 declare @strSql nvarchar(max) 13 set nocount on; 14 if(@IsGetCount = 1) 15 begin 16 set @strSql='SELECT COUNT(0) FROM ' + @tab + ' WHERE ' + @strWhere 17 end 18 else 19 begin 20 set @strSql=' SELECT * FROM (SELECT ROW_NUMBER() 21 OVER(ORDER BY ' + @Sort + ') AS rownum, ' + @strFld + ' FROM ' + @tab + ' where ' + @strWhere + ') AS Dwhere 22 WHERE rownum BETWEEN ' + CAST(((@PageIndex-1)*@PageSize + 1) as nvarchar(20)) + ' and ' + cast((@PageIndex*@PageSize) as nvarchar(20)) 23 end 24 25 print @strSql 26 exec (@strSql) 27 28 set nocount off;
webApi接口(ADO.NET部分封装了,此处是调用形式)
1 /// 测试mui下拉刷新 2 /// </summary> 3 /// <param name="flag"></param> 4 /// <returns></returns> 5 [HttpPost] 6 public object test(JObject data) 7 { 8 9 using (var db = new DbBase()) 10 { 11 SqlParameter[] arr = { 12 new SqlParameter{ ParameterName="tab",Value=data["tab"].ToString()}, 13 new SqlParameter{ ParameterName="strFld",Value=data["strFld"].ToString()}, 14 new SqlParameter{ ParameterName="strWhere",Value=data["strWhere"].ToString()}, 15 new SqlParameter{ ParameterName="PageIndex",Value=Convert.ToInt32(data["PageIndex"])}, 16 new SqlParameter{ ParameterName="PageSize",Value=Convert.ToInt32(data["PageSize"])}, 17 new SqlParameter{ ParameterName="Sort",Value=data["Sort"].ToString()}, 18 new SqlParameter{ ParameterName="IsGetCount",Value=Convert.ToInt32(data["IsGetCount"])}, 19 }; 20 21 22 return RepositoryBase.ExecuteReader(db, "Common_PageList", arr); 23 24 25 }
页面实现
1 <!DOCTYPE html> 2 <html> 3 4 <head> 5 <meta charset="utf-8"> 6 <title>Hello MUI</title> 7 <meta name="viewport" content="width=device-width, initial-scale=1,maximum-scale=1,user-scalable=no"> 8 <meta name="apple-mobile-web-app-capable" content="yes"> 9 <meta name="apple-mobile-web-app-status-bar-style" content="black"> 10 11 <link rel="stylesheet" href="../css/mui.min.css"> 12 <style type="text/css"> 13 14 15 16 </style> 17 </head> 18 19 <body> 20 21 <header class="mui-bar mui-bar-nav"> 22 <h1 class="mui-title">下拉刷新(单webview模式)</h1> 23 </header> 24 25 <div id="pullrefresh" class="mui-content mui-scroll-wrapper"> 26 <div class="mui-scroll"> 27 28 <ul id="container" class="mui-table-view mui-table-view-chevron"></ul> 29 30 31 32 </div> 33 </div> 34 35 36 <ul id="temp" class="mui-table-view" style="display: none;"> 37 <li class="mui-table-view-cell"> 38 <a class="mui-navigate-right"> 39 @name 40 </a> 41 </li> 42 43 </ul> 44 45 46 47 48 49 <script src="../js/mui.js" type="text/javascript" charset="utf-8"></script> 50 <script> 51 52 53 54 /** 55 数据源分页参数对象 56 * */ 57 var obj={ tab:'SystemUsers', 58 strFld:'code,Username', 59 strWhere:'1=1', 60 PageIndex:1, 61 PageSize:10, 62 Sort:'Username', 63 IsGetCount:0, 64 pageCount:0 65 } 66 67 //webApi服务器接口 68 var apiUrl="http://192.168.200.114:8123/api/Common/Base/test"; 69 70 71 /** 72 * 定义数据源按什么html方式展示,动态生成html字符串的逻辑 73 **/ 74 var drawHtml=function(data){ 75 var html="" 76 for (var i=0;i<data.length;i++) 77 { 78 var temp=document.getElementById("temp").innerHTML; //模板 79 html+=temp.toString().replace('@name',data[i].Username); //替换参数叠加 80 } 81 82 return html; 83 } 84 85 86 87 mui.ready(function(){ 88 89 90 /** 91 MUI配置项 92 * */ 93 mui.init({ 94 pullRefresh: { 95 container: '#pullrefresh', 96 down: { 97 callback: pulldownRefresh 98 }, //END 下拉刷新 99 up : { 100 contentrefresh : "正在加载...",//可选,正在加载状态时,上拉加载控件上显示的标题内容 101 contentnomore:'没有更多数据了',//可选,请求完毕若没有更多数据时显示的提醒内容; 102 callback :pullupRefresh //必选,刷新函数,根据具体业务来编写,比如通过ajax从服务器获取新数据; 103 } //END 上拉加载 104 } 105 }); 106 107 108 109 110 111 //统计:数据总数、分页总数 112 obj.IsGetCount=1; 113 loadData(apiUrl,obj,0); 114 115 //初始化列表数据(第一页) 116 obj.IsGetCount=0; 117 loadData(apiUrl,obj,0,"down",function(data){ 118 //此处实现动态绘制DOM的逻辑,根据数据源自行处理要展示的html方式 119 return drawHtml(data); 120 121 }); 122 123 124 }); 125 126 127 128 129 /* 130 读取数据源 131 url:api地址 132 dataObj:数据源分页查询参数对象 133 Timeout:指定多少时间后绘制页面DOM展示对象, 134 动态生成的元素代码包含在一个setTimeout函数里, 135 用 setTimeout,主要对于下拉刷新间隔时间 136 loadType:加载方式:up(上拉加载)、down(上拉刷新) 137 drawFunction:回调函数,处理拿到数据源,绘制DOM展示界面的html 138 ,要接收返回的html字符串 139 * */ 140 141 var loadData=function(url,dataObj,Timeout,loadType,drawFunction){ 142 143 mui.ajax(url, { 144 type: "post", 145 data:dataObj, 146 async:false, 147 headers: {'Content-Type': 'application/json'}, 148 success: function(data) { 149 150 //统计出数据总数 151 if(dataObj.IsGetCount==1) 152 { 153 obj.pageCount=Math.ceil(parseInt(data[0].Column1)/obj.PageSize) ; 154 return; 155 } 156 157 setTimeout(function() { 158 159 //动态绘制出的Dom元素,结合数据展现 160 var html= drawFunction(data); 161 162 if(loadType=="up") //上拉加载 163 { 164 if(obj.PageIndex==obj.pageCount) 165 { 166 //参数为true代表没有更多数据了。 167 mui('#pullrefresh').pullRefresh().endPullupToRefresh(true); 168 } 169 else 170 { 171 mui('#pullrefresh').pullRefresh().endPullupToRefresh(); 172 } 173 174 //将下一页数据追加到容器 175 document.getElementById("container").innerHTML=document.getElementById("container").innerHTML+html; 176 } 177 else if(loadType=="down") //下拉刷新 178 { 179 // 该方法的作用是关闭“正在刷新”的样式提示,内容区域回滚顶部位置 180 mui('#pullrefresh').pullRefresh().endPulldownToRefresh(); 181 182 //将第一页数据覆盖到容器 183 document.getElementById("container").innerHTML=html; 184 185 //启用上拉加载 186 mui('#pullrefresh').pullRefresh().enablePullupToRefresh(); 187 188 } 189 190 191 192 193 194 195 }, Timeout);//END setTimeout(); 196 197 },//END success(); 198 199 error: function(xhr, type, errorThrown) { 200 console.log(type); 201 }//END error(); 202 203 });//END ajax(); 204 205 }//END loadData(); 206 207 208 209 210 211 212 213 /** 214 * 下拉刷新具体业务实现 215 */ 216 function pulldownRefresh() { 217 console.log('重置数据,初始到第一页'); 218 obj.PageIndex=1; 219 220 loadData(apiUrl,obj,1000,"down",function(data){ 221 //此处实现动态绘制DOM的逻辑,根据数据源自行处理要展示的html方式 222 return drawHtml(data); 223 224 }); 225 226 } //END pulldownRefresh() 下拉刷新函数 227 228 229 230 231 232 /** 233 * 上拉加载具体业务实现 234 */ 235 function pullupRefresh() { 236 obj.PageIndex++;//当前页累加,加载下一页的数据 237 console.log("加载第:"+obj.PageIndex+"页"); 238 console.log("页总数:"+obj.pageCount); 239 240 loadData(apiUrl,obj,1000,"up",function(data){ 241 //此处实现动态绘制DOM的逻辑,根据数据源自行处理要展示的html方式 242 return drawHtml(data); 243 244 }); 245 246 247 } 248 249 250 251 </script> 252 </body> 253 254 </html>
改进的问题:当单次数的下拉刷新会自动触发上拉加载。比如:第一次进行下拉,就会自动触发上拉加载,但是第二次就没有。
SVN常用功能介绍(二)
说明
上一章节主要描述了SVN的简介、安装搭建,和项目管理人员对SVN的常用操作。
这章主要讲解,SVN对应角色组员,在实际运用中的常用操作。
将SVN服务器项目导入到开发组员的本地电脑里
方式一:
新建一个文件夹,鼠标右键点击文件夹,点击Checkout
方式二(在VS里操作依赖于VS的SVN插件):
点击后,下面的操作和方式里一样,这里不就不介绍了
在项目中新增文件或修改文件(Commit)
对于修改或者新增的文件,图标为橙色这就表示该文件和SVN服务器里的文件不一致,如图:
对于新增或修改的文件,通常进行任务完成后,我们应当进行想SVN服务器提交的功能,操作如图:
鼠标右键单击文件,在菜单中单击Commit操作,操作成功后文件图标就变成绿色
从SVN服务器拿到一个最新的文件(Update)
VS中查看文件的历史版本
右键单击文件点击菜单中的VisualSVN,在展开菜单中点击Show Log For(查看文件对于历史版本) ......
如图:
单击
通过查看历史版本和项目当前使用文件版本进行对比,操作如图
颜色的不同表示两个文件的差异之处
恢复到历史中的一个版本
总结一下SVN对于项目组员,要使用的常用功能
- 获取最新代码,完成后续开发
- Update:将服务器代码更新到本地
- Commit:将本地代码更新到服务器代码
- 恢复历史版本:右键文件—>show log—>在指定版本上右键—>revert
- 文件对比:右键文件—>show log—>在指定版本上右键compare with working copy
SVN常用功能介绍(一)
简介
SVN是Subversion的简称,是一个开放源代码的版本控制系统,相较于RCS、CVS,它采用了分支管理系统,它的设计目标就是取代CVS。
互联网上很多版本控制服务已从CVS迁移到Subversion。说得简单一点SVN就是用于多个人共同开发同一个项目,共用资源的目的。
SVN两大功能的体现
(1)一个公司一个项目通常会是一个团队一起开发,那么组员开发完了后,如何把代码项目文件等组织到一起来呢?SVN可以解决此问题,组织分工协作的代码,协同多人开发一个项目。
(2)通常一个功能点,可能在实际工作中会根据业务有很多的变更,例如第一期登陆版本开发完毕,又开发了第二期、第三期等等,
这时,客户说不想用当前的版本要使用当初第一期的版本。这个时候如何让项目登陆功能回到第一期呢?SVN可以解决此类问题,
对于历史存留的文件可访问,可以很好的恢复到之前的版本。
使用SVN主要安装的软件
1.VisualSVN-Server:搭建服务区,项目管理人员负责安装
2.TortoiseSVN:将SVN功能集成到windows右键菜单上
3.VisualSVN:对于.net开发人员,相当于VS里SVN的插件
使用SVN职责担当之项目管理人员使用部分
一、主要使用软件
二、服务器里的层次关系
三、项目的权限分配
对于仓库中的每一个项目,项目管理人员可以进行权限分配。可以对一个项目指派一个用户操作,也可以指派一个组。
组合用户,可以指定相应的权限,例如说对于实习生一类的人群可以只分配它查看,没有写的功能。而对于开发人去,可以指定权限让他对项目可读可写的操作。
1.在仓库中创建一个项目
2.项目URL
创建完成后,每个项目都有对应的服务器地址,如图:
https://lenovo-PC/svn/BLOG/
URL的第一部分lenovo-PC是你电脑的主机名,可以替换成本机的IP地址。
在开发过程中,项目人员会将URL告知组员,组员根据URL对项目进行导出。
3.为项目分配管理人员
创建用户:
创建组:
将用户加入到组中:
指定项目分配一组管理人员:
分配完成
注意:在把项目添加到SVN服务器之前,要确保为该项目分配了组员管理,否则在添加过程中会报错。
三、把项目文件加到SVN服务器
方式一:
点击OK后
完成
方式二(通过VS的SVN插件操作):
注意此时还要有一项操作,才能真正把项目导入到SVN服务器中,右击项目在菜单中,点击Commit
ASP.NET常用内置对象之——Server
简介
Server对象是HttpServerUtility的一个实例,也是上下文对象context的一个属性,提供用于处理Web请求的Helper方法。
常用成员
一、Server.MapPath()方法
方法签名:public string MapPath(string path)
描述:指定一个虚拟路径传入,返回对应虚拟路径的Web服务器上的物理路径。等同于Request.MapPath()方法。
二、Server.Execute()方法
方法签名:public void Execute(string path)
描述:在当前请求的上下文中执行指定虚拟路径的处理程序,然后执行返回给调用它的页面。
通俗的说,也就是当前页面调用了Server.Execute方法将一个指定路径的页面进行执行,将内容嵌套在当前页面中,可以实现iframe类似的效果。
示例图解:
WebForm2.apx内容:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm2.aspx.cs" Inherits="WebApplication2.WebForm2" %> <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title></title> </head> <body> <form id="form1" runat="server"> <div> <% Response.Write("我是页面2"); %> </div> </form> </body> </html>
让我们这通过一张图片看看执行原理:
从查看网页源代码,可以看出,Execute方法将指定路径的页面执行输出,作为页面中的一部分进行显示,此技术完全可以实现类似iframe的功能,父页面中嵌套一个子页面
三、Server.Transfer()方法
方法签名:public void Tarnsfer(string path)
描述:对于当前请求(当前页面),终止当前页的执行,并根据传入的URL执行新的页面。
其实Server.Transfer()方法可以看做是一个内部的重定向,是由服务器内部的资源接管,
浏览器察觉不到该请求,Htpp报文里也无法查看到请求信息。还要注意的是该方法重定向请求的页面资源必须是服务器内部的,不能重定向外部的网站。
示例图解:
在执行结束后浏览器的地址栏不会发生变化,因为是内部的,浏览器不知道,所以地址栏还是转移之前页面的url地址
俗解:
Server.Transfer就好比一个公交站点,一辆596公交车带着一批乘客开到了这个站点,就表示说,要换另一个司机了,
新的司机上车,跟着新司机又有一批新的乘客,就继续驾驶着这个596公交车。页面的Url是没有改变的,Url就像没有改变的公交车线路号(596)。
注意:还有一点需要注意的是该方法不能重定向到ashx的一般处理程序页面,否则会报“子查询出错”
四、Server.Execute()、Server.Transfer()和Response.Redirect()的区别
1.从三者字面意上就是就可以看出三个方法的核心,那么根据关键字简单概括一下:
Server.Execute():执行。根据传入的指定路径,在当前页面执行该路径对应的页面,此内容作为页面的一部分。
Server.Transfe():转移。在方法执行处,结束当前请求输出的内容,转移到一个指定页面,输出新页面的内容。
Response.Redirect():重新寄送。接收客户端请求后执行该方法后,返回给浏览器304状态码,让浏览器在发一次http请求,请求Redirect()方法指定路径的页面。
2.三者的共同点:
都可以指定一个路径参数,然后根据这个路径,实现跳转执行路径对应的页面。
3.地址栏的区别:
Server.Execute()和Server.Transfer()方法执行输出后,浏览器的地址栏不会改变,还是当前请求的地址。
然而Response.Redirect()则会告诉浏览器在一起发送一个http请求,最终地址栏会发送改变,地址栏为Redirect()方法参数路径的地址。
4.Server.Execute()和Server.Transfer()区别:
两则表面上非常相似,执行后地址栏未改变,执行结果也很类似。其实两者有本质上的区别,
Server.Execute()其实是执行一个页面,执行输出在当前页面中,当前页面下部分还要输出的。
但是,Server.Transfer()方法执行,当前页面的请求输出就中断了,转移给另一个页面了,下部分显示的是另一个页面的内容。
5.Server.Transfer()和Response.Redirect()的区别:
两者形式上相同,都是重定向到另一个资源。Response.Redirect()方法执行后会返回给浏览器一个304状态码,
浏览器根据指定的路径在发送一次http请求。如果请求的页面执行Response.Redirect()方法,其实在http报文里可以看到相关线索的。
然后Server.Transfer()是一个内部的重定向,浏览器无法察觉它的操作,Http报文里也无法看到相关线索。
还有一点是,Redirect可以传一个外部的地址,重定向外部的网站,然而Transfer只能限定说,传入的路径资源必须是服务器内部的。Redirect方法相对比较灵活。
五、Server.HtmlEncode()方法
方法签名:public string HtmlEncode(string s)
描述:一个字符串内容如果包含html标签,那么输出到客户端浏览器会解析成一个html标签,
如果我们不想让这个含有html内容的字符串输出成标签,而是输出字符串内容,那么使用Server.HtmlEncode()方法就可以实现。
实例图片:
注意:原模原样的输出了字符串内容,而不是解析成一个Html标签,实际上Encode()方法将那些有html字符替代用特殊的转义字符表示
Server.HtmlEncode()方法实际运用的情况1
假设我们项目中有一个评论功能,这个时候如果用户评论的内容,是有特殊含义的JavaScript脚本,如果顺利执行保存到数据库中,
又恰好读取评论这个页面向服务器反应的 context.Response.ContentType = "text/html";这种形式,
那么用户在读取查看这个评论的时候,脚本就会执行,那么我们很可能存在一个风险,被这个脚本有意图的打乱系统运行。
这个时候,我们可以使用Server.HtmlEncode()方法评论内容进行处理,只是让参数本分纯粹的将内容以字符串形式表示。
Server.HtmlEncode()实战示例情况2:
需求:一个程序员社区,需要大家分享代码交流,提供了相应提交评论和读取评论的功能
界面:
后台服务器接收到该参数的时候,.net平台会报一个错误,如图:
这说明,.net对客户端提交的参数,有一道检验的屏障,但是根据功能设计,这里提交的脚本代码我认为是安全的,那么就要关闭.net的这个屏障。
如何关闭:
一、将配置文件里httpRuntime标签下的requestValidationMode设置为2.0
二、这Page指令集处设置ValidateRequest属性为false(此处只是针对WebForm程序的设定,其他应用请参考https://msdn.microsoft.com/en-us/library/hh882339.aspx)
这样,服务器就可以把有代码含义的内容保存到数据库,在读取评论的时候,我们对这个有代码含义的内容使用Server.HtmlEncode()方法,将他响应给浏览器,浏览器就可以显示这个包含代码含义的字符串,为什么读取的时候使用Server.HtmlEncode()方法因为默认Response.write()肯会将内容转义交给浏览器,浏览器会执行这个代码脚本。
六、Server.HtmlDecode()方法
方法签名:public string HtmlDecode(string s)
描述:将一个含有html内容含义的字符串,解析成一个html标签输出给浏览器
实例图片:
根据Encode()方法推理,Encode()方法内部实际上把字符串里那些有html含义的字符,替代成特殊转义字符进行显示,那么HtmlDecode()方法同样可以把含义转义字符的字符串解析成html标签,如图:
注意:服务器调用context.Response.Write()方法输出一个字符串,如果字符串是html含义的,
那么服务器默认使用的是Server.HtmlDecode()方法输出给浏览器,当然这个还要看Context.Response.ContentType属性的设置
七、Server.UrlEncode()方法和Server.UrlDecode()方法
Server.UrlEncode():传一个url格式的字符串,对url进行编码,通俗的理解为加密
Server.UrlDecode():对Server.UrlEncode()编码加密过后的Url进行解码,还原本来面目
示例图解:
结论:两个方法的特点,我们可以在请求一些重要页面的时候,使用编码解码的方法来提高,请求URL地址的安全性。
以上知识点根据学习,不断领悟后对知识不断的剖解
sql server——子查询
简述:
在查询语句中包含着有另外一条查询语句,被包含的查询语句称为子查询,包含着子查询的查询就称为父查询。
总之,子查询就是在查询语句里嵌套一条或者多条查询语句。
常用子查询分类:
一、独立子查询
特征:子查询语句可以独立运行
二、相关子查询
select * from student where majorId = (select majorId from major where majorId=student.majorId)
特征:子查询中引用了父查询中的字段,依赖于父查询
子查询的使用 |
一、子查询做为查询条件
描述:当一条查询语句需要一个外部的值做为条件的时候,可以使用一个独立的查询先得到这个值,在将值返回进行条件的判断。
注意1:使用子查询做为条件的时候,子查询的查询结果只能返回一列的值,如果返回多列将报错:
注意2:子查询如果返回单列多行的结果,应该在查询语句where 后将"="换成"in",in关键字可以接收多行结果集。使用"="接收多行报错:
注意3:如果子查询做为条件返回的是,多行多列的结果集,可以采用exists接收查询结果
二、将子查询做为一个结果集
select * from (select * from student where majorId=1) tab where stuGender=1
注意:将子查询做为结果集,那么必须要为这个结果集取一个别名
三、将子查询做为查询语句中的某一列
select stuName,(select majorName from major where student.majorId=major.majorId) from student
四、子查询实现分页
方式1:
--pageIndex=2 pageSize=5 select * from (select ROW_NUMBER() over (order by did) as num ,* from DonationDetail ) tab where num>=6 and num <=10
方式2:
--pageIndex=3 pageSize=5 select top 5 * from (select ROW_NUMBER() over (order by did) as num,* from DonationDetail) tab where num not in (select top (3*5-5) ROW_NUMBER() over (order by did) as num2 from DonationDetail)
ROW_NUMBER() over (order by 字段):
根据指定的字段排序,对排序后的结果集的每一行添加一个不间断的行号。
用的时候需注意:如果使用生成行号的查询用作结果集,那么必须为该结果集取一个别名,同时生成的行号字段也要取一个别名
C#接口
概念
相当于是一个规则,完成是为了约束(统一)类的行为,接口光说而不做。
接口是一种规范,也是一种功能的体现。
在生活USB接口就类似我们程序里说的接口,定义了一个规定尺寸规格的插口,
不管你是手机数据线还是移动硬盘等设备,只要你有数据线实现这个接口,就可以使用这个接口带来的功能。
接口命名规范一般以I开头
语法:
[访问修饰符] interface 接口名
{
//接口成员定义
}
通过.NET Reflector反编译工具看看接口的本质
原代码:
反编译:
从反编译看出接口的本质其实也是一个抽象类
接口定义的规则:
1.在编写接口成员时,不要加访问修饰符(因为接口的所有成员都默认就是公共抽象成员)
2.接口中不能有非抽象的实现成员,只能声明。例如属性自能写自动属性、方法不能写方法体。
3.接口不能包含字段
实现接口
1.一个类可以实现多个接口。实现了接口的类,必须实现这个接口中声明的所有成员。
2.实现接口的方法,是类自身的方法,而不是重写的方法,跟接口没有关系
接口多态的体现
接口的运用也主要为用于多态
1.实现接口的类的对象赋值给一个接口类型的变量
2.以接口作为数组类型,存储实现该接口的类的对象
3.以接口当作方法的参数类型,在调用方法时,传入实现该接口类的对象
4.以接口作为方法的返回值类型,return时可以返回实现类的对象
一个实现接口的类不想实现该接口的成员,解决办法
将实现接口的成员,标记abstract,类也要加上abstract
字符串的本质
观察情况一(字符串实例直接赋值给string类型的变量):
分析:
通过调试看出,两个变量存储的内存地址是一样的,这个内存地址其实指向的是字符串常量区
图解:
原理:
创建一个字符串对象,系统会先扫描常量区有没有相同值的字符串,如果有,就直接返回常量区对应的地址 。
观察情况二(通过 new 关键字实例化string类型的对象):
分析:
此时为什么使用new关键字创建字符串实例,怎么内存地址没有像情况一中内存地址都一样。原因是new关键字的本质促使。
new的作用:
1.开辟堆内存空间或者常量区
2.创建对象
3.调用构造函数
4.返回开辟的内存地址
由此分析new,是开辟了新的内存区域,自然返回的内存地址也不会一样。
观察情况三:
思考:
从正常逻辑分析,a和b指向了同一个对象的引用,案例b="bb";后变量a的值也应该发生改变才对。由于是根据字符串特性的不同,这里才使a得值没有发生变化。
图解:
原理:
如果对一个字符串类型的变量的内容进行修改,其实是无法修改变量存储的字符串本身的,而是根据这个新的字符串,去扫描常量区,如果没有就开辟新的空间存储这个字符串,并返回新的内存空间地址。
字符串本质总结:
1. 创建一个字符串,系统会先扫描常量区有没有相同值的字符串,如果有,就直接返回常量区对应的地址 。
2. 如果对一个字符串类型的变量的内容进行修改,其实是无法修改变量存储的字符串本身的,而是根据这个新的字符串,去扫描常量区,如果没有就开辟新的空间存储这个字符串,并返回新的内存空间地址。
3.字符串具有恒定性(值不能改)的特点,一旦在常量区中创建,生命周期是随着应用程序结束而释放。
4.字符串存储在常量区中,作用域是一个公共的区域。
面试实战题目:
不是说字符串是不可变的吗?string s="abc";s="123"不就是变了吗?
答:
在这里,变量s的存储的值确实是由"abc"变成"123"。但是这仅仅改变的是变量s所指向的不同引用。"abc"是一个字符串实例对象,
"abc"的创建首先会扫描堆区域中的常量区,有没有"abc",如果有则直接返回地址,如果没有则开辟一块新的区域,并返回新的地址。
根据字符串的恒定性,一旦在常量区中创建,生命周期是随着应用程序结束而释放。
所以当创建"123"时,没有改变"abc"。
AJAX原生JavaScript写法
GET方式
1 //创建XMLHttpRequest对象,为考虑兼容性问题,老版本的 Internet Explorer (IE5 和 IE6)使用 ActiveX 对象 2 var ajax = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP"); 3 4 //设定请求的类型,服务器URL,以及是否异步处理 5 ajax.open("get","test.ashx?name=jcx&id="+new Date(),true); 6 7 ajax.onreadystatechange=function() 8 { 9 //4:请求已完成,且响应已就绪 10 if(ajax.readyState==4) 11 { 12 //200:成功 13 if(ajax.status==200) 14 { 15 //处理结果 16 alert(ajax.responseText); 17 }else 18 { 19 alert("AJAX服务器返回错误!"); 20 } 21 } 22 23 } 24 25 //将请求发送到服务器 26 ajax.send();
POST方式
1 var ajax=window.XMLHttpRequest?new XMLHttpRequest():new ActiveXObject("Microsoft.XMLHTTP"); 2 3 ajax.open("post", "test.ashx", true); 4 5 ajax.onreadystatechange = function () { 6 if (ajax.readyState==4) 7 { 8 if (ajax.status==200) { 9 alert(ajax.responseText); 10 } 11 } 12 } 13 14 ajax.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); 15 ajax.send("name=jcx&id=23");