var、let、const区别

 javascript  var、let、const区别已关闭评论
2月 182019
 

var、let、const区别

在javascript中有三种声明变量的方式:var、let、const。

var 声明全局变量,换句话理解就是,声明在for循环中的变量,跳出for循环同样可以使用。

for(var i=0;i<=1000;i++){ 
var sum=0; 
sum+=i; 

alert(sum);

声明在for循环内部的sum,跳出for循环一样可以使用,不会报错正常弹出结果

 

let:声明块级变量,即局部变量。 

在上面的例子中,跳出for循环,再使用sum变量就会报错,有着严格的作用域,变量只作用域当前隶属的代码块,不可重复定义同一个变量,不可在声明之前调用,必须先定义再使用,会报错,循环体中可以用let

注意:必须声明’use strict’;后才能使用let声明变量否则浏览并不能显示结果,

 

const:用于声明常量,也具有块级作用域 ,也可声明块级。

const PI=3.14;

它和let一样,也不能重复定义同一个变量,const一旦定义,无法修改

SpringMVC的拦截器(Interceptor)和过滤器(Filter)的区别与联系

 spring  SpringMVC的拦截器(Interceptor)和过滤器(Filter)的区别与联系已关闭评论
5月 162018
 

SpringMVC的拦截器(Interceptor)和过滤器(Filter)的区别与联系,挺不错的一篇文章,分享下https://blog.csdn.net/xiaoyaotan_111/article/details/53817918

一 简介

(1)过滤器:

依赖于servlet容器。在实现上基于函数回调,可以对几乎所有请求进行过滤,但是缺点是一个过滤器实例只能在容器初始化时调用一次。使用过滤器的目的是用来做一些过滤操作,获取我们想要获取的数据,比如:在过滤器中修改字符编码;在过滤器中修改HttpServletRequest的一些参数,包括:过滤低俗文字、危险字符等

(2)拦截器:

依赖于web框架,在SpringMVC中就是依赖于SpringMVC框架。在实现上基于Java的反射机制,属于面向切面编程AOP)的一种运用。由于拦截器是基于web框架的调用,因此可以使用Spring的依赖注入(DI)进行一些业务操作,同时一个拦截器实例在一个controller生命周期之内可以多次调用。但是缺点是只能对controller请求进行拦截,对其他的一些比如直接访问静态资源的请求则没办法进行拦截处理

二 多个过滤器与拦截器的代码执行顺序

如果在一个项目中仅仅只有一个拦截器或者过滤器,那么我相信相对来说理解起来是比较容易的。但是我们是否思考过:如果一个项目中有多个拦截器或者过滤器,那么它们的执行顺序应该是什么样的?或者再复杂点,一个项目中既有多个拦截器,又有多个过滤器,这时它们的执行顺序又是什么样的呢?

下面我将用简单的代码来测试说明:

(1)先定义两个过滤器:

i)过滤器1:

[java] view plain copy

  1. package cn.zifangsky.filter;  
  2.   
  3. import java.io.IOException;  
  4.   
  5. import javax.servlet.FilterChain;  
  6. import javax.servlet.ServletException;  
  7. import javax.servlet.http.HttpServletRequest;  
  8. import javax.servlet.http.HttpServletResponse;  
  9.   
  10. import org.springframework.web.filter.OncePerRequestFilter;  
  11.   
  12. public class TestFilter1 extends OncePerRequestFilter {  
  13.   
  14.     protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)  
  15.             throws ServletException, IOException {  
  16.         //在DispatcherServlet之前执行  
  17.         <a href=“http://www.07net01.com/tags-system-0.html” class=“infotextkey” style=“background:transparent;color:rgb(66,139,202);” target=“_blank”>system</a>.out.println(“############TestFilter1 doFilterInternal executed############”);  
  18.         filterChain.doFilter(request, response);  
  19.         //在视图页面返回给<a href=”http://www.07net01.com/tags-%E5%AE%A2%E6%88%B7%E7%AB%AF-0.html” class=”infotextkey” style=”background:transparent;color:rgb(66,139,202);” target=”_blank”>客户端</a>之前执行,但是执行顺序在Interceptor之后  
  20.         System.out.println(“############TestFilter1 doFilter after############”);  
  21. //      try {  
  22. //          Thread.sleep(10000);  
  23. //      } catch (InterruptedException e) {  
  24. //          e.printStackTrace();  
  25. //      }  
  26.     }  
  27.   
  28. }  

ii)过滤器2:

[java] view plain copy

  1. package cn.zifangsky.filter;  
  2.   
  3. import java.io.IOException;  
  4.   
  5. import javax.servlet.FilterChain;  
  6. import javax.servlet.ServletException;  
  7. import javax.servlet.http.HttpServletRequest;  
  8. import javax.servlet.http.HttpServletResponse;  
  9.   
  10. import org.springframework.web.filter.OncePerRequestFilter;  
  11.   
  12. public class TestFilter2 extends OncePerRequestFilter {  
  13.   
  14.     protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)  
  15.             throws ServletException, IOException {  
  16.         System.out.println(“############TestFilter2 doFilterInternal executed############”);  
  17.         filterChain.doFilter(request, response);  
  18.         System.out.println(“############TestFilter2 doFilter after############”);  
  19.   
  20.     }  
  21.   
  22. }  

iii)在web.xml中注册这两个过滤器:

[xml] view plain copy

  1.     <!– 自定义过滤器:testFilter1 –>   
  2.    <filter>  
  3.         <filter-name>testFilter1</filter-name>  
  4.         <filter-class>cn.zifangsky.filter.TestFilter1</filter-class>  
  5.     </filter>  
  6.     <filter-mapping>  
  7.         <filter-name>testFilter1</filter-name>  
  8.         <url-pattern>/*</url-pattern>  
  9.     </filter-mapping>  
  10.     <!– 自定义过滤器:testFilter2 –>   
  11.    <filter>  
  12.         <filter-name>testFilter2</filter-name>  
  13.         <filter-class>cn.zifangsky.filter.TestFilter2</filter-class>  
  14.     </filter>  
  15.     <filter-mapping>  
  16.         <filter-name>testFilter2</filter-name>  
  17.         <url-pattern>/*</url-pattern>  
  18.     </filter-mapping>  

(2)再定义两个拦截器:

i)拦截器1,基本拦截器:

[java] view plain copy

  1. package cn.zifangsky.interceptor;  
  2.   
  3. import javax.servlet.http.HttpServletRequest;  
  4. import javax.servlet.http.HttpServletResponse;  
  5.   
  6. import org.springframework.web.servlet.HandlerInterceptor;  
  7. import org.springframework.web.servlet.ModelAndView;  
  8.   
  9. public class BaseInterceptor implements HandlerInterceptor{  
  10.       
  11.     /** 
  12.      * 在DispatcherServlet之前执行 
  13.      * */  
  14.     public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {  
  15.         System.out.println(“************BaseInterceptor preHandle executed**********”);  
  16.         return true;  
  17.     }  
  18.   
  19.     /** 
  20.      * 在controller执行之后的DispatcherServlet之后执行 
  21.      * */  
  22.     public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)  
  23.             throws Exception {  
  24.         System.out.println(“************BaseInterceptor postHandle executed**********”);  
  25.     }  
  26.       
  27.     /** 
  28.      * 在页面渲染完成返回给客户端之前执行 
  29.      * */  
  30.     public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)  
  31.             throws Exception {  
  32.         System.out.println(“************BaseInterceptor afterCompletion executed**********”);  
  33. //      Thread.sleep(10000);  
  34.     }  
  35.   
  36. }  

ii)指定controller请求的拦截器:

[java] view plain copy

  1. package cn.zifangsky.interceptor;  
  2.   
  3. import javax.servlet.http.HttpServletRequest;  
  4. import javax.servlet.http.HttpServletResponse;  
  5.   
  6. import org.springframework.web.servlet.HandlerInterceptor;  
  7. import org.springframework.web.servlet.ModelAndView;  
  8.   
  9. public class TestInterceptor implements HandlerInterceptor {  
  10.   
  11.     public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {  
  12.         System.out.println(“************TestInterceptor preHandle executed**********”);  
  13.         return true;  
  14.     }  
  15.   
  16.     public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)  
  17.             throws Exception {  
  18.         System.out.println(“************TestInterceptor postHandle executed**********”);  
  19.     }  
  20.   
  21.     public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)  
  22.             throws Exception {  
  23.         System.out.println(“************TestInterceptor afterCompletion executed**********”);  
  24.     }  
  25. }  

iii)在SpringMVC的配置文件中注册这两个拦截器:

