vc2008怎么调出vc6 templatee property pages

Jackson序列化和反序列化Json数据
Web技术发展的今天,Json和XML已经成为了web数据的事实标准,然而这种格式化的数据手工解析又非常麻烦,软件工程界永远不缺少工具,每当有需求的时候就会出现各种类库,框架以及工具来解决这些基础的问题,Jackson就是这些工具中的一个,使用这个工具开发者完全可以从手工结束Json数据的重复劳动中解放出来。使用Jackson首先需要下载相应的类库,如下的Maven dependency列出了完整的POM&dependency。
&dependency&
&groupId&com.fasterxml.jackson.core&/groupId&
&artifactId&jackson-core&/artifactId&
&version&${jackson-2-version}&/version&
&/dependency&
&!-- J use this dependency if you want to attach annotations
to classes without connecting them to the code. --&
&dependency& 10
&groupId&com.fasterxml.jackson.core&/groupId& 11
&artifactId&jackson-annotations&/artifactId& 12
&version&${jackson-2-version}&/version& 13
&/dependency& 14
&!-- ObjectMapper, JsonNode and related classes are here --& 16
&dependency& 17
&groupId&com.fasterxml.jackson.core&/groupId& 18
&artifactId&jackson-databind&/artifactId& 19
&version&${jackson-2-version}&/version& 20
&/dependency& 21
&!-- smile (binary JSON). Other artifacts in this group do other formats. --& 23
&dependency& 24
&groupId&com.fasterxml.jackson.dataformat&/groupId& 25
&artifactId&jackson-dataformat-smile&/artifactId& 26
&version&${jackson-2-version}&/version& 27
&/dependency& 28
&!-- JAX-RS provider --& 29
&dependency& 30
&groupId&com.fasterxml.jackson.jaxrs&/groupId& 31
&artifactId&jackson-jaxrs-json-provider&/artifactId& 32
&version&${jackson-2-version}&/version& 33
&/dependency& 34
&!-- Support for JAX-B annotations as additional configuration --& 35
&dependency& 36
&groupId&com.fasterxml.jackson.module&/groupId& 37
&artifactId&jackson-module-jaxb-annotations&/artifactId& 38
&version&${jackson-2-version}&/version& 39
&/dependency&
比如我们需要解析的Json数据如下:
"id": 123,
"name": "Pankaj",
"permanent": true,
"address": {
"street": "Albany Dr",
"city": "San Jose",
"zipcode": 95129
"phoneNumbers": [
"role": "Manager",
"cities": [
"Los Angeles",
"New York"
"properties": {
"age": "29 years",
"salary": "1000 USD"
对应的Model Class 如下:
import java.util.A import java.util.L import java.util.M
public class Employee {
private long[] phoneN
private List&String&
private Map&String, String&
public int getId() {
public void setId(int id) {
public String getName() {
public void setName(String name) {
this.name =
public boolean isPermanent() {
public void setPermanent(boolean permanent) {
this.permanent =
public Address getAddress() {
public void setAddress(Address address) {
this.address =
public long[] getPhoneNumbers() {
return phoneN
public void setPhoneNumbers(long[] phoneNumbers) {
this.phoneNumbers = phoneN
public String getRole() {
public void setRole(String role) {
this.role =
public String toString(){
StringBuilder sb = new StringBuilder();
sb.append("***** Employee Details *****/n");
sb.append("ID="+getId()+"/n");
sb.append("Name="+getName()+"/n");
sb.append("Permanent="+isPermanent()+"/n");
sb.append("Role="+getRole()+"/n");
sb.append("Phone Numbers="+Arrays.toString(getPhoneNumbers())+"/n");
sb.append("Address="+getAddress()+"/n");
sb.append("Cities="+Arrays.toString(getCities().toArray())+"/n");
sb.append("Properties="+getProperties()+"/n");
sb.append("*****************************");
return sb.toString();
public List&String& getCities() {
public void setCities(List&String& cities) {
this.cities =
public Map&String, String& getProperties() {
public void setProperties(Map&String, String& properties) {
this.properties =
当我们需要操作Json数据的时候,如下代码示范了如何将Json数据反序列化为对象以及如何将对象序列化为Json数据。
import java.io.F import java.io.IOE import java.io.StringW import java.nio.file.F import java.nio.file.P import java.util.ArrayL import java.util.HashM import java.util.I import java.util.L import java.util.M
import com.fasterxml.jackson.core.type.TypeR import com.fasterxml.jackson.databind.JsonN import com.fasterxml.jackson.databind.ObjectM import com.fasterxml.jackson.databind.SerializationF import com.fasterxml.jackson.databind.node.ObjectN
public class JacksonObjectMapperExample {
public static void main(String[] args) throws IOException {
//read json file data to String
byte[] jsonData = Files.readAllBytes(Paths.get("C://employee.txt"));
//create ObjectMapper instance
ObjectMapper objectMapper = new ObjectMapper();
//convert json string to object
Employee emp = objectMapper.readValue(jsonData, Employee.class);
System.out.println("Employee Object/n"+emp);
//convert Object to json string
Employee emp1 = createEmployee();
//configure Object mapper for pretty print
objectMapper.configure(SerializationFeature.INDENT_OUTPUT, true);
//writing to console, can write to any output stream such as file
StringWriter stringEmp = new StringWriter();
objectMapper.writeValue(stringEmp, emp1);
System.out.println("Employee JSON is/n"+stringEmp);
public static Employee createEmployee() {
Employee emp = new Employee();
emp.setId(100);
emp.setName("David");
emp.setPermanent(false);
emp.setPhoneNumbers(new long[] { 7654 });
emp.setRole("Manager");
Address add = new Address();
add.setCity("Bangalore");
add.setStreet("BTM 1st Stage");
add.setZipcode(560100);
emp.setAddress(add);
List&String& cities = new ArrayList&String&();
cities.add("Los Angeles");
cities.add("New York");
emp.setCities(cities);
Map&String, String& props = new HashMap&String, String&();
props.put("salary", "1000 Rs");
props.put("age", "28 years");
emp.setProperties(props);
结果如下:
Employee Object ***** Employee Details ***** ID=123 Name=Pankaj Permanent=true Role=Manager Phone Numbers=[7654] Address=Albany Dr, San Jose, 95129 Cities=[Los Angeles, New York] Properties={age=29 years, salary=1000 USD} ***************************** Employee JSON is {
"id" : 100,
"name" : "David",
"permanent" : false,
"address" : {
"street" : "BTM 1st Stage",
"city" : "Bangalore",
"zipcode" : 560100
"phoneNumbers" : [ 7654 ],
"role" : "Manager",
"cities" : [ "Los Angeles", "New York" ],
"properties" : {
"salary" : "1000 Rs",
"age" : "28 years"
本文以一个完整的示例总结了Java对象序列化为Json对象和反序列化的过程,希望可以抛砖引玉对大家有所帮助。
最近工作比较忙,加了会班就不想再写东西了,就想洗洗睡。 但是这个视频真的不能断,不能像过去一样写了几集就停了。
现在公司在做一个MVC框架的项目,话说已经一年没有写MVC了,重新上手的感觉还可以。UI那块还是Bootstrap,话说真应该感激以前公司带的Bootstrap入门,颇有收获。
以前写过用datatables来实现列表数据展示功能的小结文章,现阶段正在准备总结一下平时做管理系统界面时候肯定会用到的比如&新增&,&编辑&,&删除&代码,希望能给新同学一点思路,当然也是关于MVC的。
第29集 在IIS中托管WCF服务 Hosting wcf service in iis
今天第29集,介绍一下如何把wcf托管到IIS中,毕竟,做.net的web项目和IIS还是挺亲切的。
前面实现过一个HelloService项目,本身是个类库。项目结构如下:
内容也不需要变。
1. 给当前解决方案添加一个新网站。右键解决方案,添加-新建网站
2. 选择 WCF服务,取名HelloServiceForIIS。
点击确定。
3. 打开App_Code文件夹,可以把IService.cs 和 Service.cs删了,因为我们的内容已经在上面的HelloService类库中。
4. 更改一下Service.svc文件名字,改成HelloService。然后编辑里面内容,删了CodeBehind=”~/App_Code/Service.cs”,因为我们code 是在 上面的类库中。然后把Service=”Service”改成Service=”HelloService.HelloService”,前面HelloService是命名空间,后面的是服务名称。最后给这个网站添加一下对上面HelloService类库的项目引用。
项目就变成了这样:
HelloService.svc里面就变成了这样:
&%@ ServiceHost Language="C#" Debug="true" Service="HelloService.HelloService" %&
5. 编辑网站下面的web.config文件,把HelloService类库里面的app.config内容全部贴过来,粘贴到这个web.config里面。
6. 编译生成一下网站。然后把他架到IIS上。这里用虚拟目录的方式。
运行输入inetmgr 回车打开IIS。
右键Default Web Site 选择 Add Application
输入一些基本信息:
应用程序池记得选和自己项目framework 匹配的,这里用的默认的4.0。
7. 点击网站,选择内容视图,然后右键浏览这个HelloService.svc来查看服务是否可用。
8. 客户端调用的时候地址就变成了:http://localhost/HelloService/HelloService.svc。所以记得重新添加一下这个服务引用。
这集完了,介绍了一下如何把WCF服务托管到IIS上。
ThankYou!
关于KMP算法的原理网上有很详细的解释,我总结一下理解它的要点:
以这张图片为例子
这里我们匹配到j=5时失效了,接下来就直接比较T[2](next[5]=2)和S[5]
那为什么可以跳过朴素算法里的几次比较,而直接用T[next[j]]比较就可以呢?
我们匹配过S0=T0T1T2T3T4,
next[5]=2,2是公共序列的最大长度了,也就是说:
T0T1=T3T4,但是T0T1T2&T2T3T4,T0T1T2T3&T1T2T3T4,
那么就有S3S4=T3T4=T0T1,而S2S3S4=T2T3T4&T0T1T2,S1S2S3S4=T1T2T3T4&T0T1T2T3
所以可以直接比较T2和S5
Q:next数组为什么这样计算?
如果我们算完了 i 及之前的next,现在要算next[i+1]了,我们让k=next[i],可以看到如果 k 和 i 位置的字符相同(下标0开始,所以是T[i-1]==T[k-1],当然在循环中还是T[i]和T[k]比较,i和k比较了再增加1,如果不同的话他们不相等,还不能增加1,见下文分析),那next[i+1]就等于k+1,,代码就是:
if(T[k]==T[i])
next[i]=k;
如果不同呢?那就有next[i+1]&next[i],不可能有更长的公共序列,而在匹配的部分里(图中灰色)有更小的一段(图中蓝色部分),是next[next[i]]前面的子串,根据next数组的含义,左右的蓝色的和粉色的子串分别相同,因为左右灰色部分是相同的,那左边的蓝色就和右边的粉色相同,如果这时Ti=Tnext[k],那它就是next[i]的值了,否则继续找更小的一段(这一部分和上面的判断是差不多的,所以只要更新k=next[k],然后继续循环就可以了),直到k=-1,那么next[i]就等于-1了,整个的代码就是:
void get_next(const string &T,int *next){
int i=0,k=-1;
next[i]=k;
while(T[i]!='/0'){
if(k==-1||T[k]==T[i])
next[i]=k;
k=next[k];
但是其实还可以再改进,例如
那么当i=3失配时,T的移动如下,
这样没有利用前面那么多a一样的特点,导致匹配次数比较多,所以我们这样改进:
如果T[i]=T[i-1],next[i]=next[i-1]
在这里,next[0]=-1,next[1]=-1,next[2]=-1,next[3]=-1,next[4]=3,代码就变成了:
void get_next(const string &T,int *next) {
int i=0,k=-1;
next[i]=k;
while(T[i]!='/0')
if(k==-1||T[k]==T[i])
if(T[i] != T[k])
next[i] = next[k];
k=next[k];
完整程序代码:
#include&iostream& #include&cstring& void get_next(const string &T,int *next) {
int i=0,k=-1;
next[i]=k;
while(T[i]!='/0')
if(k==-1||T[k]==T[i])
if(T[i] != T[k])
next[i] = next[k];
k=next[k];
} } /* 返回模式串T在主串P的第pos个字符起第一次出现的位置,若不存在,则返回-1 下标从0开始,0&=pos&=P.size()(P的字符总个数) */ int KMP_index(const string &P,const string &T,int pos) {
int *next=new int[T.size()+2];//动态分配next数组
get_next(T,next);
int i=0,j=
while(i&T.size()&&j&P.size())
if(i==-1||P[j]==T[i])
i=next[i];
if(i&=T.size())
return j-i;
return -1; } int main() {
char *T,*P;
T=new char[100];
P=new char[100];
cin&&P&&T;
cout&&KMP_index(P,T,0)&&
return 0; }
在启动openfire时报下列错误
[root@mc bin]# ./openfire.sh ./openfire.sh: /opt/openfire/jre/bin/java: /lib/ld-linux.so.2: bad ELF interpreter: No such file or directory
解决方法:
[root@mc bin]#yum -y install libldb.i686
本文出自 “云人生” 博客,请务必保留此出处http://ovcer./9302
我看了下这里网站里的所有东西都是这样报错,就是图片和TXT也打不开,然后查看了一下程序发现里面有三个文件.htaccess、httpd.ini、nginx.conf,我想应该是这几个家伙在作怪,首先想到的就是.htaccess这个分布文件,将其删除,果断打开网站了,那么找到原因了,把删除了的找回来,去apache里开启.htaccess就好了,下面是开启方法:
在apache配置文件httpd.conf中找到
Options FollowSymLinks&AllowOverride None&
有的版本是这样写的
Options FollowSymLinks ExecCGI IndexesAllowOverride None
总之不管怎么写,你只需要把下面的
AllowOverride&None改为AllowOverride All
然后在找到
LoadModule rewrite_module modules/mod_rewrite.so
把这个前面的&#&号去掉,就是去掉注释,然后重启apache.搞定!
下面记载点.htaccess的写法
htaccess 写法  Apache中的.htaccess(或者&分布式配置&了针对目录改变配置的方法,即,在特定的文档目录中放置包含或多个指令的,以作用于此目录及其子目录。作为,所能的命令受到限制。***Apache的AllowOverride指令来设置。
子目录中的指令会笼盖更高级目录或者主器配置中的指令。
.htaccess必需以ASCII模式上传,最好将其权限设置为644。
错误文档的定位
常用的客户端哀求错误返回代码:401 Authorization Required403 Forbidden404 Not Found405 Method Not Allowed408 Request Timed Out411 Content Length Required412 Precondition Failed413 Request Entity Too Long414 Request URI Too Long415 Unsupported Media Type
  常见的器错误返回代码:  500 Internal Server Error
利用.htaccess指定事先制作好的错误提醒页面。一般下,人们专门设立目录,例如errors放置页面。然后再.htaccess中,加入如下的指令:
ErrorDocument 404 /errors/notfound.htmlErrorDocument 500 /errors/internalerror.html
一条指令一行。上述第一条指令的意思是对于404,也找到所的文档的得显示页面为/errors目录下的notfound.html页面。不难看出语法格局为:
ErrorDocument 错误代码 /目录名/名.扩展名
所提示的很少的话,不必专门制作页面,直接在指令中HTML号了,例如下面例子:
ErrorDocument 401 &你权限访问该页面,请抛却!&
  文档访问的密码保护要利用.htaccess对某个目录下的文档设定访问和对应的密码,首先要做的是生成.htpasswd的文本文档,例如:
zheng:y4E7Ep8e7EYV
这里密码经由加密,找些工具将密码加密成.htaccess的编码。该文档最好不要放在www目录下,建议放在www根目录文档之外,这样更为安全些。
有了授权文档,在.htaccess中加入如下指令了:
AuthUserFile .htpasswd的器目录AuthGroupFile /dev/null (授权访问的目录)AuthName EnterPasswordAuthType Basic (授权类型)
是的主人,应该处处为着想。 && 雷锋require user wsabstract (允许访问的,但愿表中都允许, require valid-user)
注,括号部门为学习添加的注释
拒绝来自某个IP的访问
我不想某个政府部门访问到站点的,那.htaccess中加入该部门的IP而将它们拒绝在外。
order allow,denydeny from 210.10.56.32deny from 219.5.45.allow from all
第二行拒绝某个IP,第三行拒绝某个IP段,也219.5.45.0~219.2.45.255
想要拒绝人?用deny from all好了。不止用IP,也用域名来设定。
  保护.htaccess文档在.htaccess来设置目录的密码保护时,它包含了密码的路径。从安全考虑,有必要把.htaccess也保护起来,不让别人看到其中的。虽然用其他做到这点,好比文档的权限。不外,.htaccess本身也能做到,只需加入如下的指令:
order allow,denydeny from all
可能对重新规划,将文档了迁移,或者更改了目录。这,来自搜索引擎或者其他链接过来的访问就可能犯错。这种下,如下指令来完成旧的URL自动转向到新的:
Redirect /旧目录/旧文档名 新文档的
或者整个目录的转向:
Redirect 旧目录 新目录
改变缺省的首页
一般下缺省的首页名有default、index等。不外,有些目录中没出缺省,而是某个特定的名,好比在pmwiki中是 pmwiki.php。这种下,要记住名来访问很麻烦。在.htaccess中等闲的设置新的缺省名:
DirectoryIndex 新的缺省名
也列出多个,顺序表明它们之间的优先级别,例如:
DirectoryIndex filename.html index.cgi index.pl default.htm
不喜欢别人在的网页上连接的、文档的话,也htaccess的指令来做到。
所的指令如下:
RewriteEngine onRewriteCond %{ HTTP_REFERER } !^$RewriteCond %{ HTTP_REFERER } !^http://(www.)?/.*$ [NC]RewriteRule .(gif&jpg)$ & [F]
觉得让别人的页面开个天窗不好看,那用一张来代替:
RewriteEngine onRewriteCond %{ HTTP_REFERER } !^$RewriteCond %{ HTTP_REFERER } !^http://(www.)?/.*$ [NC]RewriteRule .(gif&jpg)$ /替代名 [R,L]
其它补充:在给出如何配置Apache支持.htaccess文件之前,首先申明一下:使用.htaccess文件,会降低httpd服务器的一点性能。
配置方法找到Apache的httpd.conf配置文件,编辑器打开。
//找到&Directory /&Options FollowSymLinksAllowOverride None&/Directory&
&Directory /&Options FollowSymLinksAllowOverride All&/Directory&
//就可以了
/*如果需要使用.htaccess以外的其他文件名,可以用AccessFileName指令来改变。例如,需要使用.config ,则可以在服务器配置文件中按以下方法配置:*/AccessFileName .config  通常,.htaccess文件使用的配置语法和主配置文件一样。AllowOverride指令按类别决定了.htaccess文件中哪些指令才是有效的。
(不)使用.htaccess文件的场合一般情况下,不应该使用.htaccess文件,除非你对主配置文件没有访问权限。有一种很常见的误解,认为用户认证只能通过.htaccess文件实现,其实并不是这样,把用户认证写在主配置文件中是完全可行的,而且是一种很好的方法。.htaccess文件应该被用在内容提供者需要针对特定目录改变服务器的配置而又没有root权限的情况下。如果服务器管理员不愿意频繁修改配置,则可以允许用户通过.htaccess文件自己修改配置,尤其是ISP在同一个机器上运行了多个用户站点,而又希望用户可以自己改变配置的情况下。虽然如此,一般都应该尽可能地避免使用.htaccess文件。任何希望放在.htaccess文件中的配置,都可以放在主配置文件的段中,而且更高效。避免使用.htaccess文件有两个主要原因。首先是性能。如果AllowOverride启用了.htaccess文件,则Apache需要在每个目录中查找.htaccess文件,因此,无论是否真正用到,启用.htaccess都会导致性能的下降。另外,对每一个请求,都需要读取一次.htaccess文件。还有,Apache必须在所有上级的目录中查找.htaccess文件,以使所有有效的指令都起作用,所以,如果请求/ctusky/ctu/sky中的页面,Apache必须查找以下文件:
/.htaccess/ctusky/.htaccess/ctusky/ctu/.htaccess/ctusky/ctu/sky/.htaccess  一共就要访问4个额外的文件,就算这些文件都不存在,这也是本文开始说会影响服务器的一点性能的原因。其次是安全。这样会允许用户自己修改服务器的配置,这可能会导致某些意想不到的修改,所以请认真考虑是否应当给予用户这样的特权。
&(解决的方法)本次直接删除.htaccess
在之前的文章中,我已经介绍过一个社交网站模拟登录的类库:imitate-login&,这是一个通过c#的HttpWebRequest来模拟网站登录的库,之前实现了微博网页版和微博Wap版;现在,模拟百度登录的部分也已经完成。由于个人时间的限制,加上目前有多个项目在同时进行,因此更新频率会根据项目关注度来决定(Star & fork)。
这个类库的使用方法非常简单,仅对外提供一个方法:
LoginResult Login(1: string userName, 2: string password, 3: LoginSite loginSite);
这个方法位于ImitateLogin的LoginHelper类中,使用之前需要先对其进行实例化。通过传入 用户名、密码以及登录的网站,返回一个包含登录结果状态、描述信息和Cookies字典的类。它通过 Thrift 来实现多语言的支持。
下面将通过介绍模拟百度登录的实现来介绍如何进行扩充与二次开发:
首先,创建百度登录类 BaiduLogin.cs 继承 ILogin 接口;实现其生成的 DoLogin 方法。
#region ILogin implementation public LoginResult DoLogin(string UserName, string Password) {
throw new NotImplementedException(); }
public CookieContainer cookies { set; get;} #endregion
然后我们通过监听百度登录过程中的网络请求,梳理出修改过Cookies和最终提交登录所需的参数的请求。
Step1: 访问以下链接生成初始Cookies:
HttpHelper.GetHttpContent("/passApi/html/_blank.html", cookies: cookies, cookiesDomain: "");
Step2: 获取最终登录提交所需的token:
//1. Get the token. string token_url = string.Format("/v2/api/?getapi&tpl=mn&apiver=v3&tt={0}&class=login&gid={1}&logintype=dialogLogin&callback=bd__cbs__{2}", TimeHelper.ConvertDateTimeInt(DateTime.Now), Guid.NewGuid().ToString().ToUpper(), build_callback()); string prepareContent = HttpHelper.GetHttpContent(token_url, null, cookies, referer: "/", encode: Encoding.GetEncoding("GB2312"), cookiesDomain: ""); //string prepareJson = prepareContent.Split('(')[1].Split(')')[0]; dynamic prepareJson = JsonConvert.DeserializeObject(prepareContent.Split('(')[1].Split(')')[0]); string token = prepareJson.data.
其中 build_callback 为随机生成6位字母或数字的组合的方法。
Step3: 获取用于加密密码的publickey:
//2. Get public key string pubkey_url = "/v2/getpublickey?token={0}&tpl=mn&apiver=v3&tt={1}&gid={2}&callback=bd__cbs__{3}"; string pubkeyContent = HttpHelper.GetHttpContent(string.Format(pubkey_url, token, TimeHelper.ConvertDateTimeInt(DateTime.Now), Guid.NewGuid().ToString().ToUpper(), build_callback()), null, cookies, referer: "/", encode: Encoding.GetEncoding("GB2312"), cookiesDomain: "");
dynamic pubkeyJson = JsonConvert.DeserializeObject(pubkeyContent.Split('(')[1].Split(')')[0]); rsa_pub_baidu = pubkeyJson. string KEY = pubkeyJson.
stopwatch 是一个记录从最初执行到最终提交之前的耗时的一个计时器,get_pwa_rsa 为加密密码的方法。
Step4: 模拟执行最终的登录:
//3. Build post data string login_data = "staticpage=https%3A%2F%%2Fcache%2Fuser%2Fhtml%2Fv3Jump.html&charset=UTF-8&token={0}&tpl=mn&subpro=&apiver=v3&tt={1}&codestring=&safeflg=0&u=https%3A%2F%%2F&isPhone=&detect=1&gid={2}&quick_user=0&logintype=dialogLogin&logLoginType=pc_loginDialog&idc=&loginmerge=true&splogin=rate&username={3}&password={4}&verifycode=&mem_pass=on&rsakey={5}&crypttype=12&ppui_logintime={6}&countrycode=&callback=parent.bd__pcbs__{7}"; login_data = string.Format(login_data, token, TimeHelper.ConvertDateTimeInt(DateTime.Now), Guid.NewGuid().ToString().ToUpper(), HttpUtility.UrlEncode(UserName), HttpUtility.UrlEncode(get_pwa_rsa(Password)), HttpUtility.UrlEncode(KEY), stopwatch.ElapsedMilliseconds, build_callback());
//4. Post the login data string login_url = "/v2/api/?login"; HttpHelper.GetHttpContent(login_url, login_data, cookies, referer: "/", cookiesDomain: "");
Step5:验证最终的登录结果:
string home_url = ""; string result = HttpHelper.GetHttpContent(home_url, cookies: cookies, cookiesDomain: ""); //5. Verifty the login result if (string.IsNullOrWhiteSpace(result) || result.Contains("账号存在异常") || !result.Contains("m.user=/"")) {
return new LoginResult() { Result = ResultType.AccounntLimit, Msg = "Fail, Msg: Login fail! Maybe you account is disable or captcha is needed." }; }
Step6:创建返回结果类:
LoginResult loginResult = new LoginResult() { Result = ResultType.Success, Msg = "Success", Cookies = HttpHelper.GetAllCookies(cookies) };
至此,模拟登录部分的代码就完成了,为了能够被其它程序调用,你还需要在 LoginSite 的枚举中新增一条来标识这个登录方法,此处增加了一个 Baidu = 5,并设置 [Description(&Baidu&)]。
然后在 LoginHelper.cs 的 Login 方法中的 switch (loginSite) 里增加一个 case:
case LoginSite.Baidu:
LoginClass = new BaiduLogin ();
本文来自&The NewIdea,作者 Carey Tzou 。好了,大功告成!Todo List中还有淘宝、QQ、Facebook、Twitter、Google要做呢,我还想加入GitHub、Wechat&现在,你可以帮我了吗?
首发地址:/login-baidu-throught-imitate-login.html未经授权,拒绝任何全文及摘要转载!
前篇说过,ES可以自动为文档设定索引。但是问题也来了&&如果默认设置的索引不是我们想要的,该怎么办呢?
要知道ES这种搜索引擎都是以Index为实际的分区,Index里面包含了不同的类型,不同的类型是逻辑上的分区;每种类型可能包含有相同的字段,如果字段的类型相同还好,如果不同….那就会导致字段的冲突了。
本篇就讲述如何使用REST API以及Logstash设置默认的索引。
更多内容参考:Elasticsearch知识汇总
使用Rest API设置默认的索引
首先先看一下不设置默认索引时,我们想要索引一个IP地址的字段,会发生什么?输入下面的命令:
$ curl -XPUT localhost:9200/test/test/1 -d '{"ip":"192.168.0.1"}'
查看映射可以发现,我们想要存储成IP类型,但是默认给存储成了字符串类型:
$ curl -XGET localhost:9200/test/_mapping?pretty
"test" : {
"mappings" : {
"test" : {
"properties" : {
"type" : "string"
这并不是我们想要的。
由于映射一旦设定好了,就不能修改了。因此再次实验的时候,需要删除索引test
$ curl -XDELETE localhost:9200/test
{"acknowledged":true}
然后设置test的默认映射:
$ curl -XPUT localhost:9200/test?pretty -d '{"mappings":{"_default_":{"properties":{"ip":{"type":"ip"}}}}}'
上面的命令中,设置test索引中,默认字段ip的属性为ip。这样我们查询test的映射时,发现ip字段已经被设置为ip:
$ curl -XGET localhost:9200/test/_mapping?pretty
"test" : {
"mappings" : {
"_default_" : {
"properties" : {
"type" : "ip"
然后插入一段数据,为了观察到插入数据后的映射的变化,可以多插入一个字段:
$ curl -XPUT localhost:9200/test/test/2 -d '{"name":"xingoo","ip":"192.168.0.1"}'
然后查询映射,可以读取到默认映射信息以及当前的映射信息:
$ curl -XGET localhost:9200/test/_mapping?pretty
"test" : {
"mappings" : {
"test" : {
"properties" : {
"type" : "ip"
"name" : {
"type" : "string"
"_default_" : {
"properties" : {
"type" : "ip"
恭喜~IP字段的类型已经变成了ip,类似的,我们可以设置date,geo,object等类型。
在Logstash中配置默认的索引
Logstash中默认索引的设置是基于模板的,原理上跟上面差不多。
首先我们需要指定一个默认的映射文件,文件的内容大致如下:
"template" : "logstash-*",
"mappings" : {
"_default_" : {
"properties" : {
"type":"ip"
其中template定义了匹配的索引模式,如果针对于特定的某个索引,则直接写成索引的名字即可。下面定义了映射的相关信息,与API的内容相同。
有了上面的配置文件,就可以在Logstash中配置output插件了:
elasticsearch {
host =& "localhost" #ES的服务器地址
protocol =& "http" #使用的协议,默认可能会使用Node,具体还要看机器的环境
index =& "logstash-%{+YYYY.MM.dd}" #匹配的索引模式
document_type =& "test" #索引的类型,旧的配置会使用index_type,但是这个字段在新版本中已经被舍弃了,推荐使用document_type   
manage_template =& true #注意默认为true,一定不能设置为false
template_overwrite =& true #如果设置为true,模板名字一样的时候,新的模板会覆盖旧的模板
template_name =& "myLogstash" #注意这个名字是用来查找映射配置的,尽量设置成全局唯一的   
template =& "D:/test/logstash.conf" #映射配置文件的位置
其中后四个是使用默认映射需要注意的地方,详细的可以多了解Logstash的源码。
【1】_default_映射:https://www.elastic.co/guide/en/elasticsearch/reference/current/default-mapping.html
【2】Elasticsearch output插件:https://www.elastic.co/guide/en/logstash/current/plugins-outputs-elasticsearch.html
【3】ELK电子书:http://kibana.logstash.es/content/logstash/plugins/output/elasticsearch.html
有些人問前端/後端、前台/後台要用什麼英文?
查了一下網友給出了以下幾種回答:
1. client side、server side
2. front side、back side
3.&front end、back end
4.&foreground、background
5.&user Interface、manage interface
我對於這些英文的理解:
1. client side 的中文翻譯為客戶端,server side 的中文翻譯為服務器端,此處不適用;
2.&front side 的中文翻譯為正面,back side 的中文翻譯為反面,有相近之意,但仍然不適用;
3.&front end 的中文翻譯為前端,back end 的中文翻譯為後端,雖然 front end 的英文解釋是向前或突出的一面,back end 的英文解釋是一个物体的侧面相反的,但是在維基百科的&前端和後端&中將它們作為了英文翻譯,原句是&前端(英語:front-end)和後端(英語:back-end)是描述進程開始和結束的通用詞彙。前端作用於採集輸入信息,後端進行處理。計算機程序的界面樣式,視覺呈現屬於前端。&;
4.&foreground 的中文翻譯是前景,background 的中文翻譯是(画等的)背景,但是&foreground 和 background&的英文解釋都是(计算机科学)在图形化的用户界面中,图标和窗口出现的屏幕区域,適用於前台的前景和背景,此處不適用;
5.&user interface 的中文翻譯是用戶界面,就是我們一直說的 UI 的全稱,manage interface 的中文翻譯是管理界面,user interface 的英文解釋是(计算机科学)为用户(通常在计算机监视器上)显示的程序,该程序允许用户与系统进行交互,包括了前台和後台,此處不適用。
前端和後端的英文:front end、back end;
那前台和後台的英文呢?前台是普通用戶訪問的頁面,後台是管理員管理網站的頁面(此處為我的理解),沒有較短英文翻譯,所以我考慮了之後決定使用 forestage&和 backstage 這兩個單詞,forestage&的中文翻譯是前級、前台、舞台幕布以前的部分,backstage(adv.) 的中文翻譯是后級、後台、在幕後,相對其它英文這個解釋個人感覺還是比較好的,幕後管理,幕前展示。
但是是否要使用這兩個單詞作為前台和後台的英文我還是有點猶豫的,我認為可以在單獨寫前台或者後台的時候使用,而在說道網站前台和網站後台等地方的時候使用&Site Reception 和&Website background。
具體使用看個人喜好。
翻譯來自百度翻譯和谷歌翻譯。
咚咚是什么?咚咚之于京东相当于旺旺之于淘宝,它们都是服务于买家和卖家的沟通。 自从京东开始为第三方卖家提供入驻平台服务后,咚咚也就随之诞生了。 我们首先看看它诞生之初是什么样的。
1.0 诞生(2010 &#)
为了业务的快速上线,1.0 版本的技术架构实现是非常直接且简单粗暴的。 如何简单粗暴法?请看架构图,如下。
1.0 的功能十分简单,实现了一个 IM 的基本功能,接入、互通消息和状态。 另外还有客服功能,就是顾客接入咨询时的客服分配,按轮询方式把顾客分配给在线的客服接待。 用开源 Mina 框架实现了 TCP 的长连接接入,用 Tomcat Comet 机制实现了 HTTP 的长轮询服务。 而消息投递的实现是一端发送的消息临时存放在 Redis 中,另一端拉取的生产消费模型。
这个模型的做法导致需要以一种高频率的方式来轮询 Redis 遍历属于自己连接的关联会话消息。 这个模型很简单,简单包括多个层面的意思:理解起来简单;开发起来简单;部署起来也简单。 只需要一个 Tomcat 应用依赖一个共享的 Redis,简单的实现核心业务功能,并支持业务快速上线。
但这个简单的模型也有些严重的缺陷,主要是效率和扩展问题。 轮询的频率间隔大小基本决定了消息的延时,轮询越快延时越低,但轮询越快消耗也越高。 这个模型实际上是一个高功耗低效能的模型,因为不活跃的连接在那做高频率的无意义轮询。 高频有多高呢,基本在 100 ms 以内,你不能让轮询太慢,比如超过 2 秒轮一次,人就会在聊天过程中感受到明显的会话延迟。 随着在线人数增加,轮询的耗时也线性增长,因此这个模型导致了扩展能力和承载能力都不好,一定会随着在线人数的增长碰到性能瓶颈。
1.0 的时代背景正是京东技术平台从 .NET 向 Java 转型的年代,我也正是在这期间加入京东并参与了京东主站技术转型架构升级的过程。 之后开始接手了京东咚咚,并持续完善这个产品,进行了三次技术架构演进。
2.0 成长(2012)
我们刚接手时 1.0 已在线上运行并支持京东 POP(开放平台)业务,之后京东打算组建自营在线客服团队并落地在成都。 不管是自营还是 POP 客服咨询业务当时都起步不久,1.0 架构中的性能和效率缺陷问题还没有达到引爆的业务量级。 而自营客服当时还处于起步阶段,客服人数不足,服务能力不够,顾客咨询量远远超过客服的服务能力。 超出服务能力的顾客咨询,当时我们的系统统一返回提示客服繁忙,请稍后咨询。 这种状况导致高峰期大量顾客无论怎么刷新请求,都很可能无法接入客服,体验很差。 所以 2.0 重点放在了业务功能体验的提升上,如下图所示。
针对无法及时提供服务的顾客,可以排队或者留言。 针对纯文字沟通,提供了文件和图片等更丰富的表达方式。 另外支持了客服转接和快捷回复等方式来提升客服的接待效率。 总之,整个 2.0 就是围绕提升客服效率和用户体验。 而我们担心的效率问题在 2.0 高速发展业务的时期还没有出现,但业务量正在逐渐积累,我们知道它快要爆了。 到 2012 年末,度过双十一后开始了 3.0 的一次重大架构升级。
3.0 爆发(2013 &#)
经历了 2.0 时代一整年的业务高速发展,实际上代码规模膨胀的很快。 与代码一块膨胀的还有团队,从最初的 4 个人到近 30 人。 团队大了后,一个系统多人开发,开发人员层次不一,规范难统一,系统模块耦合重,改动沟通和依赖多,上线风险难以控制。 一个单独 tomcat 应用多实例部署模型终于走到头了,这个版本架构升级的主题就是服务化。
服务化的第一个问题如何把一个大的应用系统切分成子服务系统。 当时的背景是京东的部署还在半自动化年代,自动部署系统刚起步,子服务系统若按业务划分太细太多,部署工作量很大且难管理。 所以当时我们不是按业务功能分区服务的,而是按业务重要性级别划分了 0、1、2 三个级别不同的子业务服务系统。 另外就是独立了一组接入服务,针对不同渠道和通信方式的接入端,见下图。
更细化的应用服务和架构分层方式可见下图。
这次大的架构升级,主要考虑了三个方面:稳定性、效率和容量。 做了下面这些事情:
业务分级、核心、非核心业务隔离
多机房部署,流量分流、容灾冗余、峰值应对冗余
读库多源,失败自动转移
写库主备,短暂有损服务容忍下的快速切换
外部接口,失败转移或快速断路
Redis 主备,失败转移
大表迁移,MongoDB 取代 MySQL 存储消息记录
改进消息投递模型
前 6 条基本属于考虑系统稳定性、可用性方面的改进升级。 这一块属于陆续迭代完成的,承载很多失败转移的配置和控制功能在上面图中是由管控中心提供的。 第 7 条主要是随着业务量的上升,单日消息量越来越大后,使用了 MongoDB 来单独存储量最大的聊天记录。 第 8 条是针对 1.0 版本消息轮询效率低的改进,改进后的投递方式如下图所示:
不再是轮询了,而是让终端每次建立连接后注册接入点位置,消息投递前定位连接所在接入点位置再推送过去。 这样投递效率就是恒定的了,而且很容易扩展,在线人数越多则连接数越多,只需要扩展接入点即可。 其实,这个模型依然还有些小问题,主要出在离线消息的处理上,可以先思考下,我们最后再讲。
3.0 经过了两年的迭代式升级,单纯从业务量上来说还可以继续支撑很长时间的增长。 但实际上到 2014 年底我们面对的不再是业务量的问题,而是业务模式的变化。 这直接导致了一个全新时代的到来。
4.0 涅槃(2015 至今 )
2014 年京东的组织架构发生了很大变化,从一个公司变成了一个集团,下设多个子公司。 原来的商城成为了其中一个子公司,新成立的子公司包括京东金融、京东智能、京东到家、拍拍、海外事业部等。 各自业务范围不同,业务模式也不同,但不管什么业务总是需要客服服务。 如何复用原来为商城量身订做的咚咚客服系统并支持其他子公司业务快速接入成为我们新的课题。
最早要求接入的是拍拍网,它是从腾讯收购的,所以是完全不同的账户和订单交易体系。 由于时间紧迫,我们把为商城订做的部分剥离,基于 3.0 架构对接拍拍又单独订做了一套,并独立部署,像下面这样。
虽然在业务要求的时间点前完成了上线,但这样做也带来了明显的问题:
复制工程,定制业务开发,多套源码维护成本高
独立部署,至少双机房主备外加一个灰度集群,资源浪费大
以前我们都是面向业务去架构系统,如今新的业务变化形势下我们开始考虑面向平台去架构,在统一平台上跑多套业务,统一源码,统一部署,统一维护。 把业务服务继续拆分,剥离出最基础的 IM 服务,IM 通用服务,客服通用服务,而针对不同的业务特殊需求做最小化的定制服务开发。 部署方式则以平台形式部署,不同的业务方的服务跑在同一个平台上,但数据互相隔离。 服务继续被拆分的更微粒化,形成了一组服务矩阵(见下图)。
而部署方式,只需要在双机房建立两套对等集群,并另外建一个较小的灰度发布集群即可,所有不同业务都运行在统一平台集群上,如下图。
更细粒度的服务意味着每个服务的开发更简单,代码量更小,依赖更少,隔离稳定性更高。 但更细粒度的服务也意味着更繁琐的运维监控管理,直到今年公司内部弹性私有云、缓存云、消息队列、部署、监控、日志等基础系统日趋完善, 使得实施这类细粒度划分的微服务架构成为可能,运维成本可控。 而从当初 1.0 的 1 种应用进程,到 3.0 的 6、7 种应用进程,再到 4.0 的 50+ 更细粒度的不同种应用进程。 每种进程再根据承载业务流量不同分配不同的实例数,真正的实例进程数会过千。 为了更好的监控和管理这些进程,为此专门定制了一套面向服务的运维管理系统,见下图。
统一服务运维提供了实用的内部工具和库来帮助开发更健壮的微服务。 包括中心配置管理,流量埋点监控,数据库和缓存访问,运行时隔离,如下图所示是一个运行隔离的图示:
细粒度的微服务做到了进程间隔离,严格的开发规范和工具库帮助实现了异步消息和异步 HTTP 来避免多个跨进程的同步长调用链。 进程内部通过切面方式引入了服务增强容器 Armor 来隔离线程, 并支持进程内的单独业务降级和同步转异步化执行。而所有这些工具和库服务都是为了两个目标:
让服务进程运行时状态可见
让服务进程运行时状态可被管理和改变
最后我们回到前文留下的一个悬念,就是关于消息投递模型的缺陷。 一开始我们在接入层检测到终端连接断开后,消息无法投递,再将消息缓存下来,等终端重连接上来再拉取离线消息。 这个模型在移动时代表现的很不好,因为移动网络的不稳定性,导致经常断链后重连。 而准确的检测网络连接断开是依赖一个网络超时的,导致检测可能不准确,引发消息假投递成功。 新的模型如下图所示,它不再依赖准确的网络连接检测,投递前待确认消息 id 被缓存,而消息体被持久存储。 等到终端接收确认返回后,该消息才算投妥,未确认的消息 id 再重新登陆后或重连接后作为离线消息推送。 这个模型不会产生消息假投妥导致的丢失,但可能导致消息重复,只需由客户终端按消息 id 去重即可。
京东咚咚诞生之初正是京东技术转型到 Java 之时,经历这些年的发展,取得了很大的进步。 从草根走向专业,从弱小走向规模,从分散走向统一,从杂乱走向规范。 本文主要重心放在了几年来咚咚架构演进的过程,技术架构单独拿出来看我认为没有绝对的好与不好, 技术架构总是要放在彼时的背景下来看,要考虑业务的时效价值、团队的规模和能力、环境基础设施等等方面。 架构演进的生命周期适时匹配好业务的生命周期,才可能发挥最好的效果。
进入命令模式后,
显示所有数据库
&选定某个数据库
use 数据库名;
创建数据库
create database
显示数据库的所有表
查看某个表的具体表结构
describe 表名;
修改表内容的值
update 表名 set 参数名=要改成的值 where 参数名=某个值;
查看存储过程
查看存储过程的具体内容
show create procedure 存储过程名;}

我要回帖

更多关于 vc template 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信