[java] view plain copy

  1. <!– 拦截器 –>  
  2. nbsp;   <mvc:interceptors>  
  3.     <!– 对所有请求都拦截,公共拦截器可以有多个 –>  
  4.     <bean name=“baseInterceptor” class=“cn.zifangsky.interceptor.BaseInterceptor” />  
  5.     <!– <bean name=“testInterceptor” class=“cn.zifangsky.interceptor.TestInterceptor” /> –>  
  6.     <mvc:interceptor>       
  7.         <!– 对/test.html进行拦截 –>  
  8.         <mvc:mapping path=“/test.html”/>  
  9.         <!– 特定请求的拦截器只能有一个 –>  
  10.         <bean class=“cn.zifangsky.interceptor.TestInterceptor” />  
  11.     </mvc:interceptor>  
  12. </mvc:interceptors>  

(3)定义一个测试使用的controller:

[java] view plain copy

  1. package cn.zifangsky.controller;  
  2.   
  3. import org.springframework.stereotype.Controller;  
  4. import org.springframework.web.bind.annotation.RequestMapping;  
  5. import org.springframework.web.servlet.ModelAndView;  
  6.   
  7. @Controller  
  8. public class TestController {  
  9.       
  10.     @RequestMapping(“/test.html”)  
  11.     public ModelAndView handleRequest(){  
  12.         System.out.println(“———TestController executed——–“);  
  13.         return new ModelAndView(“test”);  
  14.     }  
  15. }  

(4)视图页面test.jsp:

[html] view plain copy

  1. <%@ page language=“java” contentType=“text/html; charset=UTF-8”  
  2.     pageEncoding=“UTF-8”%>  
  3. <%  
  4. String path = request.getContextPath();  
  5. String basePath = request.getScheme()+”://”+request.getServerName()+”:”+request.getServerPort()+path+”/”;  
  6. %>      
  7. <html>  
  8. <head>  
  9. <meta http-equiv=“Content-Type” content=“text/html; charset=UTF-8”>  
  10. <base href=“http://983836259.blog.51cto.com/7311475/”>  
  11. <title>FilterDemo</title>  
  12. </head>  
  13. <body>  
  14.     <%  
  15.         System.out.println(“test.jsp is loading”);  
  16.     %>  
  17.     <div align=“center”>  
  18.         This is test page  
  19.     </div>  
  20. </body>  
  21. </html>  

(5)测试效果:

启动此测试项目,可以看到控制台中输出如下:

wKioL1hHhYrRCpQYAABafsYR7go378.png

这就说明了过滤器的运行是依赖于servlet容器的,跟springmvc等框架并没有关系。并且,多个过滤器的执行顺序跟xml文件中定义的先后关系有关

接着清空控制台中的输出内容并访问:http://localhost:9180/FilterDemo/test.html

可以看到,此时的控制台输出结果如下:

wKiom1hHhaPRQuBxAACG4WdOJbM758.png

相信从这个打印输出,大家就可以很清晰地看到有多个拦截器和过滤器存在时的整个执行顺序了。当然,对于过个拦截器它们之间的执行顺序跟在SpringMVC的配置文件中定义的先后顺序有关

注:对于整个SpringMVC的执行流程来说,如果加上上面的拦截器和过滤器,其最终的执行流程就如下图所示:

wKiom1hHhbmxseDtAACidU9Y84s787.png

shell中$(( ))与$( )还有${ }的区别

 开发  shell中$(( ))与$( )还有${ }的区别已关闭评论
1月 222018
 

学习了, 来自:http://blog.csdn.net/tg5156/article/details/19406275

$( )与` `(反引号)

在bash shell中,$( )与` `(反引号)都是用来做命令替换(command substitution)用的。
$ echo the last sunday is $(date -d “last sunday” +%Y-%m-%d)
得到上一星期天的日期

用$( )的理由

1. ` `很容易与’ ‘(单引号)搞混。有时在一些奇怪的字形显示中,两种符号是一模一样的(直竖两点)。
2. 在多层次的复合替换中,` `须要额外的跳脱(\`)处理,而$( )则比较直观。例如:
command1 `command2 `command3` `
原本的意图是在command2 `command3`中先将command3替换出来给command2处理,然后再将结果传给command1 `command2 …`来处理。
然而,真正的结果在命令行中却是分成了`command2`与` `两段。
正确的输入应该如下:
command1 `command2 \`command3\` `
换成$( )则一目了然:
command1 $(command2 $(command3))

$( )的不足

` `基本上可在全部的unix shell中使用,若写成shell script移植性比较高。而$( )并不是每一种shell都能使用。

${ }用来作变量替换

一般情况下,$var与${var}作用相同。但是用${ }会比较精确的界定变量名称的范围,例如:
$ A=B
$ echo $AB
原本是打算先将$A的结果替换出来,然后再补一个B字母于其后,但在命令行上,真正的结果却是只会替换变量名称为AB的值出来。
使用${ }就没问题了:
$ echo ${A}B
BB

${ }的一些特异功能

定义一个变量:
file=/dir1/dir2/dir3/my.file.txt
可以用${ }分别替换获得不同的值:
${file#*/} 拿掉第一个 / 及其左边的字符串:dir1/dir2/dir3/my.file.txt
${file##*/} 拿掉最后一个 / 及其左边的字符串:my.file.txt
${file#*.} 拿掉第一个 . 及其左边的字符串:file.txt
${file##*.} 拿掉最后一个 . 及其左边的字符串:txt
${file%/*} 拿掉最后一个 / 及其右边的字符串:/dir1/dir2/dir3
${file%%/*} 拿掉第一个 / 及其右边的字符串:(空值)
${file%.*} 拿掉最后一个 . 及其右边的字符串:/dir1/dir2/dir3/my.file
${file%%.*} 拿掉第一个 . 及其右边的字符串:/dir1/dir2/dir3/my
记忆的方法:
# 去掉左边(键盘上 # 在 $ 的左边)
% 去掉右边(在键盘上 % 在 $ 的右边)
单一符号是最小匹配,两个符号是最大匹配。
${file:0:5} 提取最左边的 5 个字节:/dir1
${file:5:5} 提取第 5 个字节右边的连续 5 个字节:/dir2
也可以对变量值里的字符串作替换:
${file/dir/path} 将第一个 dir 替换为 path:/path1/dir2/dir3/my.file.txt
${file//dir/path} 将全部 dir 替换为 path:/path1/path2/path3/my.file.txt
利用${ }还可针对不同的变量状态赋值(未设定、空值、非空值): 
${file-my.file.txt} 若 $file 未设定,则使用 my.file.txt 作传回值。(空值及非空值时不作处理) 
${file:-my.file.txt} 若 $file 未设定或为空值,则使用 my.file.txt 作传回值。(非空值时不作处理)
${file+my.file.txt} 若 $file 设为空值或非空值,均使用 my.file.txt 作传回值。(未设定时不作处理)
${file:+my.file.txt} 若 $file 为非空值,则使用 my.file.txt 作传回值。(未设定及空值时不作处理)
${file=my.file.txt} 若 $file 未设定,则使用 my.file.txt 作传回值,同时将 $file 赋值为 my.file.txt。 (空值及非空值时不作处理)
${file:=my.file.txt} 若 $file 未设定或为空值,则使用 my.file.txt 作传回值,同时将 $file 赋值为 my.file.txt。 (非空值时不作处理)
${file?my.file.txt} :若 $file 未设定,则将 my.file.txt 输出至 STDERR。(空值及非空值时不作处理)
${file:?my.file.txt} :若 $file 未设定或为空值,则将 my.file.txt 输出至 STDERR。(非空值时不作处理)
以上的理解在于,一定要分清楚 unset 与 null 及 non-null 这三种赋值状态。
一般而言,与 null 有关,若不带 : 的话,null 不受影响,若带 : 则连 null 也受影响。
${#var} 可计算出变量值的长度:
${#file} 可得到 27,/dir1/dir2/dir3/my.file.txt 刚好是 27 个字节。

bash数组(array)处理方法

一般而言,A=”a b c def”只是将 $A 替换为一个单一的字符串,但是改为 A=(a b c def),则是将 $A 定义为数组。
bash的数组替换方法可参考如下方法:
${A[@]} 或 ${A[*]} 得到 a b c def(全部数组)
${A[0]} 得到 a (第一个元素),${A[1]} 第二个…
${#A[@]} 或 ${#A[*]} 得到 4 (数组数量)
${#A[0]} 得到 1 (第一个元素 a 的长度),${#A[3]} 得到 3 (第四个元素 def 的长度)
A[3]=xyz 将第四个元素重新定义为 xyz

$(( ))的用途

用来作整数运算。在 bash 中,$(( ))的整数运算符号大致有这些:
+ – * / 加、减、乘、除
% 余数运算
& | ^ ! AND、OR、XOR、NOT运算
举例:
$ a=5; b=7; c=2
$ echo $((a+b*c))
19
$ echo $(((a+b)/c))
6
$ echo $(((a*b)%c))
1
在$(( ))中的变量名称也可以在其前面加 $ 符号:$(($a+$b*$c))也可以得到 19 的结果。
此外,$(( ))还可以作不同进制(如二进制、八进位、十六进制)运算,只是输出结果皆为十进制而已。
echo $((16#2a)) 结果为 42 (16进位转十进制)
举一个实用的例子:
当前的 umask 是 022,新建文件的权限为:
$ umask 022
$ echo “obase=8; $(( 8#666 & (8#777 ^ 8#$(umask)) ))” | bc
644
事实上,单纯用(( ))也可以重定义变量值,或作testing:
a=5; ((a++)) 将 $a 重定义为 6
a=5; ((a–)) a=4
a=5; b=7; ((a < b)) 会得到 0 (true) 的返回值
常见的用于(( ))的测试符号有以下这些:
< 小于
> 大于
<= 小于或等于
>= 大于或等于
== 等于
!= 不等于

JQuery中的load()、$.get()和$.post()详解

 jquery  JQuery中的load()、$.get()和$.post()详解已关闭评论
1月 182018
 

文章解析的比较清楚,来自: http://blog.csdn.net/csdn_yudong/article/details/52537609

load()

1.载入HTML文档 
load()方法是jQuery中最为简单和常用的Ajax方法,能载入远程HTML代码并插入DOM中。 
它的结构为:

load(url [,data][,callback])
参数名称 类型 说明
url String 请求HTML页面的URL地址
data(可选) Object 发送至服务器的key/value数据
callback(可选) Function 请求完成时的回调函数,无论请求成功或失败

首先创建一个test.html文件,用于被load()方法加载并追加到页面中。

test.html 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title></title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> </head> <body> <div class="comment"> <h6>张三:</h6> <p class="para">沙发.</p> </div> <div class="comment"> <h6>李四:</h6> <p class="para">板凳.</p> </div> <div class="comment"> <h6>王五:</h6> <p class="para">地板.</p> </div> </body> </html> 

然后再建一个demo1.html,在上面添加两个元素:<button>用来触发Ajax事件,id为”resText”的元素用来显示追加的HTML内容。HTML代码如下:

demo1.html 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title></title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <style type="text/css"> * { margin:0; padding:0;} body { font-size:12px;} .comment { margin-top:10px; padding:10px; border:1px solid #ccc;background:#DDD;} .comment h6 { font-weight:700; font-size:14px;} .para { margin-top:5px; text-indent:2em;background:#DDD;} </style> <!--   引入jQuery --> <script src="https://cdn.bootcss.com/jquery/1.7.1/jquery.min.js"></script> <script language="javascript" type="text/javascript"> $(function(){ $("#send").click(function(){ $("#resText").load("test.html");
      })
  }) </script> </head> <body> <input type="button" id="send" value="Ajax获取" /> <div class="comment"> 已有评论: </div> <div id="resText" ></div> </body> </html> 

显然,load()方法完成了原本很繁琐的工作。开发人员只需要使用jQuery选择器为HTML片段指定目标位置,然后将要加载的文件的URL作为参数传递给load()方法即可。当单击按钮后,test.html页面的HTML内ring就会被加载并插入主页面<div id=”resText”></div>的元素中。

2.筛选载入的HTML文档 
上面的例子是将test.html页面中的内容都加载到id为”resText”的元素里。如果只需要加载test.html页面内的某些元素,那么可以使用load()方法的URL参数来达到目的。通过为URL参数指定选择符,就可以很方便地从加载过来的HTML文档里筛选出所需要的内容。

load()方法的URL参数的语法结构为:“url selector”。注意,URL和选择器之间有一个空格。

例如只需要加载test.html页面中class为”para”的内容,可以将demo1.html中的

$("#resText").load("test.html");

改为

$("#resText").load("test.html  .para");

3.传递方法 
load()方法的传递方式根据参数data来自动指定。如果没有参数传递,则采用GET方式传递;反之,则会自动转换为POST方法。

//无参数传递,则是GET方式
$('#resText').load('test.php',function(){
    //... });
//有参数传递,则是POST方式
$('#resText').load('test.php',{name:'rain',age:'22'},function(){
    //... });

4.回调函数 
对于必须在加载完成后才能继续的操作,load()方法提供了回调函数(callback),该函数有3个参数,分别代表请求返回的内容请求状态XMLHttpRequest对象,jQuery代码如下:

$("#resText").load("test.html",function (responseText, textStatus, XMLHttpRequest){ alert(responseText); //请求返回的内容 alert(textStatus); //请求状态:success,error alert(XMLHttpRequest); //XMLHttpRequest对象 });

在load()方法中,无论Ajax请求是否成功,只要当请求完成(complete)后,回调函数(callback)就被触发。


load()方法通常用来从Web服务器上获取静态的数据文件,然后这并不能体现Ajax的全部价值。在项目中,如果需要传递一些参数给服务器中的页面,那么可以使用$.get()或者$.post()或者$.ajax()方法。


$.get()

$.get()方法使用GET方式来进行异步请求。 
它的结构为:

$.get(url[,data][,callback][,type])
参数名称 类型 说明
url String 请求的HTML页的URL地址
data(可选) Object 发送至服务器的key/value数据会作为QueryString附加到请求URL中
callback(可选) Function 载入成功时回调函数(只有当Response的返回状态是success才调用该方法)自动将请求结果和状态传递给该方法
type(可选) String 服务器端返回内容的样式,包括xml、html、script、json、text和_default

我们用$.get()来实现评论的功能:

get1.html 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title></title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <style type="text/css"> * { margin:0; padding:0;} body { font-size:12px;} .comment { margin-top:10px; padding:10px; border:1px solid #ccc;background:#DDD;} .comment h6 { font-weight:700; font-size:14px;} .para { margin-top:5px; text-indent:2em;background:#DDD;} </style> <!--   引入jQuery --> <script src="../scripts/jquery.js" type="text/javascript"></script> <script type="text/javascript"> //<![CDATA[ $(function(){ $("#send").click(function(){ $.get("get1.php", { 
                        username :  $("#username").val() , 
                        content :  $("#content").val()  
                    }, function (data, textStatus){ $("#resText").html(data); // 把返回的数据添加到页面上 }
            );
       })
    }) //]]> </script> </head> <body> <form id="form1" action="#"> <p>评论:</p> <p>姓名: <input type="text" name="username" id="username" /></p> <p>内容: <textarea name="content" id="content" rows="2" cols="20"></textarea></p> <p><input type="button" id="send" value="提交"/></p> </form> <div class='comment'>已有评论:</div> <div id="resText" > </div> </body> </html> 

get1.html向get1.php发送get请求,服务器端get1.php的代码如下:

<?php 
    header("Content-Type:text/html; charset=utf-8");
    echo "<div class='comment'><h6>{$_REQUEST['username']}:</h6><p class='para'>{$_REQUEST['content']}</p></div>";
?> 

由于服务器端get1.php返回的数据格式是一段HTML片段,因此并不需要经过处理就可以将新的HTML数据插入到主页面中。 
我们再来看一下get.html中的核心代码jQuery是如何完成get请求的:

$(function(){ $("#send").click(function(){ $.get("get1.php", { 
                        username :  $("#username").val() , 
                        content :  $("#content").val()  
                    }, function (data, textStatus){ $("#resText").html(data); // 把返回的数据添加到页面上 }
            );
       })
    })

我们可以看到在回调函数中,我们直接将返回回来的data(也就是HTML片段)直接在html中使用。

HTML片段实现起来只需要很少的工作量,但这种固定的数据结构并不一定能够在其他的Web应用程序中得到重用。

XML文档

服务器端是如何接收数据然后返回XML的呢? 
代码如下:

get2.php 
<?php 
    header("Content-Type:text/xml; charset=utf-8");
    echo "<?xml version='1.0' encoding='utf-8'?>".
         "<comments>".
         "<comment username='{$_REQUEST['username'] }' >".
         "<content>{$_REQUEST['content']}</content>".
         "</comment>".
         "</comments>";
?> 

注意:由于服务器端返回的数据格式是XML文档,因此需要在服务端设置Content-Type类型,代码如下:

header("Content-Type:text/xml; charset=utf-8");

对于服务器端返回的数据是XML格式的情况,我们需要对返回的数据进行处理,才能应用到HTML中,jQuery有强大的DOM处理能力,处理XML文档与处理HTML文档一样,也可以使用常规的attr()、find()、filter()以及其他方法。jQuery代码如下:

$(function(){ $("#send").click(function(){ $.get("get2.php", { 
      username :  $("#username").val() , 
      content :  $("#content").val()  
    }, function (data, textStatus){ var username = $(data).find("comment").attr("username"); var content = $(data).find("comment content").text(); var txtHtml = "<div class='comment'><h6>"+username+":</h6><p class='para'>"+content+"</p></div>";
      $("#resText").html(txtHtml); // 把返回的数据添加到页面上 },'XML');
  });
})

返回数据格式为XML文档的过程实现起来比HTML片段要稍微复杂些,但XML文档的可移植性是其他数据格式无法比拟的,因此以这种格式提供的数据的重要性将极大提高。不过,XML文档体积相对较大,与其他文件格式相比,解析和操作它们的速度要慢一些。

JSON文件 
之所以会出现这种数据格式的文件,很大程度上是因为XML文档体积大和难以解析。JSON文件和XML文档一样,也可以方便的被重用。而且,JSON文件非常简洁,也容易阅读。

服务器端是如何接收数据然后返回JSON的呢? 
代码如下:

get3.php 
<?php 
    header("Content-Type:text/html; charset=utf-8");
    echo "{ \"username\" : \"{$_REQUEST['username']}\" , \"content\" : \"{$_REQUEST['content']}\"}" ?>

JSON的格式还是比较严格的,所以格式不能写错了。 
由于服务器端返回的数据格式是JSON文件,因此需要对返回的数据进行处理之后,才可以将新的HTML数据添加到主页面中。HTML文件其他部分还是一样,要修改的地方是jQuery部分,jQuery代码如下:

$(function(){ $("#send").click(function(){ $.get("get3.php", { 
                username :  $("#username").val() , 
                content :  $("#content").val()  
            }, function (data, textStatus){ var username = data.username; var content = data.content; var txtHtml = "<div class='comment'><h6>"+username+":</h6><p class='para'>"+content+"</p></div>";
        $("#resText").html(txtHtml); // 把返回的数据添加到页面上 },"json");
       });
    })

在上面的代码中,将$.get()方法的第4个参数(type)设置为”json”来代表期待服务器返回的数据格式。

对于服务器端返回HTML片段、XML数据、JSON数据的优缺点进行分析,可以的得知在不需要与其他应用程序共享数据的时候,使用HTML片段来提供返回数据一般来说是最简单的;如果数据需要重用,那么JSON文件是不错的选择,它在性能和文件大小方面具有优势,它是Web服务器领域的“世界语”,我们推荐使用JSON。

$.post()

它与$.get()方法的结构和使用方式都相同,不过它们之间仍然有以下区别。

  • GET请求会将参数跟在URL后进行传递,而POST请求则是作为HTPP消息的实体内容发送给Web服务器。当然,在Ajax请求中,这种区别对用户是不可见的
  • GET方式对传输的数据有大小限制(通常不能大于2KB),而使用POST方式传递的数据量要比GET方式大得多(理论上不受限制)
  • GET方式请求的数据会被浏览器缓存起来,因此其他人就可以从浏览器的历史记录中读取到这些数据,例如账号和密码等。在某种情况下,GET方式会带来严重的安全性问题,而POST方式相对来说就可以避免这些问题。
  • GET方式和POST方式传递的数据在服务器端的获取也不相同。在PHP中,GET方式的数据可以用$_GET[]获取,而POST方式可以用$_POST[]获取。两种方式都可以用$_REQUEST[]来获取。

由于POST和GET方式提交的所有数据都可以通过$_REQUEST[]来获取,因此只需要改变jQuery函数,就可以将程序在GET请求和POST请求之间切换。 
代码如下:

$(function(){ $("#send").click(function(){ $.post("post1.php", { 
      username :  $("#username").val() , 
      content :  $("#content").val()  
    }, function (data, textStatus){ $("#resText").html(data); // 把返回的数据添加到页面上 });
  })
})

load()、$.get()和$.post(),我们可以发现,$.get()和$.post()方法是jQuery中的全局函数,而在此之前讲的load()是对jQuery对象进行操作的。

ScheduledExecutorService类 scheduleWithFixedDelay() 和 scheduleFixedRate() 区别

 java  ScheduledExecutorService类 scheduleWithFixedDelay() 和 scheduleFixedRate() 区别已关闭评论
7月 312017
 

好记性不如烂笔头, 不用容易忘记,记录下 scheduleWithFixedDelay() 和 scheduleFixedRate() 区别

来自:http://blog.csdn.net/butingnal/article/details/12775277

先说scheduleWithFixedDelay(),

scheduleWithFixedDelay从字面意义上可以理解为就是以固定延迟(时间)来执行线程任务,它实际上是不管线程任务的执行时间的,每次都要把任务执行完成后再延迟固定时间后再执行下一次。

而scheduleFixedRate呢,是以固定频率来执行线程任务,固定频率的含义就是可能设定的固定时间不足以完成线程任务,但是它不管,达到设定的延迟时间了就要执行下一次了。

不知道大家理解了没有,下面是示例:

 

[java] view plain copy

  1. public static void scheduleWithFixedDelay() {  
  2.   
  3.     final ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(2);  
  4.     // 响铃线程  
  5.     final Runnable beeper = new Runnable() {  
  6.         public void run() {  
  7.             SimpleDateFormat sf = new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss”);  
  8.             long time = (long) (Math.random() * 1000);  
  9.             // 输出线程的名字和使用目标对象及休眠的时间  
  10.             System.out.println(sf.format(new Date())+“线程:”+Thread.currentThread().getName()+“:Sleeping”+time+“ms”);  
  11.             try {  
  12.                 Thread.sleep(time);  
  13.             } catch (InterruptedException e) {  
[java] view plain copy

  1.         }  
  2.         }  
  3.     };  
  4.     // 设定执行线程计划,初始10s延迟,每次任务完成后延迟10s再执行一次任务  
  5.     final ScheduledFuture<?> sFuture=scheduledExecutorService.scheduleWithFixedDelay(beeper,10,10,TimeUnit.SECONDS);  
  6.   
  7.     // 40s后取消线程任务  
  8.     scheduledExecutorService.schedule(new Runnable() {  
  9.         public void run() {  
  10.             sFuture.cancel(true);  
  11.             scheduledExecutorService.shutdown();  
  12.         }  
  13.     }, 40, TimeUnit.SECONDS);  
  14.   
  15. }  


执行结果:

2013-10-16 10:45:51 线程:pool-1-thread-2:Sleeping 726ms
2013-10-16 10:46:02 线程:pool-1-thread-2:Sleeping 288ms
2013-10-16 10:46:12 线程:pool-1-thread-2:Sleeping 294ms

从执行结果数量看只执行了3次,因为每次要把任务执行完成再执行下一次,导致40s按10s的延迟时间不足以执行4次。

 

 

[html] view plain copy

  1. public static void scheduleAtFixedRate() {  
  2.     // 声明线程池  
  3.     final ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);  
  4.     // 响铃线程  
  5.     final Runnable beeper = new Runnable() {  
  6.         public void run() {  
  7.             SimpleDateFormat sf = new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss”);  
  8.             long time = (long) (Math.random() * 1000);  
  9.             // 输出线程的名字和使用目标对象及休眠的时间  
  10.             System.out.println(sf.format(new Date()) + ” 线程:” + Thread.currentThread().getName() + “:Sleeping ” + time + “ms”);  
  11.             try {  
  12.                 Thread.sleep(time);  
  13.             } catch (InterruptedException e) {  
  14.             }  
  15.         }  
  16.     };  
  17.     // 计划响铃,初始延迟10s然后以10s的频率执行响铃  
  18.     final ScheduledFuture<?> beeperHandle = scheduledExecutorService.scheduleAtFixedRate(beeper, 10, 10, TimeUnit.SECONDS);  
  19.   
  20.     // 取消响铃并关闭线程  
  21.     final Runnable cancelBeeper = new Runnable() {  
  22.         public void run() {  
  23.             System.out.println(Thread.currentThread().getName() + “CANCEL…”);  
  24.             beeperHandle.cancel(true);  
  25.             scheduledExecutorService.shutdown();  
  26.         }  
  27.     };  
  28.     // 60s后执行scheduleAtFixedRate  
  29.     scheduledExecutorService.schedule(cancelBeeper, 40, TimeUnit.SECONDS);  
  30. }  

 

执行结果:

2013-10-16 10:16:50 线程:pool-1-thread-1:Sleeping 868ms
2013-10-16 10:17:00 线程:pool-1-thread-1:Sleeping 587ms
2013-10-16 10:17:10 线程:pool-1-thread-1:Sleeping 313ms
2013-10-16 10:17:20 线程:pool-1-thread-1:Sleeping 969ms
pool-1-thread-1CANCEL…

看时间我们就可以知道是每个10s就执行下一次了。

hadoop、storm和spark的区别、比较

 开发  hadoop、storm和spark的区别、比较已关闭评论
9月 212016
 

整理的一些网上关于hadoop、storm和spark的资料。

一、hadoop、Storm该选哪一个?

为了区别hadoop和Storm,该部分将回答如下问题
1.hadoop、Storm各是什么运算
2.Storm为什么被称之为流式计算系统
3.hadoop适合什么场景,什么情况下使用hadoop
4.什么是吞吐量

首先整体认识:Hadoop是磁盘级计算,进行计算时,数据在磁盘上,需要读写磁盘;Storm是内存级计算,数据直接通过网络导入内存。读写内存比读写磁盘速度快n个数量级。根据Harvard CS61课件,磁盘访问延迟约为内存访问延迟的75000倍。所以Storm更快。

注释:
1. 延时 , 指数据从产生到运算产生结果的时间,“快”应该主要指这个。
2. 吞吐, 指系统单位时间处理的数据量。

storm的网络直传、内存计算,其时延必然比hadoop的通过hdfs传输低得多;当计算模型比较适合流式时,storm的流式处理,省去了批处理的收集数据的时间;因为storm是服务型的作业,也省去了作业调度的时延。所以从时延上来看,storm要快于hadoop。

从原理角度来讲:

  • Hadoop M/R基于HDFS,需要切分输入数据、产生中间数据文件、排序、数据压缩、多份复制等,效率较低。

  • Storm 基于ZeroMQ这个高性能的消息通讯库,不持久化数据。

为什么storm比hadoop快,下面举一个应用场景
说一个典型的场景,几千个日志生产方产生日志文件,需要进行一些ETL操作存入一个数据库。

假设利用hadoop,则需要先存入hdfs,按每一分钟切一个文件的粒度来算(这个粒度已经极端的细了,再小的话hdfs上会一堆小文件),hadoop开始计算时,1分钟已经过去了,然后再开始调度任务又花了一分钟,然后作业运行起来,假设机器特别多,几钞钟就算完了,然后写数据库假设也花了很少的时间,这样,从数据产生到最后可以使用已经过去了至少两分多钟。
而流式计算则是数据产生时,则有一个程序去一直监控日志的产生,产生一行就通过一个传输系统发给流式计算系统,然后流式计算系统直接处理,处理完之后直接写入数据库,每条数据从产生到写入数据库,在资源充足时可以在毫秒级别完成。

同时说一下另外一个场景:
如果一个大文件的wordcount,把它放到storm上进行流式的处理,等所有已有数据处理完才让storm输出结果,这时候,你再把它和hadoop比较快慢,这时,其实比较的不是时延,而是比较的吞吐了。

——————————————————————————————————————————–
最主要的方面:Hadoop使用磁盘作为中间交换的介质,而storm的数据是一直在内存中流转的。
两者面向的领域也不完全相同,一个是批量处理,基于任务调度的;另外一个是实时处理,基于流。
以水为例,Hadoop可以看作是纯净水,一桶桶地搬;而Storm是用水管,预先接好(Topology),然后打开水龙头,水就源源不断地流出来了。

——————————————————————————————————————————–
Storm的主工程师Nathan Marz表示: Storm可以方便地在一个计算机集群中编写与扩展复杂的实时计算,Storm之于实时处理,就好比Hadoop之于批处理。Storm保证每个消息都会得到处理,而且它很快——在一个小集群中,每秒可以处理数以百万计的消息。更棒的是你可以使用任意编程语言来做开发。
Storm的主要特点如下:
1.简单的编程模型。类似于MapReduce降低了并行批处理复杂性,Storm降低了进行实时处理的复杂性。
2.可以使用各种编程语言。你可以在Storm之上使用各种编程语言。默认支持Clojure、Java、Ruby和Python。要增加对其他语言的支持,只需实现一个简单的Storm通信协议即可。
3.容错性。Storm会管理工作进程和节点的故障。
4.水平扩展。计算是在多个线程、进程和服务器之间并行进行的。
5.可靠的消息处理。Storm保证每个消息至少能得到一次完整处理。任务失败时,它会负责从消息源重试消息。
6.快速。系统的设计保证了消息能得到快速的处理,使用MQ作为其底层消息队列。
7.本地模式。Storm有一个“本地模式”,可以在处理过程中完全模拟Storm集群。这让你可以快速进行开发和单元测试。

——————————————————————————————————————————–
在消耗资源相同的情况下,一般来说storm的延时低于mapreduce。但是吞吐也低于mapreduce。storm是典型的流计算系统,mapreduce是典型的批处理系统。下面对流计算和批处理系统流程

这个个数据处理流程来说大致可以分三个阶段:
1. 数据采集与准备
2. 数据计算(涉及计算中的中间存储), 题主中的“那些方面决定”应该主要是指这个阶段处理方式。
3. 数据结果展现(反馈)

1)数据采集阶段,目前典型的处理处理策略:数据的产生系统一般出自页面打点和解析DB的log,流计算将数据采集中消息队列(比如kafaka,metaQ,timetunle)等。批处理系统一般将数据采集进分布式文件系统(比如HDFS),当然也有使用消息队列的。我们暂且把消息队列和文件系统称为预处理存储。二者在延时和吞吐上没太大区别,接下来从这个预处理存储进入到数据计算阶段有很大的区别,流计算一般在实时的读取消息队列进入流计算系统(storm)的数据进行运算,批处理一系统一般会攒一大批后批量导入到计算系统(hadoop),这里就有了延时的区别。
2)数据计算阶段,流计算系统(storm)的延时低主要有一下几个方面(针对题主的问题)
A: storm 进程是常驻的,有数据就可以进行实时的处理
mapreduce 数据攒一批后由作业管理系统启动任务,Jobtracker计算任务分配,tasktacker启动相关的运算进程
B: stom每个计算单元之间数据之间通过网络(zeromq)直接传输。
mapreduce map任务运算的结果要写入到HDFS,在于reduce任务通过网络拖过去运算。相对来说多了磁盘读写,比较慢
C: 对于复杂运算
storm的运算模型直接支持DAG(有向无环图)
mapreduce 需要肯多个MR过程组成,有些map操作没有意义的

3)数据结果展现
流计算一般运算结果直接反馈到最终结果集中(展示页面,数据库,搜索引擎的索引)。而mapreduce一般需要整个运算结束后将结果批量导入到结果集中。

实际流计算和批处理系统没有本质的区别,像storm的trident也有批概念,而mapreduce可以将每次运算的数据集缩小(比如几分钟启动一次),facebook的puma就是基于hadoop做的流计算系统。

 

二、高性能并行计算引擎Storm和Spark比较

Spark基于这样的理念,当数据庞大时,把计算过程传递给数据要比把数据传递给计算过程要更富效率。每个节点存储(或缓存)它的数据集,然后任务被提交给节点。

所以这是把过程传递给数据。这和Hadoop map/reduce非常相似,除了积极使用内存来避免I/O操作,以使得迭代算法(前一步计算输出是下一步计算的输入)性能更高。

Shark只是一个基于Spark的查询引擎(支持ad-hoc临时性的分析查询)

而Storm的架构和Spark截然相反。Storm是一个分布式流计算引擎。每个节点实现一个基本的计算过程,而数据项在互相连接的网络节点中流进流出。和Spark相反,这个是把数据传递给过程。

两个框架都用于处理大量数据的并行计算。

Storm在动态处理大量生成的“小数据块”上要更好(比如在Twitter数据流上实时计算一些汇聚功能或分析)。

Spark工作于现有的数据全集(如Hadoop数据)已经被导入Spark集群,Spark基于in-memory管理可以进行快讯扫描,并最小化迭代算法的全局I/O操作。

不过Spark流模块(Streaming Module)倒是和Storm相类似(都是流计算引擎),尽管并非完全一样。

Spark流模块先汇聚批量数据然后进行数据块分发(视作不可变数据进行处理),而Storm是只要接收到数据就实时处理并分发。

不确定哪种方式在数据吞吐量上要具优势,不过Storm计算时间延迟要小。

总结下,SparkStorm设计相反,而Spark Steaming才和Storm类似,前者有数据平滑窗口(sliding window),而后者需要自己去维护这个窗口。

转自:http://flyingsnail.blog.51cto.com/5341669/1571281

**************************************************************************************************

其它文章说明:




分布式计算(Distributed Computing)

对于如何处理大数据,计算机科学界有两大方向:第一个方向是集中式计算,就是通过不断增加处理器的数量来增强单个计算机的计算能力,从而提高处理数据的速度。第二个方向是分布式计算,就是把一组计算机通过网络相互连接组成分散系统,然后将需要处理的大量数据分散成多个部分,交由分散系统内的计算机组同时计算,最后将这些计算结果合并得到最终的结果。尽管分散系统内的单个计算机的计算能力不强,但是由于每个计算机只计算一部分数据,而且是多台计算机同时计算,所以就分散系统而言,处理数据的速度会远高于单个计算机。
过去,分布式计算理论比较复杂,技术实现比较困难,因此在处理大数据方面,集中式计算一直是主流解决方案。IBM的大型机就是集中式计算的典型硬件,很多银行和政府机构都用它处理大数据。不过,对于当时的互联网公司来说,IBM的大型机的价格过于昂贵。因此,互联网公司的把研究方向放在了可以使用在廉价计算机上的分布式计算上。

服务器集群(Server Cluster)

服务器集群是一种提升服务器整体计算能力的解决方案。它是由互相连接在一起的服务器群所组成的一个并行式或分布式系统。服务器集群中的服务器运行同一个计算任务。因此,从外部看,这群服务器表现为一台虚拟的服务器,对外提供统一的服务。
尽管单台服务器的运算能力有限,但是将成百上千的服务器组成服务器集群后,整个系统就具备了强大的运算能力,可以支持大数据分析的运算负荷。Google,Amazon,阿里巴巴的计算中心里的服务器集群都达到了5000台服务器的规模。

大数据的技术基础:MapReduce、Google File System和BigTable
2003年到2004年间,Google发表了MapReduce、GFS(Google File System)和BigTable三篇技术论文,提出了一套全新的分布式计算理论。
MapReduce是分布式计算框架,GFS(Google File System)是分布式文件系统,BigTable是基于Google File System的数据存储系统,这三大组件组成了Google的分布式计算模型。
Google的分布式计算模型相比于传统的分布式计算模型有三大优势:首先,它简化了传统的分布式计算理论,降低了技术实现的难度,可以进行实际的应用。其次,它可以应用在廉价的计算设备上,只需增加计算设备的数量就可以提升整体的计算能力,应用成本十分低廉。最后,它被Google应用在Google的计算中心,取得了很好的效果,有了实际应用的证明。

后来,各家互联网公司开始利用Google的分布式计算模型搭建自己的分布式计算系统,Google的这三篇论文也就成为了大数据时代的技术核心

主流的三大分布式计算系统:Hadoop,Spark和Storm
由于Google没有开源Google分布式计算模型的技术实现,所以其他互联网公司只能根据Google三篇技术论文中的相关原理,搭建自己的分布式计算系统。
Yahoo的工程师Doug Cutting和Mike Cafarella在2005年合作开发了分布式计算系统Hadoop。后来,Hadoop被贡献给了Apache基金会,成为了Apache基金会的开源项目。Doug Cutting也成为Apache基金会的主席,主持Hadoop的开发工作。
Hadoop采用MapReduce分布式计算框架,并根据GFS开发了HDFS分布式文件系统,根据BigTable开发了HBase数据存储系统。尽管和Google内部使用的分布式计算系统原理相同,但是Hadoop在运算速度上依然达不到Google论文中的标准。

不过,Hadoop的开源特性使其成为分布式计算系统的事实上的国际标准。Yahoo,Facebook,Amazon以及国内的百度,阿里巴巴等众多互联网公司都以Hadoop为基础搭建自己的分布式计算系统。
Spark也是Apache基金会的开源项目,它由加州大学伯克利分校的实验室开发,是另外一种重要的分布式计算系统。它在Hadoop的基础上进行了一些架构上的改良。Spark与Hadoop最大的不同点在于,Hadoop使用硬盘来存储数据,而Spark使用内存来存储数据,因此Spark可以提供超过Hadoop100倍的运算速度。但是,由于内存断电后会丢失数据,Spark不能用于处理需要长期保存的数据。
Storm是Twitter主推的分布式计算系统,它由BackType团队开发,是Apache基金会的孵化项目。它在Hadoop的基础上提供了实时运算的特性,可以实时的处理大数据流。不同于Hadoop和Spark,Storm不进行数据的收集和存储工作,它直接通过网络实时的接受数据并且实时的处理数据,然后直接通过网络实时的传回结果。
Hadoop,Spark和Storm是目前最重要的三大分布式计算系统,Hadoop常用于离线的复杂的大数据处理,Spark常用于离线的快速的大数据处理,而Storm常用于在线的实时的大数据处理。

转自:http://blog.sina.com.cn/s/blog_631d3a630101nb77.html

ASCII、Unicode、GBK和UTF-8字符编码的区别联系

 其它  ASCII、Unicode、GBK和UTF-8字符编码的区别联系已关闭评论
9月 062016
 

重新温习下编码知识,来自:http://dengo.org/archives/901

很久很久以前,有一群人,他们决定用8个可以开合的晶体管来组合成不同的状态,以表示世界上的万物。他们看到8个开关状态是好的,于是他们把这称为”字节“。再后来,他们又做了一些可以处理这些字节的机器,机器开动了,可以用字节来组合出很多状态,状态开始变来变去。他们看到这样是好的,于是它们就这机器称为”计算机“。

开始计算机只在美国用。八位的字节一共可以组合出256(2的8次方)种不同的状态。 他们把其中的编号从0开始的32种状态分别规定了特殊的用途,一但终端、打印机遇上约定好的这些字节被传过来时,就要做一些约定的动作。遇上0×10, 终端就换行,遇上0×07, 终端就向人们嘟嘟叫,例好遇上0x1b, 打印机就打印反白的字,或者终端就用彩色显示字母。他们看到这样很好,于是就把这些0×20以下的字节状态称为”控制码”。他们又把所有的空 格、标点符号、数字、大小写字母分别用连续的字节状态表示,一直编到了第127号,这样计算机就可以用不同字节来存储英语的文字了。大家看到这样,都感觉 很好,于是大家都把这个方案叫做 ANSI的”Ascii”编码(American Standard Code for Information Interchange,美国信息互换标准代码)。当时世界上所有的计算机都用同样的ASCII方案来保存英文文字。

后来,就像建造巴比伦塔一样,世界各地的都开始使用计算机,但是很多国家用的不是英文,他们的字母里有许多是ASCII里没有的,为了可以在计算机保存他们的文字,他们决定采用 127号之后的空位来表示这些新的字母、符号,还加入了很多画表格时需要用下到的横线、竖线、交叉等形状,一直把序号编到了最后一个状态255。从128 到255这一页的字符集被称”扩展字符集“。从此之后,贪婪的人类再没有新的状态可以用了,美帝国主义可能没有想到还有第三世界国家的人们也希望可以用到计算机吧!

等中国人们得到计算机时,已经没有可以利用的字节状态来表示汉字,况且有6000多个常用汉字需要保存呢。但是这难不倒智慧的中国人民,我们不客气地把那些127号之后的奇异符号们直接取消掉, 规定:一个小于127的字符的意义与原来相同,但两个大于127的字符连在一起时,就表示一个汉字,前面的一个字节(他称之为高字节)从0xA1用到 0xF7,后面一个字节(低字节)从0xA1到0xFE,这样我们就可以组合出大约7000多个简体汉字了。在这些编码里,我们还把数学符号、罗马希腊的字母、日文的假名们都编进去了,连在 ASCII 里本来就有的数字、标点、字母都统统重新编了两个字节长的编码,这就是常说的”全角”字符,而原来在127号以下的那些就叫”半角”字符了。 中国人民看到这样很不错,于是就把这种汉字方案叫做 “GB2312“。GB2312 是对 ASCII 的中文扩展。

但是中国的汉字太多了,我们很快就就发现有许多人的人名没有办法在这里打出来,特别是某些很会麻烦别人的国家领导人。于是我们不得不继续把 GB2312 没有用到的码位找出来老实不客气地用上。 后来还是不够用,于是干脆不再要求低字节一定是127号之后的内码,只要第一个字节是大于127就固定表示这是一个汉字的开始,不管后面跟的是不是扩展字符集里的内容。结果扩展之后的编码方案被称为 GBK 标准,GBK包括了GB2312 的所有内容,同时又增加了近20000个新的汉字(包括繁体字)和符号。 后来少数民族也要用电脑了,于是我们再扩展,又加了几千个新的少数民族的字,GBK扩成了 GB18030。从此之后,中华民族的文化就可以在计算机时代中传承了。 中国的程序员们看到这一系列汉字编码的标准是好的,于是通称他们叫做 “DBCS“(Double Byte Charecter Set 双字节字符集)。在DBCS系列标准里,最大的特点是两字节长的汉字字符和一字节长的英文字符并存于同一套编码方案里,因此他们写的程序为了支持中文处理,必须要注意字串里的每一个字节的值,如果这个值是大于127的,那么就认为一个双字节字符集里的字符出现了。那时候凡是受过加持,会编程的计算机僧侣 们都要每天念下面这个咒语数百遍: “一个汉字算两个英文字符!一个汉字算两个英文字符……”

因为当时各个国家都像中国这样搞出一套自己的编码标准,结果互相之间谁也不懂谁的编码,谁也不支持别人的编码,连大陆和台湾这样只相隔了150海里,使用着同一种语言的兄弟地区,也分别采用了不同的 DBCS 编码方案——当时的中国人想让电脑显示汉字,就必须装上一个”汉字系统”,专门用来处理汉字的显示、输入的问题,但是那个台湾的愚昧封建人士写的算命程序就必须加装另一套支持 BIG5 编码的什么”倚天汉字系统”才可以用,装错了字符系统,显示就会乱了套!这怎么办?而且世界民族之林中还有那些一时用不上电脑的穷苦人民,他们的文字又怎么办? 真是计算机的巴比伦塔命题啊!

正在这时,大天使加百列及时出现了——一个叫 ISO (国际标谁化组织)的国际组织决定着手解决这个问题。他们采用的方法很简单:废了所有的地区性编码方案,重新搞一个包括了地球上所有文化、所有字母和符号 的编码!他们打算叫它”Universal Multiple-Octet Coded Character Set”,简称 UCS, 俗称 “unicode“。
unicode开始制订时,计算机的存储器容量极大地发展了,空间再也不成为问题了。于是 ISO 就直接规定必须用两个字节,也就是16位来统一表示所有的字符,对于ASCII里的那些“半角”字符,unicode包持其原编码不变,只是将其长度由原来的8位扩展为16位,而其他文化和语言的字符则全部重新统一编码。由于”半角”英文符号只需要用到低8位,所以其高8位永远是0,因此这种大气的方案在保存英文文本时会多浪费一倍的空间。

这时候,从旧社会里走过来的程序员开始发现一个奇怪的现象:他们的strlen函数靠不住了,一个汉字不再是相当于两个字符了,而是一个!是的,从unicode开始,无论是半角的英文字母,还是全角的汉字,它们都是统一的”一个字符“!同时,也都是统一的”两个字节“,请注意”字符”和”字节”两个术语的不同,“字节”是一个8位的物理存贮单元,而“字符”则是一个文化相关的符号。在unicode中,一个字符就是两个字节。一个汉字算两个英文字符的时代已经快过去了。

unicode同样也不完美,这里就有两个的问题,一个是,如何才能区别unicode和ascii?计算机怎么知道三个字节表示一个符号,而不是分别表示三个符号呢?第二个问题是,我们已经知道,英文字母只用一个字节表示就够了,如果unicode统一规定,每个符号用三个或四个字节表示,那么每个英文字母前都必然有二到三个字节是0,这对于存储空间来说是极大的浪费,文本文件的大小会因此大出二三倍,这是难以接受的。

unicode在很长一段时间内无法推广,直到互联网的出现,为解决unicode如何在网络上传输的问题,于是面向传输的众多 UTF(UCS Transfer Format)标准出现了,顾名思义,UTF-8就是每次8个位传输数据,而UTF-16就是每次16个位。UTF-8就是在互联网上使用最广的一种unicode的实现方式,这是为传输而设计的编码,并使编码无国界,这样就可以显示全世界上所有文化的字符了。

UTF-8最大的一个特点,就是它是一种变长的编码方式。它可以使用1~4个字节表示一个符号,根据不同的符号而变化字节长度,当字符在ASCII码的范围时,就用一个字节表示,保留了ASCII字符一个字节的编码做为它的一部分,注意的是unicode一个中文字符占2个字节,而UTF-8一个中文字符占3个字节)。从unicode到uft-8并不是直接的对应,而是要过一些算法和规则来转换。

Unicode符号范围 | UTF-8编码方式

(十六进制)         |        (二进制)
—————————————————————–
0000 0000-0000 007F | 0xxxxxxx
0000 0080-0000 07FF | 110xxxxx 10xxxxxx
0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

之前一直对字符编码很模糊,网查资料被忽悠地晕头转向,看完这篇风趣的文章,把之前模糊的知识点串联起来,并稍加总结,我和我的小伙伴们都明白了!

10月 102015
 

这里介绍一个在父项目中的根结点中声明dependencyManagement和dependencies的区别

dependencyManagement

Maven 使用dependencyManagement 元素来提供了一种管理依赖版本号的方式。通常会在一个组织或者项目的最顶层的父POM 中看到dependencyManagement 元素。使用pom.xml 中的dependencyManagement 元素能让
所有在子项目中引用一个依赖而不用显式的列出版本号。Maven 会沿着父子层次向上走,直到找到一个拥有dependencyManagement 元素的项目,然后它就会使用在这个dependencyManagement 元素中指定的版本号。

 

例如在父项目里:

Xml代码  收藏代码

  1. <dependencyManagement>  
  2. <dependencies>  
  3. <dependency>  
  4. <groupId>mysql</groupId>  
  5. <artifactId>mysql-connector-java</artifactId>  
  6. <version>5.1.2</version>  
  7. </dependency>  
  8. …  
  9. <dependencies>  
  10. </dependencyManagement>  

然后在子项目里就可以添加mysql-connector时可以不指定版本号,例如:

 

Xml代码  收藏代码

  1. <dependencies>  
  2. <dependency>  
  3. <groupId>mysql</groupId>  
  4. <artifactId>mysql-connector-java</artifactId>  
  5. </dependency>  
  6. </dependencies>  

这样做的好处就是:如果有多个子项目都引用同一样依赖,则可以避免在每个使用的子项目里都声明一个版本号,这样当想升级或切换到另一个版本时,只需要在顶层父容器里更新,而不需要一个一个子项目的修改 ;另外如果某个子项目需要另外的一个版本,只需要声明version就可。

 

dependencyManagement里只是声明依赖,并不实现引入,因此子项目需要显式的声明需要用的依赖。

dependencies

相对于dependencyManagement,所有声明在dependencies里的依赖都会自动引入,并默认被所有的子项目继承。

 

classifier

如果你要发布同样的代码,但是由于技术原因需要生成两个单独的构件,你就要使用一个分类器(classifier)。例如,如果你想要构建两个单独的构件成JAR,一个使用Java 1.4 编译器,另一个使用Java 6 编译器,你就可以使用分类器
来生成两个单独的JAR构件,它们有同样的groupId:artifactId:version组合。如果你的项目使用本地扩展类库,你可以使用分类器为每一个目标平台生成一个构件。分类器常用于打包构件的源码,JavaDoc 或者二进制集合。

3月 112015
 

拦截器与Filter的区别 
Spring的拦截器与Servlet的Filter有相似之处,比如二者都是AOP编程思想的体现,都能实现权限检查、日志记录等。不同的是:
使用范围不同:Filter是Servlet规范规定的,只能用于Web程序中。而拦截器既可以用于Web程序,也可以用于Application、Swing程序中。
规范不同:Filter是在Servlet规范中定义的,是Servlet容器支持的。而拦截器是在Spring容器内的,是Spring框架支持的。
使用的资源不同:同其他的代码块一样,拦截器也是一个Spring的组件,归Spring管理,配置在Spring文件中,因此能使用Spring里的任何资源、对象,例如Service对象、数据源、事务管理等,通过IoC注入到拦截器即可;而Filter则不能。
深度不同:Filter在只在Servlet前后起作用。而拦截器能够深入到方法前后、异常抛出前后等,因此拦截器的使用具有更大的弹性。所以在Spring构架的程序中,要优先使用拦截器。

 

实际上Filter和Servlet极其相似,区别只是Filter不能直接对用户生成响应。实际上Filter里doFilter()方法里的代码就是从多个Servlet的service()方法里抽取的通用代码,通过使用Filter可以实现更好的复用。 

filter是一个可以复用的代码片段,可以用来转换HTTP请求、响应和头信息。Filter不像Servlet,它不能产生一个请求或者响 应,它只是修改对某一资源的请求,或者修改从某一的响应。  

JSR中说明的是,按照多个匹配的Filter,是按照其在web.xml中配置的顺序 来执行的。 
所以这也就是,把自己的Filter或者其他的Filter(比如UrlRewrite的Filter)放在Struts的 DispatcherFilter的前面的原因。因为,它们需要在请求被Struts2框架处理之前,做一些前置的工作。 
当Filter被调用,并且进入了Struts2的DispatcherFilter中 后,Struts2会按照在Action中配置的Interceptor Stack中的Interceptor的顺序,来调用Interceptor。
 

3.servlet、filter、interceptor的执行顺序


f84cb2fe-e9bc-30f9-923a-260e77ae221e
    Filter代码:

Java代码  收藏代码

  1. @Override  
  2.     public void doFilter(ServletRequest servletrequest,  
  3.             ServletResponse servletresponse, FilterChain filterchain)  
  4.             throws IOException, ServletException {  
  5.         System.out.println(“in  filter 1.”);  
  6.         filterchain.doFilter(servletrequest, servletresponse);  
  7.         System.out.println(“outing filter 1”);  
  8.     }  

 

 

   interceptor代码:
    @Override

Java代码  收藏代码

  1. public String intercept(ActionInvocation actioninvocation) throws Exception {  
  2.     System.out.println(“in logininterceptor”);  
  3.     String result=actioninvocation.invoke();  
  4.     System.out.println(“outing logininterceptor”);  
  5.     return result;  
  6. }  

 
    action代码:

Java代码  收藏代码

  1. @Override    
  2.    public String execute() throws Exception {    
  3.        System.out.println(“in loginaciton”);  
  4.        ActionContext context=ActionContext.getContext();  
  5.        Map<String, Object> session=context.getSession();   
  6.        session.put(“userName”, userName);    
  7.          
  8.       /* HttpServletRequest request = ServletActionContext. getRequest(); 
  9.        HttpSession session = request.getSession(); 
  10.        session.putValue(“userName”, userName);*/  
  11.        System.out.println(“outing loginaciton”);  
  12.        return SUCCESS;    
  13.    }   

 
      
   jsp代码:

Html代码  收藏代码

  1.  <script type=“text/javascript”>     
Html代码  收藏代码

  1. function submitForm(){  
  2.       document.getElementById(“form1”).submit();   
  3.    }  
  4. </script>  
  5.   
  6.  </head>  
  7.    
  8.  <body>  
  9.    This is Login page. <br>  
  10.    <form action=“<%=path %>/login2.action” method=“post” id=“form1” name=“form1”>  
  11.       UserName:<input type=“text” id=“userName” name=“userName”/><input type=“button” value=“submit” onclick=“submitForm()” id=“submit1” />  
  12.    </form>  
  13.  </body>  

 


   struts.xml

Xml代码  收藏代码

  1.  <struts>  
Xml代码  收藏代码

  1. <package name=“default” extends=“struts-default” namespace=“/”>    
  2.            
  3.          <interceptors>  
  4.             <interceptor name=“MyInterceptor” class=“Login.LoginInterceptor”></interceptor>  
  5.                 <interceptor-stack name=“myInterceptorStack”>  
  6.                     <interceptor-ref name=“MyInterceptor”/>  
  7.                     <interceptor-ref name=“defaultStack”/>  
  8.                 </interceptor-stack>  
  9.         </interceptors>  
  10.            
  11.             <action name=“login2” class=“Login.LoginAction”>    
  12.                 <result name=“success”>    
  13.                    /Login/success.jsp    
  14.                 </result>  
  15.                 <interceptor-ref name=“myInterceptorStack”></interceptor-ref>  
  16.             </action>    
  17.    
  18.         </package>  
  19.     </struts>  

 
    
console:
in  filter 1.
in logininterceptor
in loginaciton
outing loginaciton
outing logininterceptor
outing filter 1

 

3.servlet、filter的执行顺序

servlet代码:

Java代码  收藏代码

  1. public void init() throws ServletException {   
  2.     System.out.println(“servlet初始化”);  
  3.   }   

  

Java代码  收藏代码

  1. public void doPost(HttpServletRequest request, HttpServletResponse response)          
Java代码  收藏代码

  1. throws ServletException, IOException {   
  2.       System.out.println(“in servlet”);  
  3.     response.setContentType(“text/html”);   
  4.     PrintWriter out = response.getWriter();   
  5.     out   
  6.         .println(“<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01 Transitional//EN”>”);   
  7.     out.println(“<HTML>”);   
  8.     out.println(”    <HEAD><TITLE>A Servlet</TITLE></HEAD>”);   
  9.     out.println(”    <BODY>”);   
  10.     out.print(”        This is “);   
  11.     out.print(this.getClass());   
  12.     out.println(“, using the POST method”);        
  13.        
  14.     out.println(“<br>”);   
  15.     String x = request.getParameter(“x”);   
  16.     String y = request.getParameter(“y”);   
  17.     out.println(“x=”+x);   
  18.     out.println(“<br>”);   
  19.     out.println(“y=”+y);   
  20.     out.println(“<br>”);   
  21.        
  22.     out.println(”    </BODY>”);   
  23.     out.println(“</HTML>”);   
  24.     out.flush();   
  25.     out.close();   
  26.     System.out.println(“outing servlet”);  
  27.   }   

 

Java代码  收藏代码

  1. public void destroy(){        
Java代码  收藏代码

  1. System.out.println(“servlet销毁”);  
  2.         super.destroy();  
  3.     }  

 console:

servlet初始化

in  filter 1.

in servlet

before HttpServletRequest

after HttpServletRequest

outing servlet

outing filter 1

当tomcat容器停止的时候,输出:servlet销毁

转自:http://listenup.iteye.com/blog/1559553

4月 292014
 

下面的文章对spring配置中bean的id与name区别写的很清楚,分享下!


在BeanFactory的配置中,<bean>是我们最常见的配置项,它有两个最常见的属性,即id和name,最近研究了一下,发现这两个属性还挺好玩的,特整理出来和大家一起分享。 

  1.id属性命名必须满足XML的命名规范,因为id其实是XML中就做了限定的。总结起来就相当于一个Java变量的命名:不能以数字,符号打头,不能有空格,如123,?ad,”ab “等都是不规范的,Spring在初始化时就会报错,诸如: 
  

Java代码  收藏代码

  1. org.xml.sax.SAXParseException: Attribute value “?ab” of type ID must be a name.  

  

  2.name属性则没有这些限定,你可以使用几乎任何的名称,如?ab,123等,但不能带空格,如”a b”,” abc”,,这时,虽然初始化时不会报错,但在getBean()则会报出诸如以下的错误: 
 

Java代码  收藏代码

  1. org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named ‘a b’ is defined  

  3.配置文件中不允许出现两个id相同的<bean>,否则在初始化时即会报错,如: 
 

Java代码  收藏代码

  1. org.xml.sax.SAXParseException: Attribute value “aa” of type ID must be unique within the document.  

  4.但配置文件中允许出现两个name相同的<bean>,在用getBean()返回实例时,后面一个Bean被返回,应该是前面那个<bean>被后面同名的   <bean>覆盖了。有鉴于此,为了避免不经意的同名覆盖的现象,尽量用id属性而不要用name属性。 

  5.name属性可以用,隔开指定多个名字,如<bean name=”b1,b2,b3″>,相当于多个别名,这时通过getBean(“a1”) getBean(“a2”) getBean(“a3”)返回的都是同一个实例(假设是singleton的情况) 
  
   6.如果id和name都没有指定,则用类全名作为name,如<bean class=”com.stamen.BeanLifeCycleImpl”>,则你可以通过 
   getBean(“com.stamen.BeanLifeCycleImpl”)返回该实例。 

  7.如果存在多个id和name都没有指定,且实例类都一样的<bean>,如: 
  

Java代码  收藏代码

  1. <bean class=“com.stamen.BeanLifeCycleImpl”/>  
  2.    <bean class=“com.stamen.BeanLifeCycleImpl”/>  
  3.    <bean class=“com.stamen.BeanLifeCycleImpl”/>  

   则第一个bean通过getBean(“com.stamen.BeanLifeCycleImpl”)获得, 
     第二个bean通过getBean(“com.stamen.BeanLifeCycleImpl#1”)获得, 
     第三个bean通过getBean(“com.stamen.BeanLifeCycleImpl#2”)获得,以此类推。 
  
  [小结] 
    当然,这些都是奇技淫巧,不足以去实践,通过id指定唯一名称才是阳光大道,其他仅作为一笑而过的见闻罢了。 

  

转自:http://stamen.iteye.com/blog/24525