yxhxj2006

常用链接

统计

最新评论

2012年6月30日 #

jQuery 插件autocomplete 应用

项目中有时会用到自动补全查询,就像Google搜索框、淘宝商品搜索功能,输入汉字或字母,则以该汉字或字母开头的相关条目会显示出来供用户选择, autocomplete插件就是完成这样的功能。

  autocomplete官网 : http://bassistance.de/jquery-plugins/jquery-plugin-autocomplete/ (可下载jQuery autocomplete插件)。

  淘宝商品搜索功能 效果:

  下面来使用 autocomplete插件来实现类似效果。

1. 创建 AjaxPage.aspx 页面,在其中定义 WebMethod 方法来返回 搜索页面需要的输入框所有提示条目。 后台代码如下:

复制代码
 1 using System.Collections.Generic;
2 using System.IO;
3 using System.Runtime.Serialization.Json;
4 using System.Web.Services;
5
6 public partial class AjaxPage : System.Web.UI.Page
7 {
8 [WebMethod]
9 public static string GetAllHints()
10 {
11 Dictionary<string, string> data = new Dictionary<string, string>();
12 data.Add("苹果4代iphone正品", "21782");
13 data.Add("苹果4代 手机套", "238061");
14 data.Add("苹果4", "838360");
15 data.Add("苹果皮", "242721");
16 data.Add("苹果笔记本", "63348");
17 data.Add("苹果4s", "24030");
18 data.Add("戴尔笔记本", "110105");
19 data.Add("戴尔手机", "18870");
20 data.Add("戴尔键盘", "30367");
21
22 DataContractJsonSerializer serializer = new DataContractJsonSerializer(data.GetType());
23
24 using (MemoryStream ms = new MemoryStream())
25 {
26 serializer.WriteObject(ms, data);
27 return System.Text.Encoding.UTF8.GetString(ms.ToArray());
28 }
29 }
30 }
复制代码

  注:该方法返回的数据格式为json字符串。

2. 创建搜索页面 Index.aspx, 前台代码如下:

复制代码
 1 <%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Index.aspx.cs" Inherits="_Default" %>
2
3 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
4
5 <html xmlns="http://www.w3.org/1999/xhtml">
6 <head runat="server">
7 <title></title>
8 <link rel="Stylesheet" href="Styles/jquery.autocomplete.css" />
9 <script type="text/javascript" src="Scripts/jquery-1.4.1.js"></script>
10 <script type="text/javascript" src="Scripts/jquery.autocomplete.js"></script>
11 <script type="text/javascript">
12 var v = 1;
13 $(document).ready(function () {
14 $.ajax({
15 type: "POST",
16 contentType: "application/json",
17 url: "AjaxPage.aspx/GetAllHints",
18 data: "{}",
19 dataType: "json",
20 success: function (msg) {
21 var datas = eval('(' + msg.d + ')');
22 $("#txtIput").autocomplete(datas, {
23 formatItem: function (row, i, max) {
24 return "<table width='400px'><tr><td align='left'>" + row.Key + "</td><td align='right'><font style='color: #009933; font-family: 黑体; font-style: italic'>约" + row.Value + "个宝贝</font>&nbsp;&nbsp;</td></tr></table>";
25 },
26 formatMatch: function(row, i, max){
27 return row.Key;
28 }
29 });
30 }
31 });
32 });
33 </script>
34 </head>
35 <body>
36 <form id="form1" runat="server">
37 <div>
38 <center>
39 <asp:TextBox ID="txtIput" runat="server" Width="400px"></asp:TextBox>
40 </center>
41 </div>
42 </form>
43 </body>
44 </html>
复制代码

  实现效果如下:

3. autocomplete 参数说明

* minChars (Number)
    在触发autoComplete前用户至少需要输入的字符数.Default: 1,如果设为0,在输入框内双击或者删除输入框内内容时显示列表
* width (Number)
    指定下拉框的宽度. Default: input元素的宽度
* max (Number)
    autoComplete下拉显示项目的个数.Default: 10
* delay (Number)
    击键后激活autoComplete的延迟时间(单位毫秒).Default: 远程为400 本地10
* autoFill (Boolean)
    要不要在用户选择时自动将用户当前鼠标所在的值填入到input框. Default: false
* mustMatch (Booolean)
    如果设置为true,autoComplete只会允许匹配的结果出现在输入框,所有当用户输入的是非法字符时将会得不到下拉框.Default: false
* matchContains (Boolean)
    决定比较时是否要在字符串内部查看匹配,如ba是否与foo bar中的ba匹配.使用缓存时比较重要.不要和autofill混用.Default: false
* selectFirst (Boolean)
    如果设置成true,在用户键入tab或return键时autoComplete下拉列表的第一个值将被自动选择,尽管它没被手工选中(用键盘或鼠标).当然如果用户选中某个项目,那么就用用户选中的值. Default: true
* cacheLength (Number)
    缓存的长度.即对从数据库中取到的结果集要缓存多少条记录.设成1为不缓存.Default: 10
* matchSubset (Boolean)
    autoComplete可不可以使用对服务器查询的缓存,如果缓存对foo的查询结果,那么如果用户输入foo就不需要再进行检索了,直接使用缓存.通常是打开这个选项以减轻服务器的负担以提高性能.只会在缓存长度大于1时有效.Default: true
* matchCase (Boolean)
    比较是否开启大小写敏感开关.使用缓存时比较重要.如果你理解上一个选项,这个也就不难理解,就好比foot要不要到FOO的缓存中去找.Default: false
* multiple (Boolean)
    是否允许输入多个值即多次使用autoComplete以输入多个值. Default: false
* multipleSeparator (String)
    如果是多选时,用来分开各个选择的字符. Default: ","
* scroll (Boolean)
    当结果集大于默认高度时是否使用卷轴显示 Default: true
* scrollHeight (Number)
    自动完成提示的卷轴高度用像素大小表示 Default: 180  
* formatItem (Function)
    为每个要显示的项目使用高级标签.即对结果中的每一行都会调用这个函数,返回值将用LI元素包含显示在下拉列表中. Autocompleter会提供三个参数(row, i, max): 返回的结果数组, 当前处理的行数(即第几个项目,是从1开始的自然数), 当前结果数组元素的个数即项目的个数. Default: none, 表示不指定自定义的处理函数,这样下拉列表中的每一行只包含一个值.
* formatResult (Function)
    和formatItem类似,但可以将将要输入到input文本框内的值进行格式化.同样有三个参数,和formatItem一样.Default: none,表示要么是只有数据,要么是使用formatItem提供的值.
* formatMatch (Function)
    对每一行数据使用此函数格式化需要查询的数据格式. 返回值是给内部搜索算法使用的. 参数值row
* extraParams (Object)
    为后台(一般是服务端的脚本)提供更多的参数.和通常的作法一样是使用一个键值对对象.如果传过去的值是{ bar:4 },将会被autocompleter解析成my_autocomplete_backend.php?q=foo&bar=4 (假设当前用户输入了foo). Default: {}
* result (handler)
    此事件会在用户选中某一项后触发,参数为:
    event: 事件对象. event.type为result.
    data: 选中的数据行.
    formatted:formatResult函数返回的值
    例如:
    $("#singleBirdRemote").result(function(event, data, formatted) {
        //如选择后给其他控件赋值,触发别的事件等等
    });

 

posted @ 2016-06-17 17:54 奋斗成就男人 阅读(263) | 评论 (0)编辑 收藏

防止重复登录请求

过页头生成Token,进行请求验证,解决Ajax请求安全问题。目前为止我做的最多的防止ajax请求攻击的就是添加验证码、添加随机Token,限制同一请求在规定时间内的最大请求数。

下面重点说说添加随机Token限制:
token是为了防止表单重复提交,token 原理大致为:

1:显示表单的那个 action 中使用 createToken() 生成一个随机的 token值,并存放在服务端(session或者cache中),并且传递一份到页面中

2:表单页面使用一个隐藏表单域获取后端传过来的 token值,该表单页面提交时会将此 token 值一同提交到后端

3:在表单页面提交到的 actioin 中使用 validateToken() 将服务端与表单隐藏域中的 token 值进行对比,如果服务端存在 token值并且与表单提交过来的值相等,证明是第一次提交。

4:每次校验过后服务端的 token 值会立即被清除,所以当用户重复提交时,后面的提交校验都再也无法通过。从而实现了防止重复提交的功能,validateToken 是在 synchronized 块中执行的保障了多线程下的安全性。

    token 会优先存入 me.setTokenCache(ITokenCache) 指定的 TokenCache 中,如果未指定则默认使用 session 来存放

但是这种机制是有问题的,比如我是用ajax提交表单,提交完成以后表单页面并不刷新,然后我修改了部分数据以后再次提交页面,那么token还是之前的那个token,后台会以为这个为重复提交不能通过校验,那么请求就不能完成,数据无法得到正确的处理。我认为合理的机制应该是这样的:

1:显示表单的那个 action 中使用 createToken() 生成一个随机的 token值,并且传递一份到页面中

2:表单页面使用一个隐藏表单域获取后端传过来的 token值,该表单页面提交时会将此 token 值一同提交到后端

3:将提交过来的token值放入session或者cache中,然后执行controller中的代码,代码全部执行完以后,再把存入session或cache中的token值删除掉;验证用户是否为重复提交只需要验证提交过来的token是否存在于session或cache中,有则为重复提交,无则为正常提交。

4:该逻辑应该可以写成一个Interceptor,在需要的地方加上,或者直接设为全局拦截器都是可以的,简单,快捷;

posted @ 2015-12-03 16:03 奋斗成就男人 阅读(477) | 评论 (0)编辑 收藏

在Java中直接调用js代码

JDK1.6版添加了新的ScriptEngine类,允许用户直接执行js代码。

在Java中直接调用js代码

不能调用浏览器中定义的js函数,会抛出异常提示ReferenceError: “alert” is not defined。

 
package com.sinaapp.manjushri; 
import javax.script.ScriptEngine; 
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;   /**  * 直接调用js代码  */
public class ScriptEngineTest {    
public static void main(String[] args) { 
  ScriptEngineManager manager = new ScriptEngineManager();
  ScriptEngine engine = manager.getEngineByName("javascript");
     try{                engine.eval("var a=3; var b=4;print (a+b);");           // engine.eval("alert(\"js alert\");");    // 不能调用浏览器中定义的js函数 // 错误,会抛出alert引用不存在的异常
 }catch(ScriptException e){   e.printStackTrace();  }  }    }

输出结果:7

在Java中绑定js变量

在调用engine.get(key);时,如果key没有定义,则返回null

 
package com.sinaapp.manjushri;     import javax.script.Bindings;   import javax.script.ScriptContext;   import javax.script.ScriptEngine;   import javax.script.ScriptEngineManager;   import javax.script.ScriptException;     public class ScriptEngineTest2 {    public static void main(String[] args) {    ScriptEngineManager manager = new ScriptEngineManager();    ScriptEngine engine = manager.getEngineByName("javascript");    engine.put("a", 4);    engine.put("b", 3);    Bindings bindings = engine.getBindings(ScriptContext.ENGINE_SCOPE);   try {                          // 只能为Double,使用Float和Integer会抛出异常      Double result = (Double) engine.eval("a+b");         System.out.println("result = " + result);     engine.eval("c=a+b");      Double c = (Double)engine.get("c");      System.out.println("c = " + c);         } catch (ScriptException e) {     e.printStackTrace();         }      }   }

输出:
result = 7.0
c = 7.0

在Java中调用js文件中的function,传入调用参数,并获取返回值

js文件中的merge函数将两个参数a,b相加,并返回c。

 
// expression.js 
function merge(a, b) { 
 c = a * b; 
 return c; 
}

在Java代码中读取js文件,并参数两个参数,然后回去返回值。

 
package com.sinaapp.manjushri;     import java.io.FileReader;    import javax.script.Invocable;   import javax.script.ScriptEngine;   import javax.script.ScriptEngineManager;    /**  * Java调用并执行js文件,传递参数,并活动返回值  *   * @author manjushri  */   public class ScriptEngineTest {      public static void main(String[] args) throws Exception {    ScriptEngineManager manager = new ScriptEngineManager();    ScriptEngine engine = manager.getEngineByName("javascript");       String jsFileName = "expression.js";   // 读取js文件     FileReader reader = new FileReader(jsFileName);   // 执行指定脚本    engine.eval(reader);     if(engine instanceof Invocable) {     Invocable invoke = (Invocable)engine;    // 调用merge方法,并传入两个参数      // c = merge(2, 3);      Double c = (Double)invoke.invokeFunction("merge", 2, 3);      System.out.println("c = " + c);    }     reader.close();      } }

输出结果:
c = 5.0


java调用脚本语言笔记(jython,jruby,groovy)

 有两种方法
1.java se 6以后实现了jsr 223规范
java代码:

[java]
  1. ScriptEngineManager factory = new ScriptEngineManager();  
  2. ScriptEngineManager scriptEngine = factory.getEngineByName("javascript");//或者"js"  
  3. scriptEngine.eval(code);//执行一段脚本,code是js代码  


 很方便调用脚本

2.可以使用脚本语方本身提供的与java的集成手段

jython集成
使用jsr223:
前提下载jython的包,已实现jsr223
(建议在官网上下载,在安装目录下有jython.jar,http://repo2.maven.org/maven2/org/python/jython/2.5.0/ 这里也有,但是这个包里没有jsr223的实现,看包下存不存在org.python.jsr223)

[java]
  1. ScriptEngineManager factory = new ScriptEngineManager();  
  2. ScriptEngineManager scriptEngine = factory.getEngineByName("python");//或者"jython"  
  3. scriptEngine.eval(code);  


使用PythonInterpreter,可以调用exec(String code)方法:

[java]
  1. PythonInterpreter interpreter = new PythonInterpreter();  
  2. interpreter.exec(code);  

访问数据库
使用jdbc:

[python] 
  1. from oracle.jdbc.driver import OracleDriver  
  2. from java.sql import DriverManager  
  3.   
  4. username = 'hr'  
  5. password = '123456'  
  6. url = 'jdbc:oracle:thin:@localhost:1521:XE'  
  7. driver = OracleDriver()  
  8. DriverManager.registerDriver(driver)  
  9. conn = DriverManager.getConnection(url, username, password)  
  10. stmt = conn.createStatement()  
  11. sql = "select salary from EMPLOYEES t where t.salary<2300"  
  12. rs = stmt.executeQuery(sql)  
  13. while (rs.next()):  
  14.  print rs.getInt('salary')  
  15. rs.close()  
  16. stmt.close()  


 结果:
2200
2100
2200

使用zxJDBC :

[python] 
  1. from com.ziclix.python.sql import zxJDBC  
  2.   
  3. url = 'jdbc:oracle:thin:@localhost:1521:XE'  
  4. username = 'hr'  
  5. password = '123456'  
  6. driverName = 'oracle.jdbc.driver.OracleDriver'  
  7. mysqlConn = zxJDBC.connect(url,username, password,driverName)  
  8. cursor = mysqlConn.cursor()       
  9. cursor.execute("select last_name from EMPLOYEES t where t.salary<2300");  
  10. #print cursor.fetchone()  
  11. list = cursor.fetchall()  
  12. for record in list:  
  13.     print "name:"+record[0]  
  14. #print cursor.description[0]  
  15. #print cursor.description[1]  


 结果:
name:麦克
name:Olson
name:Philtanker

从数据库中查出的中文内容正常的。
而在代码里面的中文全部是乱码或抛异常,未解决。

与jruby集成
使用jsr223:Java代码

[java]
  1. ScriptEngineManager factory = new ScriptEngineManager();  
  2. ScriptEngineManager scriptEngine = factory.getEngineByName("jruby");//或者"ruby"  
  3. scriptEngine.eval(code);  

 访问数据库

Ruby代码

[ruby] 
  1. require 'java'  
  2.   
  3. module JavaLang  
  4.   include_package "java.lang"  
  5. end  
  6.   
  7. module JavaSql  
  8.   include_package 'java.sql'  
  9. end  
  10.   
  11. begin  
  12.  username = 'hr'  
  13.  password = '123456'  
  14.  url = 'jdbc:oracle:thin:@localhost:1521:XE'  
  15.  driverName = 'oracle.jdbc.driver.OracleDriver'  
  16.  JavaLang::Class.forName(driverName).newInstance  
  17.  conn = JavaSql::DriverManager.getConnection(url, username, password)  
  18.  stmt = conn.createStatement  
  19.  sql = "select last_name from EMPLOYEES t where t.salary<2300"  
  20.  rs = stmt.executeQuery(sql)  
  21.  while (rs.next) do  
  22.   puts "名字:"+rs.getString("last_name")  
  23.  end  
  24.  rs.close  
  25.  stmt.close  
  26.  conn.close()  
  27. rescue JavaLang::ClassNotFoundException  
  28.  puts "ClassNotFoundException"  
  29. rescue JavaSql::SQLException  
  30.  puts "SQLException"  
  31. end  


 

 结果:
名字:楹﹀厠
名字:Olson
名字:Philtanker

 

从数据库中查出的中文内容为乱码的。
而在代码里面的中文正常。

 

与groovy集成
使用jsr223:

Java代码

[java] 
  1. ScriptEngineManager factory = new ScriptEngineManager();  
  2. ScriptEngineManager scriptEngine = factory.getEngineByName("groovy");//或者"Groovy"  
  3. scriptEngine.eval(code);  


 使用GroovyShell:

Java代码

[java] 
  1. GroovyShell shell = new GroovyShell();  
  2. Script script = shell.parse(code);  
  3. Object result = script.run();  


访问数据库

Groovy代码

 

  1. import groovy.sql.Sql  
  2.   
  3. def username = 'hr'  
  4. def password = '123456'  
  5. def url = 'jdbc:oracle:thin:@localhost:1521:XE'  
  6. def driverName = 'oracle.jdbc.driver.OracleDriver'  
  7. def sql = Sql.newInstance(url, username, password, driverName)  
  8.   
  9. sql.eachRow("select last_name from EMPLOYEES t where t.salary<2300") {  
  10.  println "名字:${it.last_name}"  
  11. }  

结果:
名字:麦克
名字:Olson
名字:Philtanker

 

在使用groovy过程中碰到了一个异常
Exception in thread "main" java.lang.VerifyError: (class: groovy/runtime/metaclass/java/util/ArrayListMetaClass, method: super$2$invokeMethod signature: (Ljava/lang/Class;Ljava/lang/Object;Ljava/lang/String;[Ljava/lang/Object;ZZ)Ljava/lang/Object;) Illegal use of nonvirtual function call
这个异常解决花了很长时间
是因为在原来项目中存在json-lib-2.1.jar(有可能名称为json-lib-2.1-jdk15.jar),这个包是用来处理json的,与groovy1.7.5存在冲突,更新为json-lib-2.3.jar即可
(json-lib里有一些groovy运行时处理的内容)

posted @ 2015-11-19 00:25 奋斗成就男人 阅读(2885) | 评论 (0)编辑 收藏

Java导入证书的问题(PKIX:unable to find valid certification path to requested target 的问题)

这两天Java服务器上忽然遇到这样的异常:

avax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

问题的根本是:

缺少安全证书时出现的异常。

解决问题方法:

将你要访问的webservice/url....的安全认证证书导入到客户端即可。


以下是获取安全证书的一种方法,通过以下程序获取安全证书:

/*
 * Copyright 2006 Sun Microsystems, Inc.  All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
*/

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.security.KeyStore;
import java.security.MessageDigest;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;

public class InstallCert {

    public static void main(String[] args) throws Exception {
        String host;
        int port;
        char[] passphrase;
        if ((args.length == 1) || (args.length == 2)) {
            String[] c = args[0].split(":");
            host = c[0];
            port = (c.length == 1) ? 443 : Integer.parseInt(c[1]);
            String p = (args.length == 1) ? "changeit" : args[1];
            passphrase = p.toCharArray();
        } else {
            System.out
                    .println("Usage: java InstallCert <host>[:port] [passphrase]");
            return;
        }

        File file = new File("jssecacerts");
        if (file.isFile() == false) {
            char SEP = File.separatorChar;
            File dir = new File(System.getProperty("java.home") + SEP + "lib"
                    + SEP + "security");
            file = new File(dir, "jssecacerts");
            if (file.isFile() == false) {
                file = new File(dir, "cacerts");
            }
        }
        System.out.println("Loading KeyStore " + file + "");
        InputStream in = new FileInputStream(file);
        KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
        ks.load(in, passphrase);
        in.close();

        SSLContext context = SSLContext.getInstance("TLS");
        TrustManagerFactory tmf = TrustManagerFactory
                .getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(ks);
        X509TrustManager defaultTrustManager = (X509TrustManager) tmf
                .getTrustManagers()[0];
        SavingTrustManager tm = new SavingTrustManager(defaultTrustManager);
        context.init(nullnew TrustManager[] { tm }, null);
        SSLSocketFactory factory = context.getSocketFactory();

        System.out
                .println("Opening connection to " + host + ":" + port + "");
        SSLSocket socket = (SSLSocket) factory.createSocket(host, port);
        socket.setSoTimeout(10000);
        try {
            System.out.println("Starting SSL handshake");
            socket.startHandshake();
            socket.close();
            System.out.println();
            System.out.println("No errors, certificate is already trusted");
        } catch (SSLException e) {
            System.out.println();
            e.printStackTrace(System.out);
        }

        X509Certificate[] chain = tm.chain;
        if (chain == null) {
            System.out.println("Could not obtain server certificate chain");
            return;
        }

        BufferedReader reader = new BufferedReader(new InputStreamReader(
                System.in));

        System.out.println();
        System.out.println("Server sent " + chain.length + " certificate(s):");
        System.out.println();
        MessageDigest sha1 = MessageDigest.getInstance("SHA1");
        MessageDigest md5 = MessageDigest.getInstance("MD5");
        for (int i = 0; i < chain.length; i++) {
            X509Certificate cert = chain[i];
            System.out.println(" " + (i + 1) + " Subject "
                    + cert.getSubjectDN());
            System.out.println("   Issuer  " + cert.getIssuerDN());
            sha1.update(cert.getEncoded());
            System.out.println("   sha1    " + toHexString(sha1.digest()));
            md5.update(cert.getEncoded());
            System.out.println("   md5     " + toHexString(md5.digest()));
            System.out.println();
        }

        System.out
                .println("Enter certificate to add to trusted keystore or 'q' to quit: [1]");
        String line = reader.readLine().trim();
        int k;
        try {
            k = (line.length() == 0) ? 0 : Integer.parseInt(line) - 1;
        } catch (NumberFormatException e) {
            System.out.println("KeyStore not changed");
            return;
        }

        X509Certificate cert = chain[k];
        String alias = host + "-" + (k + 1);
        ks.setCertificateEntry(alias, cert);

        OutputStream out = new FileOutputStream("jssecacerts");
        ks.store(out, passphrase);
        out.close();

        System.out.println();
        System.out.println(cert);
        System.out.println();
        System.out
                .println("Added certificate to keystore 'jssecacerts' using alias '"
                        + alias + "'");
    }

    private static final char[] HEXDIGITS = "0123456789abcdef".toCharArray();

    private static String toHexString(byte[] bytes) {
        StringBuilder sb = new StringBuilder(bytes.length * 3);
        for (int b : bytes) {
            b &= 0xff;
            sb.append(HEXDIGITS[b >> 4]);
            sb.append(HEXDIGITS[b & 15]);
            sb.append(' ');
        }
        return sb.toString();
    }

    private static class SavingTrustManager implements X509TrustManager {

        private final X509TrustManager tm;
        private X509Certificate[] chain;

        SavingTrustManager(X509TrustManager tm) {
            this.tm = tm;
        }

        public X509Certificate[] getAcceptedIssuers() {
            throw new UnsupportedOperationException();
        }

        public void checkClientTrusted(X509Certificate[] chain, String authType)
                throws CertificateException {
            throw new UnsupportedOperationException();
        }

        public void checkServerTrusted(X509Certificate[] chain, String authType)
                throws CertificateException {
            this.chain = chain;
            tm.checkServerTrusted(chain, authType);
        }
    }

}

编译InstallCert.java,然后执行:java InstallCert hostname,比如:
java InstallCert www.twitter.com
会看到如下信息:

java InstallCert www.twitter.com
Loading KeyStore /usr/java/jdk1.6.0_16/jre/lib/security/cacerts
Opening connection to www.twitter.com:443
Starting SSL handshake

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:150)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1476)
    at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:174)
    at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:168)
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:846)
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:106)
    at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:495)
    at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:433)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:815)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1025)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1038)
    at InstallCert.main(InstallCert.java:63)
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:221)
    at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:145)
    at sun.security.validator.Validator.validate(Validator.java:203)
    at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:172)
    at InstallCert$SavingTrustManager.checkServerTrusted(InstallCert.java:158)
    at com.sun.net.ssl.internal.ssl.JsseX509TrustManager.checkServerTrusted(SSLContextImpl.java:320)
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:839)
     7 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:236)
    at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:194)
    at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:216)
     13 more

Server sent 2 certificate(s):

 1 Subject CN=www.twitter.com, O=example.com, C=US
   Issuer  CN=Certificate Shack, O=example.com, C=US
   sha1    2e 7f 76 9b 52 91 09 2e 5d 8f 6b 61 39 2d 5e 06 e4 d8 e9 c7 
   md5     dd d1 a8 03 d7 6c 4b 11 a7 3d 74 28 89 d0 67 54 

 2 Subject CN=Certificate Shack, O=example.com, C=US
   Issuer  CN=Certificate Shack, O=example.com, C=US
   sha1    fb 58 a7 03 c4 4e 3b 0e e3 2c 40 2f 87 64 13 4d df e1 a1 a6 
   md5     72 a0 95 43 7e 41 88 18 ae 2f 6d 98 01 2c 89 68 

Enter certificate to add to trusted keystore or 'q' to quit: [1]


输入1,回车,然后会在当前的目录下产生一个名为“ssecacerts”的证书。

将证书拷贝到$JAVA_HOME/jre/lib/security目录下,或者通过以下方式:
System.setProperty("javax.net.ssl.trustStore", "你的jssecacerts证书路径");



注意:因为是静态加载,所以要重新启动你的Web Server,证书才能生效。


试了以上的方法,后来发现还不行。最后突然心血来潮:我把Myeclipse关闭,直接启动Tomcat,然后运行,居然就可以了。具体原因没有找到。估计是
我的Myeclipse引用的JDK引用不对。后来就没有具体找原因了。

posted @ 2015-10-30 15:06 奋斗成就男人 阅读(1375) | 评论 (0)编辑 收藏

常用的MySQL语句写法

MySQLSQL语句写法,除了那些基本的之外,还有一些也算比较常用的,这里记录下来,以便以后查找。
    好记性不如烂笔头,这话说的太有道理了,一段时间不写它,还真容易忘记。大家不要纠结这些SQL语句包含的业务或是其它问题,本文只是一篇笔记而已。

    将数据从T1表导入到T2
INSERT INTO T2 (C1,C2) SELECT C1,C2 FROM T1 [WHERE C1 = XX AND C2 = XX ORDER BY C1]

    使用T2表的NAME来更新T1表的NAME
UPDATE T1 AS A, T2 AS B SET A.NAME = B.NAME WHERE A.TID = B.ID

    两表的关联更新
UPDATE T_ROLE_USER AS A,
 (
    SELECT
        ID
    FROM
        T_USER
    WHERE
        DEPARTID IN (
            SELECT
                ID
            FROM
                T_DEPART
            WHERE
                LENGTH(ORG_CODE) = 9
        )
AS B
SET A.ROLEID = '123456'
WHERE
    A.USERID = B.ID

    自己和自己关联更新
UPDATE T_DEPART AS A,
 (
    SELECT
        ID,
        SUBSTRING(ORG_CODE, 16) ORG_CODE
    FROM
        T_DEPART
    WHERE
        LENGTH(ORG_CODE) = 8
    AND PARENT_DEPART_ID IS NOT NULL
AS B
SET A.PARENT_DEPART_ID = B.ID
WHERE
    SUBSTRING(A.ORG_CODE, 16= B.ORG_CODE

    两表关联删除,将删除两表中有关联ID并且T2NAME为空的两表记录
DELETE A,B FROM T1 AS A LEFT JOIN T2 AS B ON A.TID = B.ID WHERE B.NAME IS NULL

    将统计结果插入到表
INSERT INTO SE_STAT_ORG (
    RECORD_DATE,
    ORG_ID,
    ORG_NAME,
    SIGN_CONT_COUNT,
    SIGN_ARRI_CONT_COUNT,
    SIGN_CONT_MONEY,
    SIGN_ARRI_CONT_MONEY,
    TOTAL_ARRI_CONT_COUNT,
    TOTAL_ARRI_MONEY,
    PUBLISH_TOTAL_COUNT,
    PROJECT_COUNT
SELECT
    *
FROM
    (
        SELECT
            '2012-06-09' RECORD_DATE,
            PARENT_ORG_ID,
            PARENT_ORG_NAME,
            SUM(SIGN_CONT_COUNT) SIGN_CONT_COUNT,
            SUM(SIGN_ARRI_CONT_COUNT) SIGN_ARRI_CONT_COUNT,
            SUM(SIGN_CONT_MONEY) SIGN_CONT_MONEY,
            SUM(SIGN_ARRI_CONT_MONEY) SIGN_ARRI_CONT_MONEY,
            SUM(TOTAL_ARRI_CONT_COUNT) TOTAL_ARRI_CONT_COUNT,
            SUM(TOTAL_ARRI_MONEY) TOTAL_ARRI_MONEY,
            SUM(PUBLISH_TOTAL_COUNT) PUBLISH_TOTAL_COUNT,
            SUM(PROJECT_COUNT) PROJECT_COUNT,
        FROM SE_STAT_USER
        WHERE DATE_FORMAT(RECORD_DATE, '%Y-%m-%d'= '2012-06-09'
        GROUP BY PARENT_ORG_ID
    ) M

    三表关联更新
UPDATE SE_STAT_USER A,
 (
    SELECT
        USER_ID,
        SUM(INVEST_ORG_COUNT + FINANCIAL_ORG_COUNT + INTERMEDIARY_ORG_COUNT + ENTERPRISE_COUNT) AS COMMON_COUNT
    FROM SE_STAT_USER
    WHERE DATE_FORMAT(RECORD_DATE, '%Y-%m-%d'= '2012-06-09'
    GROUP BY USER_ID
) B,
 (
    SELECT
        USER_ID,
        SUM(ESTABLISH_COUNT + STOCK_COUNT + MERGER_COUNT + ACHIEVE_COUNT) AS PROJECT_COUNT
    FROM SE_STAT_USER
    WHERE DATE_FORMAT(RECORD_DATE, '%Y-%m-%d'= '2012-06-09'
    GROUP BY USER_ID
) C
SET A.COMMON_COUNT = B.COMMON_COUNT, A.PROJECT_COUNT = C.PROJECT_COUNT
WHERE A.USER_ID = B.USER_ID
AND A.USER_ID = C.USER_ID
AND DATE_FORMAT(A.RECORD_DATE, '%Y-%m-%d'= '2012-06-09'

    带条件的关联更新
UPDATE SE_STAT_USER A,
 (
    SELECT
        P.CHANNEL,
        COUNT(P.CONT_ID) AS CONT_COUNT,
        C.CUST_MGR_ID
    FROM
        (
            SELECT
                CHANNEL,
                CONT_ID
            FROM SK_PROJECT
            WHERE PROJECT_STATUS = 6
            AND DATE_FORMAT(AUDIT_TIME, '%Y-%m-%d'= '2012-06-11'
        ) p
    INNER JOIN SE_CONTRACT C ON P.CONT_ID = C.CONT_ID
    GROUP BY P.CHANNEL, C.CUST_MGR_ID
) B
SET
    A.STOCK_COUNT = CASE WHEN B.CHANNEL = 2 THEN B.CONT_COUNT ELSE 0 END,
    A.ESTABLISH_COUNT = CASE WHEN B.CHANNEL = 3 THEN B.CONT_COUNT ELSE 0 END,
    A.ACHIEVE_COUNT = CASE WHEN B.CHANNEL = 4 THEN B.CONT_COUNT ELSE 0 END
    A.BRAND_COUNT = CASE WHEN B.CHANNEL = 5 THEN B.CONT_COUNT ELSE 0 END,
    A.MERGER_COUNT = CASE WHEN B.CHANNEL = 6 THEN B.CONT_COUNT ELSE 0 END
WHERE
    A.USER_ID = B.CUST_MGR_ID
AND DATE_FORMAT(A.RECORD_DATE, '%Y-%m-%d'= '2012-06-11'

    加索引
ALTER TABLE PROJECT ADD INDEX INDEX_USER_ID (USER_ID),
        ADD INDEX INDEX_PROJECT_STATUS (PROJECT_STATUS);

    删除列
ALTER TABLE PROJECT DROP COLUMN PROJECT_STATUS,
        DROP COLUMN EXPECT_RETURN,DROP COLUMN CURRENCY;

    增加列
ALTER TABLE PROJECT 
        ADD COLUMN DICT_ID INT DEFAULT NULL COMMENT 'xxx' AFTER PROJECT_SITE,
        ADD COLUMN INTRODUCE TEXT DEFAULT NULL COMMENT 'xx' AFTER DICT_ID,
        ADD COLUMN STAGE INT DEFAULT NULL COMMENT 'xx' AFTER ID,
        ADD COLUMN ATTACH_URI VARCHAR(8DEFAULT NULL COMMENT 'xxx' AFTER INTRODUCE;

    修改列,一般用MODIFY修改数据类型,CHANGE修改列名
ALTER TABLE PROJECT CHANGE DICT_ID DICT_ID1 INT NOT NULL,
        MODIFY PROJECT_STATUS TINYINT NOT NULL COMMENT 'xxx';

posted @ 2015-08-09 23:31 奋斗成就男人 阅读(370) | 评论 (0)编辑 收藏

程序员必看的书

做为一名程序员,如果你只顾得写代码,那是不行的,要抽出一下时间来丰富自己的知识,多看看书,在这里我将为程序员们推荐一些不错的书。能够给程序员们带来帮助。

大数据时代

5487a5bd00010d2903120426

《大数据时代》是国外大数据研究的先河之作,本书作者维克托•迈尔•舍恩伯格被誉为"大数据商业应用第一人",拥有在哈佛大学、牛津大学、耶鲁大学和新加坡国立大学等多个互联网研究重镇任教的经历,早在2010年就在《经济学人》上发布了长达14页对大数据应用的前瞻性研究。

维克托•迈尔•舍恩伯格在书中前瞻性地指出,大数据带来的信息风暴正在变革我们的生活、工作和思维,大数据开启了一次重大的时代转型,并用三个部分讲述了大数据时代的思维变革、商业变革和管理变革。

维克托最具洞见之处在于,他明确指出,大数据时代最大的转变就是,放弃对因果关系的渴求,而取而代之关注相关关系。也就是说只要知道"是什么",而不需要知道"为什么"。这就颠覆了千百年来人类的思维惯例,对人类的认知和与世界交流的方式提出了全新的挑战。

 淘宝技术这十年

5487a5c800013dae03030438

《淘宝技术这十年》内容简介:任何网站的发展都不是一蹴而就的。它在发展过程中会遇到各种各样的问题和业务带来的压力。正是这些问题和压力推动着技术的进步和发展,而技术的发展反过来又会促进业务的更大提升。如今淘宝网的流量排名已是全球前15名、国内前3名,其系统服务器也从一台发展到万台以上。

《淘宝技术这十年》从工程师的角度讲述淘宝这个超大规模互联网系统的成长历程,及其所有主动和被动的技术变革的前因后果。书中有幕后故事、产品经验、架构演进、技术启蒙,也有大牛成长、业内八卦、失败案例、励志故事。《淘宝技术这十年》文风流畅,有技术人员特有的幽默感;内容积极正面,有现场感,全部是作者亲身经历。

白帽子讲Web安全

5487a7b90001fa2303030438

《白帽子讲Web安全》内容简介:在互联网时代,数据安全与个人隐私受到了前所未有的挑战,各种新奇的攻击技术层出不穷。如何才能更好地保护我们的数据?《白帽子讲Web安全》将带你走进Web安全的世界,让你了解Web安全的方方面面。黑客不再变得神秘,攻击技术原来我也可以会,小网站主自己也能找到正确的安全道路。大公司是怎么做安全的,为什么要选择这样的方案呢?你能在《白帽子讲Web安全》中找到答案。详细的剖析,让你不仅能"知其然",更能"知其所以然"。

重构:改善既有代码的设计

5487a7c400010cce04000400

《重构:改善既有代码的设计》清晰地揭示了重构的过程,解释了重构的原理和最佳实践方式,并给出了何时以及何地应该开始挖掘代码以求改善。书中给出了70多个可行的重构,每个重构都介绍了一种经过验证的代码变换手法的动机和技术。《重构:改善既有代码的设计》提出的重构准则将帮助你一次一小步地修改你的代码,从而减少了开发过程中的风险。

《重构:改善既有代码的设计》适合软件开发人员、项目管理人员等阅读,也可作为高等院校计算机及相关专业师生的参考读物。

代码整洁之道

5487a7cf000167fd03240408

软件质量,不但依赖于架构及项目管理,而且与代码质量紧密相关。这一点,无论是敏捷开发流派还是传统开发流派,都不得不承认。《代码整洁之道》提出一种观念:代码质量与其整洁度成正比。干净的代码,既在质量上较为可靠,也为后期维护、升级奠定了良好基础。

作为编程领域的佼佼者,《代码整洁之道》作者给出了一系列行之有效的整洁代码操作实践。这些实践在《代码整洁之道》中体现为一条条规则(或称"启示"),并辅以来自现实项目的正、反两面的范例。只要遵循这些规则,就能编写出干净的代码,从而有效提升代码质量。

《代码整洁之道》阅读对象为一切有志于改善代码质量的程序员及技术经理。书中介绍的规则均来自作者多年的实践经验,涵盖从命名到重构的多个编程方面,虽为一"家"之言,然诚有可资借鉴的价值。

设计模式之禅 (第2版)


549ccdfa00018b6503630363

  本书是设计模式领域公认的3本经典著作之一,"极具趣味,容易理解,但讲解又极为严谨和透彻"是本书的写作风格和方法的最大特点。第1版2010年出版,畅销至今,广受好评,是该领域的里程碑著作。深刻解读6大设计原则和28种设计模式的准确定义、应用方法和最佳实践,全方位比较各种同类模式之间的异同,详细讲解将不同的模式组合使用的方法。第2版在第1版的基础上有两方面的改进,一方面结合读者的意见和建议对原有内容中的瑕疵进行了修正和完善,另一方面增加了4种新的设计模式,希望这一版能为广大程序员们奉上一场更加完美的设计模式盛宴!

程序员修炼之道

549cce040001ee3b03150420

  《程序员修炼之道》由一系列的独立的部分组成,涵盖的主题从个人责任、职业发展,直到用于使代码保持灵活、并且易于改编和复用的各种架构技术。利用许多富有娱乐性的奇闻轶事、有思想性的例子以及有趣的类比,全面阐释了软件开发的许多不同方面的最佳实践和重大陷阱。无论你是初学者,是有经验的程序员,还是软件项目经理,本书都适合你阅读。

平台战略:正在席卷全球的商业模式革命

549cce0e00012ad003120426

《平台战略:正在席卷全球的商业模式革命》内容简介:平台商业模式的精髓,在于打造一个完善的、成长潜能强大的"生态圈"。它拥有独树一帜的精密规范和机制系统,能有效激励多方群体之间互动,达成平台企业的愿景。纵观全球许多重新定义产业架构的企业,我们往往就会发现它们成功的关键——建立起良好的"平台生态圈",连接两个以上群体,弯曲、打碎了既有的产业链。

平台生态圈里的一方群体,一旦因为需求增加而壮大,另一方群体的需求也会随之增长。如此一来,一个良性循环机制便建立了,通过此平台交流的各方也会促进对方无限增长。而通过平台模式达到战略目的,包括规模的壮大和生态圈的完善,乃至对抗竞争者,甚至是拆解产业现状、重塑市场格局。

互联网创业启示录

549cce170001475203030438

《互联网创业启示录》是一部互联网公司的创业指南,内容涉及网站创业的现状和机遇、创业公司价值、平台选择、工具和群组、资金的筹集、管理和盈利、社会化媒体环境、行动执行管理、开发人员方法论和工作效率、创始人的角色等方面,既有纲领和指导性理论,又有具体操作方法。书中大量对互联网创业成功人士的访谈介绍,以及创业公司的成功案例,更可以作为初次创业者的良好借鉴。

《互联网创业启示录》主要写给想自己创业的程序员,但同样适合非技术人员,适合网络创业者、大学生创业者、网络营销人员及一切有志创业者。做网络不一定要懂技术,互联网的成功是可以借鉴和延伸的!

程序员健康指南

549cce2600015a5003600369

本书是为程序员量身制作的健康指南,针对头痛、眼部疲劳、背部疼痛和手腕疼痛等常见的问题,简要介绍了其成因、测试方法,并列出了每天的行动计划,从运动、饮食等方面给出详细指导,帮助程序员在不改变工作方式的情况下轻松拥有健康。

本书适合程序员、长期伏案工作的其他人群以及所有关心健康的人士阅读。

结网@改变世界的互联网产品经理

54aa4f680001268603060435

本书以如何创建、发布、推广互联网产品为主线,介绍了互联网产品经理的工作内容以及应对每一部分工作所需的方法和工具。为用户创造价值是产品经理的第一要务,产品经理的工作是围绕用户及具体任务展开的,本书丰富的案例和透彻的分析道出了从发现用户到最终满足用户这一过程背后的玄机。

本书面向现在正在从事及未来将要从事互联网相关工作的创业者和产品经理,也可以作为互联网产品策划人员或相关专业学生的参考书。新版完善了各章节,增加了优雅降级等内容,读者也可从中更深地去感受一名产品经理的感悟。

程序员面试逻辑题解析

54aa4f7800016ca403240408

程序员面试逻辑题解析》共分为3个部分。第一部分从有趣且锻炼头脑的谜题入手,继而给出解题思路和详细答案,更有"热身问题"给大家提供充分的思考空间。第二部分综合了不同类型的谜题,如数独、调度问题及概率题等。神秘的第三部分带领大家不断历险,开动脑筋,解决大量密码及银行账户等方面的问题。几十道简洁的小谜题不仅充分锻炼了我们的思维方式,更为提高面试成功率奠定了基础。

    《程序员面试逻辑题解析》不仅适合程序员阅读,更是谜题爱好者的饕餮盛宴。

程序员,你伤不起

54aa4f8d000171b703060435

本书是作者博客文章的精选集。是作者作为老牌程序员、现在的IT 创业者15 年软件开发生涯的心路历程和经验总结。涉及程序人生、开发经验、职业规划、创业心得。对任何的软件开发者和IT 从业人员都有借鉴价值。作者语言风趣幽默,读起来津津有味。字里行间充满了不屈不挠的码农正能量。

像程序员一样思考

54aa4f9800013e1e03270405

编程的真正挑战不是学习一种语言的语法,而是学习创造性地解决问题,从而构建美妙的应用。《像程序员一样思考》分析了程序员解决问题的方法,并且教授你其他图书所忽略的一种能力,即如何像程序员一样思考。

全书分为8章。第1章通对几个经典的算法问题切入,概括了问题解决的基本技巧和步骤。第2章通过实际编写C++代码来解决几个简单的问题,从而让读者进一步体会到问题解决的思路和应用。第3到7章是书中的主体部分,分别探讨了用数组、指针和动态内存、类、递归和代码复用来解决问题的途径和实际应用。最后,第8章从培养程序员思维的角度,进行了总结和概括,告诉读者如何才能像程序员一样思考。

编写可读代码的艺术

54aa4fbf0001a7c103180417

细节决定成败,思路清晰、言简意赅的代码让程序员一目了然;而格式凌乱、拖沓冗长的代码让程序员一头雾水。除了可以正确运行以外,优秀的代码必须具备良好的可读性,编写的代码要使其他人能在最短的时间内理解才行。本书旨在强调代码对人的友好性和可读性。

本书关注编码的细节,总结了很多提高代码可读性的小技巧,看似都微不足道,但是对于整个软件系统的开发而言,它们与宏观的架构决策、设计思想、指导原则同样重要。编码不仅仅只是一种技术,也是一门艺术,编写可读性高的代码尤其如此。如果你要成为一位优秀的程序员,要想开发出高质量的软件系统,必须从细处着手,做到内外兼修,本书将为你提供有效的指导。

posted @ 2015-06-13 00:03 奋斗成就男人 阅读(407) | 评论 (0)编辑 收藏

Oracle分析函数入门

一、Oracle分析函数入门

分析函数是什么?
分析函数是Oracle专门用于解决复杂报表统计需求的功能强大的函数,它可以在数据中进行分组然后计算基于组的某种统计值,并且每一组的每一行都可以返回一个统计值。

          

分析函数和聚合函数的不同之处是什么?
普通的聚合函数用group by分组,每个分组返回一个统计值,而分析函数采用partition by分组,并且每组每行都可以返回一个统计值。

              

分析函数的形式
分析函数带有一个开窗函数over(),包含三个分析子句:分组(partition by), 排序(order by), 窗口(rows) ,他们的使用形式如下:over(partition by xxx order by yyy rows between zzz)。
注:窗口子句在这里我只说rows方式的窗口,range方式和滑动窗口也不提

    

分析函数例子(在scott用户下模拟)

示例目的:显示各部门员工的工资,并附带显示该部分的最高工资。

复制代码
--显示各部门员工的工资,并附带显示该部分的最高工资。
SELECT E.DEPTNO,
E.EMPNO,
E.ENAME,
E.SAL,
LAST_VALUE(E.SAL)
OVER(PARTITION BY E.DEPTNO
ORDER BY E.SAL ROWS
--unbounded preceding and unbouned following针对当前所有记录的前一条、后一条记录,也就是表中的所有记录
--unbounded:不受控制的,无限的
--preceding:在...之前
--following:在...之后
BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) MAX_SAL
FROM EMP E;
复制代码

运行结果:

               

示例目的:按照deptno分组,然后计算每组值的总和

SELECT EMPNO,
ENAME,
DEPTNO,
SAL,
SUM(SAL) OVER(PARTITION BY DEPTNO ORDER BY ENAME) max_sal
FROM SCOTT.EMP;

运行结果:

     

示例目的:对各部门进行分组,并附带显示第一行至当前行的汇总

复制代码
SELECT EMPNO,
ENAME,
DEPTNO,
SAL,
--注意ROWS BETWEEN unbounded preceding AND current row 是指第一行至当前行的汇总
SUM(SAL) OVER(PARTITION BY DEPTNO
ORDER BY ENAME
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) max_sal
FROM SCOTT.EMP;
复制代码

运行结果:

   

示例目标:当前行至最后一行的汇总

复制代码
SELECT EMPNO,
ENAME,
DEPTNO,
SAL,
--注意ROWS BETWEEN current row AND unbounded following 指当前行到最后一行的汇总
SUM(SAL) OVER(PARTITION BY DEPTNO
ORDER BY ENAME
ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) max_sal
FROM SCOTT.EMP;
复制代码

运行结果:

   

 示例目标:当前行的上一行(rownum-1)到当前行的汇总

复制代码
SELECT EMPNO,
ENAME,
DEPTNO,
SAL,
--注意ROWS BETWEEN 1 preceding AND current row 是指当前行的上一行(rownum-1)到当前行的汇总
SUM(SAL) OVER(PARTITION BY DEPTNO
ORDER BY ENAME ROWS
BETWEEN 1 PRECEDING AND CURRENT ROW) max_sal
FROM SCOTT.EMP;
复制代码

运行结果:

    

示例目标:   当前行的上一行(rownum-1)到当前行的下辆行(rownum+2)的汇总     

复制代码
SELECT EMPNO,
ENAME,
DEPTNO,
SAL,
--注意ROWS BETWEEN 1 preceding AND 1 following 是指当前行的上一行(rownum-1)到当前行的下辆行(rownum+2)的汇总
SUM(SAL) OVER(PARTITION BY DEPTNO
ORDER BY ENAME
ROWS BETWEEN 1 PRECEDING AND 2 FOLLOWING) max_sal
FROM SCOTT.EMP;
复制代码

运行结果:


posted @ 2015-05-13 00:46 奋斗成就男人 阅读(340) | 评论 (0)编辑 收藏

常见分析函数详解

     摘要: 三、常见分析函数详解为了方便进行实践,特将演示表和数据罗列如下:一、创建表create table t( bill_month varchar2(12) , area_code number, net_type varchar(2), local_fare number );      二、插入数据insert i...  阅读全文

posted @ 2015-05-13 00:46 奋斗成就男人 阅读(383) | 评论 (0)编辑 收藏

ORACLE 常用函数

  这个系列我将整理一些日常我们经常使用到的ORACLE函数,鉴于篇幅太长,我大体会按下面分类来整理、汇总这些常用的ORACLE函数,如果有些常用函数没有被整理进来,也希望大家指点一二。

 1: 聚合函数

2: 日期函数
3: 字符串函数
4: 格式化函数
5: 类型转换函数
6: 加密函数
7: 控制流函数
8: 数学函数
9: 系统信息函数
10:分析函数

------------------------------------------聚合函数---------------------------------------------
--1:   AVG(DISTINCT|ALL)

ALL表示对所有的值求平均值,DISTINCT只对不同的值求平均值
SELECT AVG(SAL) FROM SCOTT.EMP;
SELECT AVG(DISTINCT SAL) FROM SCOTT.EMP;
--2:   MAX(DISTINCT|ALL)

求最大值,ALL表示对所有的值求最大值,DISTINCT表示对不同的值求最大值,相同的只取一次

(加不加查询结果一致,不知DISTINCT有什么用途,不同于AVG等聚合函数)
SELECT MAX(DISTINCT SAL) FROM SCOTT.EMP;
SELECT MAX(SAL) FROM SCOTT.EMP
--3:   MIN(DISTINCT|ALL)
求最小值,ALL表示对所有的值求最小值,DISTINCT表示对不同的值求最小值,相同的只取一次
SELECT MIN(SAL) FROM SCOTT.EMP;
SELECT MIN(DISTINCT SAL) FROM SCOTT.EMP;

--4:  STDDEV(distinct|all)
求标准差,ALL表示对所有的值求标准差,DISTINCT表示只对不同的值求标准差
SELECT STDDEV(SAL) FROM SCOTT.EMP;
SELECT STDDEV(DISTINCT SAL) FROM SCOTT.EMP;

--5:   VARIANCE(DISTINCT|ALL)
求协方差  ALL表示对所有的值求协方差,DISTINCT表示只对不同的值求协方差
SELECT VARIANCE(SAL) FROM SCOTT.EMP;
SELECT VARIANCE(DISTINCT SAL) FROM SCOTT.EMP;

--6:  SUM(DISTINCT|ALL)
求和  ALL表示对所有值求和,DISTINCT表示只对不同值求和(相同值只取一次)
SELECT SUM(SAL) FROM SCOTT.EMP;
SELECT SUM(DISTINCT SAL) FROM SCOTT.EMP;


--7:COUNT(DISTINCT|ALL)
求记录、数据个数。 ALL对所有记录,数组做统计, DISTINCT只对不同值统计(相同值只取一次)
SELECT COUNT(SAL) FROM SCOTT.EMP;
SELECT COUNT(DISTINCT SAL) FROM SCOTT.EMP;  
 
----8: MEDIAN
求中位数
SELECT MEDIAN(SAL) FROM SCOTT.EMP;
SELECT MEDIAN(DISTINCT SAL) FROM SCOTT.EMP;  --错误:DISTINCT 选项在此函数中禁用。
----------------------------------------------------------------------------------------------

posted @ 2015-05-13 00:37 奋斗成就男人 阅读(311) | 评论 (0)编辑 收藏

如何判断PHP空间是否支持curl, gzip等功能

在使用PHP时,我们需要将自己写好的php文件上传到已申请的php空间。由于租用或申请的php空间是不允许用户进行配置的,那么对于php的一些功能是否开启,如curl, allow_url_fopen, gzip,就需要提前判断,而不是等写完代码后发现不能使用时,那样改动就大了。

方法/步骤

  1. 其实判断功能是否开启,很简单,我们只需要写一个php文件上传之php空间服务器中。v.php的源代码如图。

    如何判断PHP空间是否支持curl, gzip等功能
  2. 其含义很简单,就是传入一个函数的名字,服务器判断是否存在这个函数,如果存在则表示支持该函数对应的功能,输出“支持”,反之输出“不支持”。将文件上传至php空间中。

    如何判断PHP空间是否支持curl, gzip等功能
  3. 再通过访问空间,地址+v.php?f=+要测试的功能所包括的函数,比如curl功能可以是v.php?f=curl_init,allow_url_fopen功能可以用v.php?f=fopen来测试。

posted @ 2015-04-22 00:04 奋斗成就男人 阅读(269) | 评论 (0)编辑 收藏

从程序员到CTO的Java技术路线图

  在技术方面无论我们怎么学习,总感觉需要提升自已不知道自己处于什么水平了。但如果有清晰的指示图供参考还是非常不错的,这样我们清楚的知道我们大概处于那个阶段和水平。 

 

Java程序员

高级特性

              反射、泛型、注释符、自动装箱和拆箱、枚举类、可变

              参数、可变返回类型、增强循环、静态导入

        核心编程

             IO、多线程、实体类、

             集合类、正则表达式、

             XML和属性文件

             图形编程

             AWT(Java2D/JavaSound/JMF)、Swing、SWT、JFace

        网路编程

            Applet、Socket/TCP/UDP、NIO、RMI、CORBA

       Java语法基础

           类、抽象类、接口、最终类、静态类、匿名类、内部类、异常类、编码规范

      Java开发环境

          JDK、JVM、Eclipse、Linux

Java核心编程技术

Java,设计而又非常精巧的语言。学习Java,须从Java开发环境开始,到Java语法,再到Java的核心API。

        1.Java开发入门:Java开发环境的安装与使用,包括JDK命令、EclipseIDE、Linux下Java程序的开发和部署等。

        2.Java语法基础:基于JDK和Eclipse环境,进行Java核心功能开发,掌握Java面向对象的语法构成,包括类、抽象类、接口、最终类、静态类、匿名类、内部类、异常的编写。

        3.Java核心API:基于JDK提供的类库,掌握三大核心功能:

        A。Java核心编程:包括Java编程的两大核心功能——Java输入/输出流和多线程,以及常用的辅助类库——实体类、集合类、正则表达式、XML和属性文件。

        B。Java图形编程:包括Sun的GUI库AWT(Java2D、JavaSound、JMF)和Swing,IBM和GUI库SWT和Jface;

        C. Java网路编程:Applet组件编程,Socket编程,NIO非阻塞Socket编程、RMI和CORBA分布式开发。

        4.Java高级特性:掌握JDK1.4、JDK5.0、JDK6.0中的Java高级特性,包括反射、泛型、注释,以及java高级特性——自动装箱和拆箱、枚举类、可变参数、可变返回类型、增强循环、静态导入等。

JavaEE初级软件工程师

JSF框架开发技术

       配置文件(页面导航、后台Bean)、JSF组件库(JSF EL语言、HTML标签、事件处理、)、JSF核心库(格式转换、输入验证、国际化)

Javaweb核心开发技术       

       开发环境(Eclipse、Linux)

       三大组件(JSP、JavaBean、Servlet)

       扩展技术(EL、JSTL、Taglib)

网页开发技术

       HTML、XML、CSS、JavaScript、AJAX

       数据库设计技术

       SQL、MySql、Oracle、SQLServer、JDBC

Web服务器(Tomcat/Jetty/Resin/JBossWeb)

JavaWeb核心技术:

        JavaWeb项目开发的全过程可以分解为:

       网页开发+数据库设计——>JavaWeb项目开发,其中,javaWeb由6项基本技术组成:JSP+JavaBean+Servlet+EL+JSTL+Taglib,而JSF正是将这6种技术进行有机结合的技术框架:

JavaEE中级软件工程师

四种经典架构SSH1、SSI1、SSH2、SSI2

        Struts1表现层框架

      入门配置、核心组件、标签库、国际化、数据检验、数据库开发、Sitemesh集成、集成Hibernate/iBATIS

        Struts2表现层框架

               入门配置、核心组件、标签库、国际化、数据校验、Sitemesh集成转换器、拦截器、集成Hibernate/iBATIS

        Spring业务层框架

              入门配置、IoC容器、MVC、标签库、国际化、数据校验、数据库开发

        Hibernate持久层框架

            MySQL、Oracle、SQLServer iBATIS持久层框架

            MySQL、Oracle、SQLServer

Web服务器(Tomcat/Jetty/Resin/JBossWeb)

Java高级软件工程师

javaWeb开源技术与框架

        工作流、

规则引擎

搜索引擎、

缓存引擎 、

        任务调度、

身份认证

        报表服务、

系统测试、

        集群、

负载平衡、

故障转移

JavaWeb分布式开发技术

JTA(Java事物管理)

      JAAS(Java验证和授权服务)

      JNDI(Java命名和目录服务)

      JavaMail(Java邮件服务)

JMS(java信息服务)

WebService(web服务)

JCA(java连接体系)

JMS(java管理体系)

应用服务器(JBossAS/WebLogic/WebSphere)

JavaEE系统架构师

        面向云架构(COA)

            COA、SaaS、网格计算、集群计算、分布式计算、云计算

        面向资源架构(ROA)

            ROA、RESI

        面向web服务架构(SOA)

           WebService、SOA、SCA、ESB、OSGI、EAI

        Java设计模式

          创建式模式:抽象工厂/建造者/工厂方法/原型/单例

          构造型模式:适配器/桥接/组合/装饰/外观/享元/代理

          行为型模式:责任链/命令/解释器/迭代子/中介者/备忘录/观察者/状态/策略/模板方法/访问者

       Java与UML建模

          对象图、用例图、组件图、部署图、序列图、交互图、活动图、正向工程与逆向工程

CTO首席技术官

         发展战略

         技术总监

         团队提升

         团队建设

         项目管理

         产品管理

企业级项目实战(带源码)地址http://zz563143188.iteye.com/blog/1825168


收集五年的开发资料下载地址:  http://pan.baidu.com/share/home?uk=4076915866&view=share

 

 

 

 

 下面的更深入的有兴趣可以了解一下,我的目的不是要大家掌握下面的知识,只是希望扩展自己的思维,摘自牛人的技术博客。

/**************************************************牛人必看*****************************************************************/

 

 

 

系统后台框架:

 

 

前端工程师技能:

 

 

 

B2C电子商务基础系统架构解析
运营B2C日 久,越来越深刻的意识到IT系统对确保规范化业务流转,支撑消费者端的均一服务有着决定性的作用。于是,一直想好好整理下相关的系统架构,怎奈俗务缠身, 一直拖到今日,猛然发现下周娃很可能就要出生,拖无可拖,快马加笔,居然整出来了。本文的重点是理清系统的逻辑关系,详细的功能模块请参见结尾附上的系统 架构图。
首先,聊下对系统逻辑架构的看法;我个人始终坚持认为,系统的开发与演化,前台严格follow消费者的购买流程,后台则盯牢订单流转,牢牢抓住这两条主线,才能高屋建瓴的看清B2C的逻辑链和数据流,更深刻的规划功能模块,从而更有效支撑实际业务的流转。
前台系统包括:商品展示,内容展示,订单确认,支付系统,用户中心四大模块
一,商品展示
按照Ebay的内部分类,任何将商品以单个或批量的方式展示给消费者的功能均应归入此系统。因此,该系统至少包括:
A,站内搜索(搜索提示,搜索规则,搜索成功页,搜索不成功页,相似推荐)
B,导航(频道导航,其他导航如销售排行,广告位,推荐位,文字链,Also buy等)
C,商品分类(品牌分类,品类分类,属性分类如剪裁形式)
D, 登陆页(商品列表页,商品详细页,商品活动页)
这里的访问逻辑是:A /B/C分流消费者去往相对个性化的页面,由登陆页体现商家的核心诉求和价值传递,完成call-to-action的第一步。
二,内容展示
内容展示较为简单,对纯购物品牌而言包括:
A,公告区
B,帮助中心
C,论坛(如需商城与论坛发生交互,则需自行开发,否则可集成discuz做同步登陆即可)
大家都知道,就不多说了。
三,订单确认
订单确认,就是帮助消费者正确提交订单信息的环节,看似简单,实则非常复杂,需要对很多信息逻辑判断和处理,一般由2个部分组成:
A,购物车(购物车浮层,购物车页面,无注册购买)
无注册购买是需要慎用的功能,除非刻意追求用户的短平快下单,如团购/换购,一般不推荐使用,会造成系统异常复杂,开发量也很大。
B,订单提交(返回购物车,收货地址&地址薄,支付方式判断,配送方式,发票,订单标记,实付金额计算等等)
值得一提的是,几乎大多数的促销逻辑运算在这个环节完成,充分考虑各种促销方式之间的互斥与重叠是系统设计的核心,需要充分考虑各种情况,避免出现逻辑漏洞。
四,支付系统
与一般的想象不同,支付系统其实并不简单等于第三方支付工具接入:
A,外部支付系统(支付宝将接口,财付通接口,网银直联端口,信用ka分期端口)
B,内部支付系统(账户余额,积分,礼品卡,优惠券)
支付系统的逻辑设计不但需要考虑到各种极端情况的发生(如一张订单先用礼品卡,再用积分,最后网银支付),还要预留财务做账所需的相关字段,并充分考虑订单取消之后如何回滚各类内部账户。
五,用户中心
用户中心的实质是用户自助功能的dashboard,一般4个部分组成:
A,注册&登陆(快速注册,完整注册,注册有礼,推荐注册,密码找回,主站id登陆,open-id登陆如QQ,新浪微博等)
B,订单中心(历史订单状态,中间状态订单修改,物流追踪)
C,服务中心(各类自助服务如退款申请,退换货申请,建议与投诉等)
D, 信息管理(用户基本信息管理和账户信息管理)
用户中心的价值在于:尽可能引导用户自行获取所需的信息并提交所需的服务,在提升服务准确率,及时性的同时降低对人工成本。
后台系统包括:商品&促销,CRM,订单处理,WMS,采购管理,财务管理,报表管理,系统设置,WA系统9大模块
一, 商品&促销
商品&促销模块的核心在于确保消费者下单之前,前台内容所见即所得
A, 商品管理(品类管理,品牌管理,单品管理)
B, 促销管理(活动管理和自定义活动模板管理)
在上述模块中,最重要的是2个部分:单品管理中的批量产品生成的自动程序和活动管理中“共享与互斥”管理。前者用于大幅提升上新速度,后者避免促销活动失控。
二, CRM
CRM是对B2C核心资源—会员的管理,服务与再营销系统,包括如下部分:
A,会员管理(会员信息的增删改查和到其他系统的链接)
B,用户关怀(条件触发和人工触发相关EDM & 短信 & OB)
C,定向营销(会员分组和营销活动管理)
D, 客服管理(内容非常多,集成所有需前台与后台交互的功能,详情还是看图吧)
E, 呼叫中心(IVR,坐席管理,统计报表,参数传递与窗口嵌入)
值得注意的,EDM和短信通道市面上已经有成熟的外包服务商,一般都会外包;呼叫中心和在线客服自行开发成本太高,特别是呼叫中心系统,业务初期也都是外包的。
三, 订单处理
订单处理是在订单未正式进入仓储部门处理之前,对订单的前置性处理环节。
A,订单录入(电话订购,网上下单,外部团购订单,无金额订单录入如礼品单)
B,订单审核(自动审核和人工审核)
C,RMA处理(RMA申请单和RMA处理单)
RMA的逻辑也异常复杂,需要在效率和成本之间找平衡,确保在不拖垮仓储部门的正常出入库的前提下对消费者端快速有效close工单;对内部则需要控制成本,货损不能超过预算上限。
四, WMS(Warehouse Management system仓库管理系统)
WMS的流程很长,功能模块也很多,大致分为入库管理,库存管理,出库管理和票据管理4个模块四个模块,细细道来就是另外一篇文章了,各位可以参考 我这篇文章:庖丁解牛—B2C仓储内部运作解密(上,中,下)http://blog.sina.com.cn/wangxida0855
五, 采购管理
采购管理的核心是有效跟进采购合同/发票的状态,大货的采购入库/退库,财务结算和在仓库存查询和处理。
A,供应商管理(供应商信息管理,合同发票管理)
B,采购单管理(PO单管理,负PO单管理)
C,库存管理(库存查询,库存占用单,库存变动log)
六, 财务管理
B2C的财务管理,主要是对供应商,渠道和内部费用支出的成本控制。
A,供应商结算
B,渠道结算
C,配送结算
D, 内部结算
说实在的,哥对财务这块也不算很了解,大家将就看看,图片上有明细。
七, 报表管理
报表是B2C业务的宏观表现,理论上说,每个部门的KPI都应该从中找到。
A,搜索报表(站内搜索量查询)
B,销售报表(多个维度销量查询,优惠券使用情况,报表导出)
C,财务报表
D, 客服报表(客服日报和坐席报表)
前者反映与消费者发生的日常交互(包括正常与异常),后者考核客服的工作绩效
E, 仓储物流报表
这几块报表,是业务运作的核心,涉及到公司机密,就不能写的太细了,见谅。
八, 系统设置
这块大家都知道是干嘛的,也就不多说了,分成三块。
A,基础设置(和业务有关的一些字段值)
B,权限设置(不同账号的操作权限和操作记录)
C,其他设置
九, WA系统(Web Analytcis)
网站分析系 统,几乎全是外购,很少有能够自建的,即使自建,最多做几个简单的模块。用于实战的,要么是免费的GA(Google Analytics),要么是昂贵的Omniture。这块的知识,细细说来也是另外一篇文章了,有兴趣的同学可以看我这篇科普文章:揭秘—我所知道的网 站分析(上,下) http://blog.sina.com.cn/wangxida0855
最后,上全系统大图,再感慨一句,B2C系统,真是一个大工程啊。

 

fr  http://blog.sina.com.cn/s/blog_59d6717c0100syh3.html

posted @ 2015-04-11 13:41 奋斗成就男人 阅读(229) | 评论 (0)编辑 收藏

ajax+json+Struts2实现list传递(转载)

     摘要: ajax+json+Struts2实现list传递(转载)一、首先需要下载JSON依赖的jar包。它主要是依赖如下:      json-lib-2.2.2-jdk15      ezmorph-1.0.4       commons-logging-1.0.4&nbs...  阅读全文

posted @ 2015-04-04 01:17 奋斗成就男人 阅读(336) | 评论 (0)编辑 收藏

iBatis简单入门教程

     摘要: Batis 简介:iBatis 是apache 的一个开源项目,一个O/R Mapping 解决方案,iBatis 最大的特点就是小巧,上手很快。如果不需要太多复杂的功能,iBatis 是能够满足你的要求又足够灵活的最简单的解决方案,现在的iBatis 已经改名为Mybatis 了。官网为:http://www.myb...  阅读全文

posted @ 2015-04-04 01:16 奋斗成就男人 阅读(188) | 评论 (0)编辑 收藏

PHP页面跳转代码

第一篇: JavaScript 跳转

方法一:

<script language="javascript">
    window.location= "http://www.baidu.com";
</script>

方法二:

<script language="javascript">
    document.location = "http://www.baidu.com";
</script>

方法三: (带进度条)

<html>
<head>
<meta http-equiv="Content-Language" content="zh-cn">
<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=gb2312">
<title>跳转到baidu.com</title>
</head>
<body>
<form name=loading>
<P align=center><FONT face=Arial color=#0066ff size=2>loading...</FONT>
<INPUT style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-WEIGHT: bolder; PADDING-BOTTOM: 0px; COLOR: #0066ff; BORDER-TOP-style: none; PADDING-TOP: 0px; BORDER-RIGHT-style: none; BORDER-LEFT-style: none; BACKGROUND-COLOR: white; BORDER-BOTTOM-style: none"
size=46 name=chart>
<BR>
<INPUT style="BORDER-RIGHT: medium none; BORDER-TOP: medium none; BORDER-LEFT: medium none; COLOR: #0066ff; BORDER-BOTTOM: medium none;" size=47 name=percent>
<script language="javascript">
var bar=0
var line="||"
var amount="||"
count()
function count(){
    bar=bar+2
    amount =amount + line
    document.loading.chart.value=amount
    document.loading.percent.value=bar+"%"
    if (bar<99){
        setTimeout("count()",100);
    }else{
        window.location = "http://www.baidu.com/";
    }
}
</script>
</P>
</form>
</body>
</html>

第二篇: 页面跳转

<head>
<meta http-equiv="refresh" content="10; url=http://www.baidu.com">
</head>

第三篇: 动态页面跳转

方法一: PHP 跳转

<?php
header("location: http://www.baidu.com");
?>


方法二: ASP 跳转

<%
response.redirect "http://www.baidu.com"
%>

FYI:
<%
Dim ID1
Dim ID2
dim str
ID1 = Request("forumID")
ID2 = Request("threadID")
str="/blog/threadview.asp?forumID="& ID1 &"&threadID=" & ID2
response.redirect str
%>
<%
response.redirect "http://www.baidu.com"
%>

FYI:
<%
Dim ID1
Dim ID2
dim str
ID1 = Request("forumID")
ID2 = Request("threadID")
str="/blog/threadview.asp?forumID="& ID1 &"&threadID=" & ID2
response.redirect str
%>

posted @ 2015-04-01 17:08 奋斗成就男人 阅读(229) | 评论 (0)编辑 收藏

zencart使用smtp发邮件设置

zencart如何设置smtp发邮件,zencart不能发email,发email失败怎么办?zen cart要使用gmail发送邮件,首先要把你的gmail账户开通pop/smtp, 然后再zencart后台设置邮件发送方式,邮箱帐号,密码。 
具体操作方法如: 
进入后台--商店设置--电子邮件,首先选择”电子邮件发送方式“为smtpauth。然后输入你的gamil邮箱地址。 
最后设置

1)首先后台电子邮件 发送方式是:smtpauth
2)smtp帐号邮箱:xxx@gmail.com
3)smtp帐号密码:xxxxxxxx
4)smtp主机:smtp.gmail.com
5)smtp服务器端口:465或者587

注意:国内的邮箱最好使用163邮箱:服务器:smtp.163.com  端口:465/25,其他的邮箱不能发,具体原因暂时不清楚。

如果这样设置是正确的。但是有些主机还是会出现Email Error: SMTP Error: Could not connect to SMTP host.这样的情况 。

这个需要服务器支持。检查下后台-工具-服务器信息里是否有OpenSSL。因为google 传输是ssl://smtp.gmail.com协议。

所以需要服务器支持Openssl这个尤为重要。

补充重要情况:电子邮件必须从现有域名发送  设置成 no


zencart-email-smtp.png
zencart-email-smtp.png

 

如果还是发不了email,可参考下面的技术细节:

在服务器上 telnet smtp.gmail.com 465 确定能连接

yum -y install openssl 安装ssl,重启apache在试一试

 

 

 开通gmail帐号的pop/smtp功能:
gmail-pop-smtp.png

 

Zen Cart后台邮件发送不成功的解决办法,错误提示“电子邮件错误: The following From address failed: ”
几个需要注意的设置项:
1、服务器应启用SMTPAUTH电子邮件发送方式;
2、检查SMTP帐号、邮箱、密码、邮件服务器域名和端口是否设置正确。
3、发件人邮件地址要用你的SMTP邮箱帐号,并且电子邮件必须从现有域名发送设为Yes.

* 如果上述都没错,请多换其他SMTP账户/邮箱测试。推荐gmail

收费调试服务

我们希望您能自己搞定这些问题,但是如果你多方测试都无法找到发邮件不成功的解决办法,我们也提供收费调试服务。诊断调试要花费技术很多时间,调试一次需要的时间可能很长,估计2-5小时。每次调试收费200元。保证帮你调试到前台 联系我们 contact us 页面能发送邮件

posted @ 2015-04-01 14:47 奋斗成就男人 阅读(1349) | 评论 (0)编辑 收藏

linux下导入、导出mysql数据库命令

一、导出数据库用mysqldump命令(注意mysql的安装路径,即此命令的路径):
1、导出数据和表结构:
mysqldump -u用户名 -p密码 数据库名 > 数据库名.sql
#/usr/local/mysql/bin/   mysqldump -uroot -p abc > abc.sql
敲回车后会提示输入密码

2、只导出表结构
mysqldump -u用户名 -p密码 -d 数据库名 > 数据库名.sql
#/usr/local/mysql/bin/   mysqldump -uroot -p -d abc > abc.sql

注:/usr/local/mysql/bin/  --->  mysql的data目录


二、导入数据库
1、首先建空数据库
mysql>create database abc;

2、导入数据库
方法一:
(1)选择数据库
mysql>use abc;
(2)设置数据库编码
mysql>set names utf8;
(3)导入数据(注意sql文件的路径)
mysql>source /home/abc/abc.sql;
方法二:
mysql -u用户名 -p密码 数据库名 < 数据库名.sql
#mysql -uabc_f -p abc < abc.sql

建议使用第二种方法导入。

注意:有命令行模式,有sql命令

posted @ 2015-03-26 14:19 奋斗成就男人 阅读(192) | 评论 (0)编辑 收藏

那些强悍的PHP一句话后门[转]

     摘要: 我们以一个学习的心态来对待这些PHP后门程序,很多PHP后门代码让我们看到程序员们是多么的用心良苦。强悍的PHP一句话后门这类后门让网站、服务器管理员很是头疼,经常要换着方法进行各种检测,而很多新出现的编写技术,用普通的检测方法是没法发现并处理的。今天我们细数一些有意思的PHP一句话木马。利用404页面隐藏PHP小马:01<!DOCTYPE HTML PUBLIC  "-...  阅读全文

posted @ 2015-02-25 14:18 奋斗成就男人 阅读(2470) | 评论 (0)编辑 收藏

如何创建magento模块之Hello World例子

步骤:
1.创建一个Hello World模块
2.为这个模块配置路由
3.为这个模块创建执行控制器

 

创建Hello World模块



创建模块的结构目录:
app/core/local/Sjolzy/HelloWorld/Block
app/core/local/Sjolzy/HelloWorld/controllers
app/core/local/Sjolzy/HelloWorld/etc
app/core/local/Sjolzy/HelloWorld/Helper
app/core/local/Sjolzy/HelloWorld/Model
app/core/local/Sjolzy/HelloWorld/sql
创建config.xml的内容(app/core/local/Sjolzy/HelloWorld/etc/config.xml):
<config>
 <modules>
  <Sjolzy_HelloWorld>
   <version>0.1.0</version>
  </Sjolzy_HelloWorld>
 </modules>
</config>
然后创建一个系统配置文件激活这个模块
Sjolzy_HelloWorld.xml(app/etc/modules/Sjolzy_HelloWorld.xml)
<config>
 <modules>
  <Sjolzy_HelloWorld>
   <active>true</active>
   <codePool>local</codePool>
  </Sjolzy_HelloWorld>
 </modules>
</config>
检查是否模块已经激活:先清空magento缓存(var/cache),在后台管理:System->Configuration->Advanced 展开Disable Modules Output,看是否Sjolzy_HelloWorld显示出来。
 

配置路由


路由是用来把一个URL请求转换成一个执行控制器的方法。
需要在magento的全局配置中显式的定义你的路由。
在config.xml(app/core/local/Sjolzy/HelloWorld/etc/config.xml)中:
<config>
 ...
 <!-- /*  fontend:指向网站的前台(也可以是admin|install) */ -->
 <frontend>
  <!-- /*  routers:路由对象的定义或路由路径的定义 */ -->
  <routers>
   <!-- /*  helloworld:指向网站的前台 */ -->
   <helloworld>
    <use>standard</use>
     <args>
      <!-- /*  module:模块名字的小写版本 */ -->
      <module>Sjolzy_HelloWorld</module>
      <!-- /*  fontName:路由过程中的一个参数,只跟路由相关(Front Controller则是用来实例化所有路由) */ -->
      <frontName>helloworld</frontName>
     </args>
   </helloworld>
  </routers>
 </frontend>
</config>
 

为路由创建执行控制器


路由会把控制权交给控制器,我们已经定义了路由,现在来定义我们的执行控制器。
app/code/local/Sjolzy/HelloWorld/controllers/IndexAction.php(模块的控制器放在子目录controllers<小写>里,这是magento的规定)
<?php
class Sjolzy_HelloWorld_IndexController extends Mage_Core_Controller_Front_Action{
 public function indexAction(){
  echo 'Hello World!';
 }
}
?>

还是情况缓存,请求URL:http://example.com/helloworld/index/index
注:http://example.com/frontName/执行控制器/执行方法


如果看到空白页面上写着'Hello World!',则你的模块创建成功!

posted @ 2015-02-25 12:06 奋斗成就男人 阅读(198) | 评论 (0)编辑 收藏

如何在magento中建立自定义页面

老话重提,我们还是通过URL来进行分析

http://<host>/<Magento虚拟目录>/<config.xm中的frontName>/<Controller文件名去掉Controller>/<Controller文件的方法名去掉Action>

例如,我们现在想在paypal的模块中,增加一个查看帮助的页面。

访问url为:
http://youip/paypal/standard/help

那么我们反向分析。根据之前的分析,我们找到控制文件
\app\code\core\Mage\Paypal\controllers\StandardController.php
在里面增加一个方法
  1. public function helpAction()
  2.        {
  3.   
  4.    $this->loadLayout();
  5.          $this->_initLayoutMessages('paypal/session');
  6.          $this->renderLayout();
  7.        }
其中:$this->loadLayout();将载入\app\design\frontend\default\default\layout\目录下的paypal.xml
增加以下片段:
  1.     <paypal_standard_help>
  2.       <!-- Mage_Paypal -->
  3.          <remove name="right"/>
  4.          <remove name="left"/>

  5.       <reference name="root">
  6.       <action method="setTemplate">
  7.          <template>/page/1column.phtml</template>
  8.           </action>
  9.       </reference>
  10.       <reference name="content">
  11.       <block type="paypal/standard_help" name="paypal_standard_help" template="paypal/standard/help.phtml"/>
  12.       </reference>
  13.    </paypal_standard_help>  
接着建立block类文件,\app\code\core\Mage\Paypal\Block\Standard\Help.php
  1. class Mage_Paypal_Block_Standard_Help extends Mage_Directory_Block_Data
  2. {
  3.    public function getHelp(){
  4.          return "this is paypal help file content!";
  5.        }
  6. }
最后建立模板文件
\app\design\frontend\default\default\template\paypal\standard\help.phtml
  1. <?php echo $this->getHelp(); ?> 

posted @ 2015-02-25 12:06 奋斗成就男人 阅读(611) | 评论 (1)编辑 收藏

服务端XMLHTTP(ServerXMLHTTP in ASP)应用

近几年很流行 Ajax,而 Ajax 的本质就 是 XMLHttpRequest,是客户端 XMLHttpRequest 对象的使用。相对于 Ajax,服务端 XMLHTTP 就是在服务端使 用 XMLHttpRequest 对象了。虽然说,在服务端使用异步请求是比较不方便的,但是做为可以服务端发送 HTTP 请求的组件,学习一下也是 没有坏处的。[喝小酒的网摘]http://blog.const.net.cn/a/2589.htm

这里,我讲的是在 ASP 环境中使用服务端 XMLHttpRequest,并以 JScript 做为演示代码的语言,因此,你需要了解 ASP 以及 JScript。

服 务端 XMLHTTP,通常会用在获取远程主机的网页或者其他内容,新闻聚合系统一般就是使用服务端 XMLHTTP 对象来获取要聚合的 Feed 的 内容,然后使用 XMLDOM 对象来分析 Feed 的内容,取出新闻的标题、作者、内容等信息,再存在数据库中,然后将若干个数据源的新闻一起显示在 一起。抓虾就是这样一个新闻聚合器,但是它不是用 ASP 写的就是了 :)

在 ASP 中,我们可以用以下代码来创建一个 ServerXMLHTTP 对象,而这个对象,就是我们在服务端进行一切操作的基础。
程序代码:

// demo code from xujiwei
// @website: http://www.xujiwei.cn/
var xmlhttp = new ActiveXObject("MSXML2.ServerXMLHTTP.5.0");

首先来了解一下 ServerXMLHTTP 对象有哪些比较有用的方法:

1. abort 这个方法用于取消 XMLHTTP 的请求。如果 XMLHTTP 对象以异步方式发送请求,如果到达一定的时间请求仍然没有返回,就可以使用这个方法来取消请求。

2. getAllResponseHeaders 这个方法的返回值是一个字符串,相当于 HTTP 请求的头部去掉了请求方法、URI和协议版本信息。

3. getResponseHeader 这个方法用来获取指定头部信息,比较有用的就是可以用来获取返回数据的 Content-Type、Referer 等。

4. open 使用指定的请求方法、URI和同步方式以及认证信息等初始化一个请求。

5. send 发 送 HTTP 请求,等待接收响应数据,注意,如果是以同步方式发送请求,send方法调用后不会立即返回,而是等到请求完成后才会返回,而以异步方法请 求时,则会立即返回。另外,send方法带有一个可选参数body,表示要发送的数据,这在使用 POST 方法时比较有用。

6. setTimeout 设置 ServerXMLHTTP 对象的 4 个超时时间,分别是:域名解析、连接服务器、发送数据、接收响应。可以通过设置相应的超时时间来控制 ServerXMLHTTP 对象,以免 ServerXMLHTTP 不能及时返回而造成程序停止响应。

7. setRequestHeader 设 置请求的 Header,在客户端 XMLHttpRequest中,通常用来设置请求的数据类型,或者标识请求的方法等等,例如 jquery 会增加 头部标识 X-Request-With,表示请求是从 XMLHttpRequest 对象发出,以方便服务端做出相应的动作。

8. waitForResponse 在使用异步方式发送请求时,可以用这个方法来控制请求的进程。在服务端脚本中,不可以像客户端那样直接使用回调函数来控制异步请求,也没有相应的函数来使用程序休眠一定的时间,因此,为了等待请求返回,我们可以使用这个方法来等待一定时间。

另外,还有其他一些方法,如 getOption、setOption、setProxy 等,这些方法用得比较少,因此这里不再介绍,需要了解的朋友可以查阅 MSDN。

接下来,再看看 ServerXMLHTTP 对象的属性:

1. onreadystatechange XMLHTTP 对象状态改变时的回调函数,这个属性为异步操作奠定了一个基础,可以让程序在不用查询 XMLHTTP 对象状态的情况获知 XMLHTTP 操作是否已经完成。

2. readyState XMLHTTP 对象状态,有 5 个值,从 0 到 4,分别代表的意思是:

0 - 未初始化,刚使用 new ActiveXObject("MSXML.ServerXMLHTTP.5.0") 创建时对象所处的状态

1 - 载入中,这个时候,已经调用了 open 方法,但是还没有使用 send 方法发送数据

2 - 已经载入,已经调用了 send 方法发送数据,但是还没有可用的响应流

3 - 正在交互,正在接收数据,这个时候可以使用 responseBody 和 responseText 属性来获取已经得到的部分数据了

4 - 完成请求,全部数据已经接收完成

通常情况下,我们只需要判断一下状态 4 即可,这个时候数据已经全部载入,使用 responseBody 或 responseText 属性就能获取需要的数据。

3. status HTTP 响应状态码,正常情况应该为 200,如果请求的资源不存在,就会返回 404,还有其他状态码如服务器错误 500 等。

4. statusText HTTP 响应状态文本,用于描述响应状态码所代表的意思,诸如 200 OK 中的 OK,404 Not Found 中的 Not Found

5. responseBody 响应数据的字节数组,这在 VBScript 里是可以直接使用的,但是在 JScript 里就需要转换过了。

6. responseText 以文本方式获取响应数据

7. responseXML 将响应数据作为一个 XMLDOM 对象来返回,这在请求的数据是一个 XML 文档时特别有用

8. responseStream 响应流对象,这个属性不常用
在 ServerXMLHTTP中,异步请求不再是主要用途,往往是同步的请求用得更多,因为在服务端编程中,程序的执行是需要迅速结束并返回结果的,不像在 桌面程序中,有一个消息循环。这样就导致了在服务端编程中,同步编程用得更多。当然,这并不是说异步请求没有用处,在一定的情况下,异步请求会有很大的作 用。

1. 简单的使用ServerXMLHTTP请求并显示指定Url

首先来看一下很简单的例子,使用ServerXMLHTTP请求Google的首页并显示出来:
程序代码:

<%@LANGUAGE="JScript" CODEPAGE="65001"%>
<%
// code from xujiwei
// http://www.xujiwei.cn
var url = "http://www.google.cn";
var xmlhttp = new ActiveXObject("MSXML2.ServerXMLHTTP.5.0");
xmlhttp.open("GET", url, false);
xmlhttp.send("");
Response.BinaryWrite(xmlhttp.responseBody);
xmlhttp = null;
%>

在浏览器查看这个页面,你就可以看到Google的首页了:

图片附件

但是,我们可以看到,这里的Logo图片是没有显示的,因为这个logo在网页源代码里是以相对路径的方式来指定的:

<img src=/intl/zh-CN/images/logo_cn.gif width=286 height=110 border=0 alt="Google" title="Google">

但是,我们的测试服务器里并没有这个图片文件,因此浏览器就会显示此图片的替代文字“Google”。

这 里我使用了xmlhttp的responseBody属性,这是因为,在不知道所请求的网页是使用什么编码的情况下,可以让浏览器来处理这个问题,而不用 在服务器处理编码。如果要在服务器处理编码,你必需知道你所请求的URL所返回的内容是使用什么编码的,并且正确的将返回内容进行转码以使得客户端浏览器 能正常的显示。

例如,我们请求Baidu的首页,就会因为编码问题而导致页面完全错乱:

图片附件

所以,使用responseText或者responseBody,完全取决于我们的需要,并不是一成不变的,或者,在某些时候,我们要使用的并不是这两个中的一个,而是responseXML:)

2. 设置超时

在 使用ServerXMLHTTP发送同步请求时,整个ASP程序的执行是被阻塞了的,也就意味着在开始发送请求到请求完成响应这段时间里,我们是做不了任 何事情的。那么这里就有几个问题,如果所请求的域名解析很慢怎么办?如果程序运行的服务器与请求的服务器之间的网络环境比较差导致连接很慢怎么办?如果要 发送的数据量很大但是带宽不够怎么办?同样如果响应的数据量很大但是带宽不够怎么办?

服务器所在环境及网络条件我们是无法改善的,因为,面对这些问题,我们只能采取回避的策略,即如果碰到这些问题,我们就直接丢掉这个请求。这时,ServerXMLHTTP的超时机制就有很大的用处了。

在 前一篇中,我介绍了ServerXMLHTTP的常用方法,其中有一个setTimeouts方法,就是用来设置ServerXMLHTTP对象的四个超 时时间,分别是:域名解析超时时间(resolveTimeout)、连接超时时间(connectTimeout)、数据发送超时时间 (sendTimeout)、数据接收超时时间(receiveTimeout)。这四个超时时间所代表的意义可以从它们的字面来理解,它们分别对应了这 一节开头所提出一的四个问题。

在不使用setTimeouts方法进行设置的情况下,域名解析超时时间(resolveTimeout)是 无限的,即不会在域名解析时产生超时,连接超时时间(connectTimeout)的默认值为60秒,数据发送超时时间(sendTimeout)的默 认值为30秒,数据接收超时时间(receiveTimeout)的默认值也是30秒。

通常情况下,我们不需要默认值中所指定的那么长的超时时间,因为碰到了最坏的情况下,在一个页面显示时,访客将要面对2分钟左右的无响应时间,这时访客往往认为这个页面是无效的并且会离开这个页面。

所 以我们要做的就是给ServerXMLHTTP设置一个较短的超时时间,一般情况下,域名解析和连接远程服务器都可以在2秒内完成,发送数据时间视数据量 而定,如果只是使用GET请求,这个数据量是很小的,也可以在2秒内完成,而响应,则可以稍微长一点,定在10秒左右,超过10秒时可以认为远程服务器没 有响应。

需要注意的是,setTimeouts方法所使用的参数单位是以毫秒为单位的,也就是说,如果 要指定2秒的超时时间,所用的参数为2000。另外,setTimeouts的参数顺序也是固定的,按顺序为:域名解析超时时间 (resolveTimeout)、连接超时时间(connectTimeout)、数据发送超时时间(sendTimeout)、数据接收超时时间 (receiveTimeout)。

那么,可以使用下面的代码来完成超时设置:
程序代码:

<%@LANGUAGE="JScript" CODEPAGE="65001"%>
<%
// code from xujiwei
// http://www.xujiwei.cn
var url = "http://www.google.com";
var xmlhttp = new ActiveXObject("MSXML2.ServerXMLHTTP.5.0");
// 设置超时时间,注意参数顺序
xmlhttp.setTimeouts(2000, 2000, 2000, 10000);
xmlhttp.open("GET", url, false);
xmlhttp.send("");
Response.BinaryWrite(xmlhttp.responseBody);
xmlhttp = null;
%>

如 果在某个阶段超时了,程序会抛出异常,在JScript里可以使用try...catch来捕获,并根据ServerXMLHTTP对象的 readyState属性来获知是在哪个阶段产生了超时异常。注意,同步请求时,超时异常会发生在调用send方法所在的行,例如上例中的 xmlhttp.send("")。
程序代码:

<%@LANGUAGE="JScript" CODEPAGE="65001"%>
<%
// code from xujiwei
// http://www.xujiwei.cn
var url = "http://www.youtube.com/";
var xmlhttp = new ActiveXObject("MSXML2.ServerXMLHTTP.5.0");
// 设置超时时间,注意参数顺序
xmlhttp.setTimeouts(2000, 2000, 2000, 10000);
xmlhttp.open("GET", url, false);
try {
xmlhttp.send("");
}
catch(e) {
Response.Write("发生异常:" + e.message + "<br/>");
// 判断是否为超时错误
if(e.number == -2147012894) {
var step = "";
// 判断超时错误发生所在的阶段
switch(xmlhttp.readyState) {
case 1:
step = "解析域名或连接远程服务器"
break;
case 2:
step = "发送请求";
break;
case 3:
step = "接收数据";
break;
default:
step = "未知阶段";
}
Response.Write("在 " + step + " 时发生超时错误");
}
Response.End();
}
Response.BinaryWrite(xmlhttp.responseBody);
xmlhttp = null;
%>
3. 请求使用HTTP认证的页面

呃,虽然说目前使用HTTP基本认证的已经少之又少,但是,总该知道ServerXMLHTTP有这么一个功能,可以直接实现HTTP基本认证。

在ServerXMLHTTP对象的open中,我们通常用到的只是它的前3个参数,即method、uri、async,但事实上,它还有另外两个可选参数,即用于HTTP基本认证的username及password。

那么,如果某天,我们要使用ServerXMLHTTP访问某个使用HTTP基本认证的网站,并且我们已经有了认证所需要的用户名及密码,那么可以使用以下密码来访问需要认证的内容:
程序代码:

<%@LANGUAGE="JScript" CODEPAGE="65001"%>
<%
// code from xujiwei
// http://www.xujiwei.cn
// 访问www.google.cn并不需要HTTP认证,这里只是作为一个演示
var url = "http://www.google.cn";
var xmlhttp = new ActiveXObject("MSXML2.ServerXMLHTTP.5.0");
// 用户名和密码分别为username和password
xmlhttp.open("GET", url, false, "username", "password");
xmlhttp.send("");
Response.BinaryWrite(xmlhttp.responseBody);
xmlhttp = null;
%>

4. 使用responseXML属性

有时候,我们所需要的结果并不是文本的,而是一个XML文档,譬如目前最常用的RSS。这个时候,responseXML属性就是我们的不二选择了。

使用responseXML属性所得到的对象,就是一个DOMDocument对象,这个对象可以使用诸如selectNodes、selectSingleNode这样的方法来操作XML文档对象。

例如,我们可以利用ServerXMLHTTP抓取新浪新闻的RSS并显示出来:
程序代码:

<%@LANGUAGE="JScript" CODEPAGE="65001"%>
<%
// code from xujiwei
// http://www.xujiwei.cn
// 新浪新闻的RSS地址
var url = "http://rss.sina.com.cn/news/marquee/ddt.xml";
var xmlhttp = new ActiveXObject("MSXML2.ServerXMLHTTP.5.0");
xmlhttp.open("GET", url, false);
xmlhttp.send("");
var xml = xmlhttp.responseXML;
Response.Write("<h1>" + xml.selectSingleNode("/rss/channel/title").text + "</h1>");
var items = xml.selectNodes("/rss/channel/item");
for(var i = 0; i < items.length; i++) {
Response.Write("<h3>" + items[i].selectSingleNode("title").text + "</h3>");
Response.Write("<small>" + items[i].selectSingleNode("pubDate").text + "</small>");
Response.Write("<div>" + items[i].selectSingleNode("description").text + "</div><hr />");
}
items = null;
xmlhttp = null;
%>

这些如果弄明白了,写一个RSS新闻聚合器就不是难事了。当然XMLDOM操作就不在本系列的范围之类了。
服务端XMLHTTP(ServerXMLHTTP in ASP)进阶应用-User Agent伪装

这篇开始讲讲ServerXMLHTTP的进阶应用。说是进阶应用,但也就是讲一些在基本应用里没有讲到的属性或者方法之类:)

使用setRequestHeader伪装User-Agent

User-Agent一般是服务端程序用来判断客户端浏览器、操作系统等信息的标志,它的说明可以参考Wiki,譬如在我的电脑 IE7 的UA就是:

Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) ;

SLCC1; .NET CLR 2.0.50727; .NET CLR 3.5.21022; .NET CLR 3.5.30729; .NET CLR 3.0.30618)

可以看到,这个UA提供了不少信息,IE版本、Windows版本、.NET版本都有。再看看 Firefox 的:

Mozilla/5.0 (Windows; U; Windows NT 6.0; zh-CN; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3 (.NET CLR 3.5.30729)

UA的格式不是本文的重点,因此,如果需要了解UA的具体格式,可以去Google上找找,另外,在http://www.user-agents.org/这里可以找到目前大多数浏览器、搜索引擎Spider等的UA。

在我们使用 ServerXMLHTTP 发送请求时,它所用的 User-Agent 是以下内容:

Mozilla/4.0 (compatible; Win32; WinHttp.WinHttpRequest.5)

但是,某些网站会限制这个UA的访问,比如Google,如果我们使用以下代码来请求Google的页面,它使用的是默认UA“Mozilla/4.0 (compatible; Win32; WinHttp.WinHttpRequest.5)”:
程序代码:

<%@LANGUAGE="JScript" CODEPAGE="65001"%>
<%
// code from xujiwei
// http://www.xujiwei.cn
var url = "http://news.google.cn/?output=rss";
var xmlhttp = new ActiveXObject("MSXML2.ServerXMLHTTP.5.0");
xmlhttp.open("GET", url, false);
//xmlhttp.setRequestHeader("User-Agent", "Mozilla/5.0 (Windows; U; Windows NT 6.0; zh-CN; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3 (.NET CLR 3.5.30729)");
xmlhttp.send("");
Response.BinaryWrite(xmlhttp.responseBody);
xmlhttp = null;
%>

你会发现,我们会收到一个 403 Forbidden 的错误:

图片附件

为 了使得Google的RSS输出程序能把我们的识别成正常的RSS阅读或者一般浏览器,就需要在请求发出前设置 Request Header。要设 置 Request Header,只需要简单的在调用 open 方法之后,send 方法之前使用 setRequestHeader 来设置就行 了,它的语法是 xmlhttp.setRequestHeader(key, value)。下面我们就让Google的RSS输出程序把我们的请求识 别为Firefox的请求:
程序代码:

<%@LANGUAGE="JScript" CODEPAGE="65001"%>
<%
// code from xujiwei
// http://www.xujiwei.cn
var url = "http://news.google.cn/?output=rss";
var xmlhttp = new ActiveXObject("MSXML2.ServerXMLHTTP.5.0");
xmlhttp.open("GET", url, false);
// 设置 User Agent 为 Firefox 的UA
xmlhttp.setRequestHeader("User-Agent", "Mozilla/5.0 (Windows; U; Windows NT 6.0; zh-CN; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3 (.NET CLR 3.5.30729)");
xmlhttp.send("");
Response.BinaryWrite(xmlhttp.responseBody);
xmlhttp = null;
%>

刷新浏览器,显示出了Firefox的RSS预览界面,获取Google资讯RSS成功!

图片附件

ok,我们能正确得到Google资讯的RSS了,再通过XMLDOM来操作返回的RSS文档,就可以采集Google资讯那海量的新闻了。
[喝小酒的网摘]http://blog.const.net.cn/a/2589.htm

转载自 [blog.const.net.cn]喝小酒的网摘 及本文链接地址:http://blog.const.net.cn/a/2589.htm

相关文章
  • 发生msxml3.dll,错误800c0005错误的原因和解决方法
  • Function getHTTPPage(url)
    dim http
    set http=Server.createobject("Microsoft.XMLHTTP")
    Http.open "GET",url,false
    Http.send()
    if Http.readystate<
  • 定时运行ASP文件
  • 在一定的时候,要定时的运行某个ASP文件去执行一个任务,如一个工厂在早上9点钟要采集所有的电表的读数,当然这要通过IN SQL连接到各个电表中,我们现在就是用一个ASP文件把IN SQL中表的读数再集中到MS SQL中。

    可能你看到的定时运行ASP文件的方法有多种,不过我现在要说的是一种简单的方法,利用计划任务就可简单的实现。

    首先,你要
  • 安装asppdf的几种方式
  • asppdf其实只有一个文件,也就是asppdf.dll,安装的时候只需要复制到系统system32目录下,然后regsvr32就可以了,当然你 也可以去官方网站下载asppdf.exe,安装程序不会把asppdf.dll复制到system32,但他还是已经regsvr32了,并且有一些示 例代码,也自动新建了一个虚拟目录/asppdf。也就是说可以直接http://localhost/asppd
  • xmlhttp属性和方法
  • 下面是WinHttpRequest component,不过我想也应该适用于xmlhttp,
    前文有讲到xmlhttp的属性与方法,但觉得不是很完整,所以就有了下面的补充,下面的这些数据是来自于Microsoft,估计这个是比较全的,但里面提到的一些方法,例如属性(property-get)Option,在xmlhttp中平时都没有用过,又比如function SetTimeouts
  • asp中使用xmlhttp下载图片代码
  • asp中使用xmlhttp下载图片代码:
    <%
    function getHTTPimg(url)
    dim http
    set http=server.createobject("MSXML2.XMLHTTP")
    Http.open "GET",url,false
    Http

    posted @ 2015-02-05 00:45 奋斗成就男人 阅读(565) | 评论 (0)编辑 收藏

    国内PHP开源建站程序一览

    国外的开源技术也影响和推动了国内开源程序的发展,上文我介绍的《国外优秀开源PHP建站程序一览》中,很多国外开源程序并不太符合中国人的使用习惯,而国内有一些厂家或个人也做了一些不错的产品,不少程序是提供源代码下载的,虽然有些在许可协议上和开源许可证有些出入,但其在使用上还是挺符合中国人的使用习惯,今天我就介绍一些国内的PHP“开源”建站程序。

      论坛:Discuz

      Discuz非常流行,也是中国地区最多用户使用的论坛程序,论坛搭建非常简单易用,使用风格符合中国人的口味。另一个流行的论坛程序是PHPWind

      SNS:Ucenter Home

      UCenter Home是采用PHP+MySQL构建的社会化网络软件(Social Network Software,简称SNS)。 通过 UCenter Home,建站者可以轻松构建一个以好友关系为核心的交流网络,用户可以使用迷你博客记录;方便快捷地发布日志、上传图片;与其好友们一起分享信息、讨论话题;了解好友最新动态。

      E-Commerce:ECSHOP

      ECSHOP是一款开源免费的网上商店系统,用户可以根据自己的商务特征对ECSHOP进行定制,增加自己商城的特色功能。另一个流行的网上商城系统是shopex

      点评:Modoer

      Modoer一款PHP点评系统,可针对多种行业进行点评,可以自由调控点评项目,类型,采用Web 2.0的建站方式,网站会员能让快速上手。

      Digg:PBDigg

      PBDigg是基于PHP+MYSQL的开源Digg社区资讯系统,融合了社会性标签、主题评论、Rss订阅等多种WEB2.0元素,是一个高效、快速的网站解决方案。

      Wiki:HDWiki

      HDWiki是专为中文用户设计和开发的开源、高效的中文百科建站解决方案,免费、易用、功能强大,和UCenter可无缝整合。

      RSS:IXNA

      IXNA是国内开源PHP新闻聚合程序,支持RSS多核心切换,默认支持lastrss、simplepie、magpierss,支持RDF、RSS、ATOM,支持智能识别。

      CMS:关于CMS的PHP产品很多,这里主要介绍下面三个。

      SupeSite

      SupeSite 是一套独立的内容管理系统(CMS),并且拥有对Discuz!论坛信息和UCenter Home个人空间信息聚合的功能,是一个不错的社区门户解决方案。

      DedeCMS

      DedeCMS是一个比较老的PHP CMS系统,很多早期的用户都是使用这个建立网站的。

      KingCMS

      KingCMS是一套简单易学,操作简单的开源内容管理系统(CMS),KingCMS分为PHP+MySQL和ASP+MSSQL/ACCESS两种语言版本的系统。

      最后是一次快讯,Twitter又无法访问了,估计XJ那里完事后可能会恢复,现在的解决方法在这里



      除非注明,月光博客文章均为原创,转载请以链接形式标明本文地址 

      本文地址:http://www.williamlong.info/archives/1853.html

    posted @ 2015-01-16 23:08 奋斗成就男人 阅读(186) | 评论 (0)编辑 收藏

    国外优秀开源PHP建站程序一览

    大量的PHP开源(开放源代码/Open Source)应用改变了这个世界,改变了互联网,以下我们总结从数据库到购物、博客等众多类型的开源PHP软件,供网站开发者们参考。

      博客:WordPress

      WordPress是使用PHP开发的著名博客平台,免费开源,功能强大,不仅仅用于博客搭建,还可以广泛应用于各类网络信息发布平台。

      论坛:phpBB

      phpBB是一种广泛流行的开源论坛软件,具有易于使用的管理面板和友好的用户安装界面,可以轻松地在数分钟内建立起一个论坛,功能上具有很高的可配置性,能够完全定制出相当个性化的论坛。

      CMS:Drupal

      Drupal是一个开源的内容管理系统(CMS)平台,拥有强大并可自由配置的功能,能支持从个人博客到大型社区驱动的网站等各种不同应用的网站项目。

      Wiki:MediaWiki

      MediaWiki是PHP语言写成开源Wiki引擎,全世界最大的Wiki项目维基百科就是使用MediaWiki引擎。

      Digg:Pligg

      Pligg是一套灵活的类似Digg的Web2.0 CMS系统,系统使用PHP开发,模仿了国外流行的DIGG系统。

      图像:Gallery

      Gallery 是一个非常有名的免费开源图库相册软件,基于 PHP 和 MySQL, PostgreSQL 等数据库。功能非常强大,有丰富的扩展可以下载,安装很简单,有很多插件可用。

      RSS:Gregarius

      Gregarius是一个RSS聚合程序,免费开源,具备不错的用户体验,易于操作和管理。可以把其当成RSS阅读器使用。

      电子商务:osCommerce

      osCommerce是一套由自由软件开发社团开发并维护的在线商店的解决方案,免费开源,并可以应用到任何的商业环境中,可以在短时间内生成一个功能强大的电子商务网站。

      广告:OpenX

      OpenX(原名phpAdsNew)是一个用PHP开发的广告管理与跟踪系统,适合各类网站使用,能够管理每个广告主拥有的多种任何尺寸横幅广告,按天查看,详细和概要统计并通过电子邮件发送报表给广告主。

      微博客:Laconica

      Laconica是一个开源的微型博客系统,也是一个Twitter克隆,可以实现Microblog的常用功能,国外不少微博客系统都是通过这个开源系统架设的。

      英文原文:Top Ten Open Source PHP Apps

    posted @ 2015-01-16 23:07 奋斗成就男人 阅读(238) | 评论 (0)编辑 收藏

    js调用php和php调用js的方法举例

    1 JS方式调用PHP文件并取得php中的值

     

    举一个简单的例子来说明:

    如在页面a.html中用下面这句调用:

     

    <script type="text/javascript" src="b.php?action=test"></script>

    <script type="text/javascript" >

    alert(jstext);

    </script>

     

     

    在b.php中有这样一段PHP代码:

    <? $action=$_GET['action']; //echo "var jstext='$action'"; //输出一句JS语句,生成一个JS变量,并赋颠值为PHP变量 $action的值 //echo "var jstext='aa'"; echo "var jstext="."'$action'"; ?>

     

     

    当执行a.html文件时,就会调用b.php文件,并将b.php文件的输出作为JS语句来执行,所以此处会弹出一个提示框,内容为JS变量jstext的值,也就是在PHP文件中赋给jstext的值.

    小结:

          在HTML里用JS 调用文件的方式调PHP文件,则PHP文件的输出将会被调用页作为JS的代码来用.

     

     

    2 php调用js中的值

    在z.php页面中有这样一段代码:

    <script type="text/javascript" > var url="aaaa*"; </script> <? $key="<script type=text/javascript>document.write(url)</script>"; echo $key; ?>

     

     

    3 php调用js中的方法(函数)

    <script type="text/javascript"> function test() {   var t1=3;   t1 = t1+2;   alert(t1);   //return t1; } </script>
    <?php echo "<script type='text/javascript'>test();</script>"; ?>

     

    4 JS调用PHP变量

    (1)

    <?php
    $userId=100;
    ?> <script>
    var userId;
    userId=document.getElementByIdx_x_x_x("userId").value;
    alert (userId);
    </script>
    <input type="text" name="userId" id="userId" value="<?php echo $userId; ?>">

    (2)

    <?php
    $url = '变化的网址';    //定义变量
    ?>
    <script type="text/javascript">
    //js调用php变量
    var ds ="<?php echo $url?>" ; //赋值 alert(ds); //输出效果 </script>

    5  -------------------------------

    <script language="JavaScript"> <!--

    var Y=<?php echo date('Y')?>,M=<?php echo date('n')?>,D=<?php echo date('j')?>;

    -->

    </script>

     

    6 自己写的js和php互相调用

    1.php内容:

    <?php

     

    //echo "<script LANGUAGE='javascript'>alert('$php变量');</script>";   //最简单的php调用js

    //echo "<a href=#><img width=50 src='$fruit_pic_array[$i]' onMouseOver=’javascript:a();‘></a>";

    //echo "<a href='3.php'>aaaa</a>";   //php中超链接

     

    //echo "<script type='text/javascript' language='javascript'>phpmake('PHP建站学习笔记网');</script>";   //有时候需要在PHP执行过程中,需要调用JavaScript自定义函数(验证时出错)

    echo "function ok(msg){alert(msg);}";

    ?>

    <HTML>

    <HEAD>

    <TITLE> php调用js文件的好办法</TITLE>

    </HEAD>

    <BODY>

    <!--js调用php中定义的js-->

    <scrīpt language=''javascrīpt'' type=''text/javascrīpt'' src=''1.php''></scrīpt>  

    <scrīpt>

    ok("aaaaaa!");

    </scrīpt>

    </script>

    </BODY>

    </HTML>

     

    2.php内容:

    <!--js调用php-->

    <?php

     

    $userId=100;

     

    ?>

     

    <script>

     

    var userId;

     

    userId=document.getElementByIdx_x("userId").value;

     

    alert (userId);

     

    </script>

     

    <input type="text" name="userId" id="userId" value="<?php echo $userId; ?>">

     

     

     

    <!--js调用php-->

    <?php

    if($_GET["action"]=="ok")

    {

    echo "I'm OK!";

    }

    else

    {

    echo "I'm not OK!";

    }

    ?>

    <SCRIPT Language = "JavaScript">

    function func()

    {

    if(confirm("Are you OK with this?"))

    {

    this.location = "ok.php?action=ok";

    }

    else

    {

    this.location = "ok.php?action=cancel";

    }

    }

    </SCRIPT>

    <html>

    <head>

    </head>

    <body>

    <a href="#" href="#" onClick="javascript:func();">Please Click</a>

    </body>

    </html>

     

    <!--js调用php-->

    <html>

    <head>

    <script>

    function isMail(PostString) 

    re=/\w*/ 

    if(re.test(PostString)) 

    return true; 

    else 

    return false; 

    function test(){

    if (isMail(<?php echo $email?>)) 

    {document.write("<?php echo "N";?>");} 

    else 

    {document.write('<?php echo 'Y';?>');}

    }

    </script>

    </head>

    <body>

    <?php 

    $email="aa"; 

    ?>

    <input   type=button   value=click   onclick= 'test() '>

    </body>

    </html>

     

    <!--php中含有js代码-->

    <?php

        echo   "

    <script   language=javascript>

      function   test(){

        alert( 'hello ');    

      }

    </script> ";

     

    ?>

    <input   type=button   value=click   onclick= 'test() '>

    posted @ 2015-01-16 01:45 奋斗成就男人 阅读(230) | 评论 (0)编辑 收藏

    PHP与JavaScript下的Cookie操作

         摘要: 下面的例子列出几种情形交互场景,列出JS和php交互的方法。总结下,以免日后再为cookie问题困扰。setcookie.php01<?php02    setcookie('php_cn_ck','php_中文_cookie');03    setcookie('php_en_ck','php_english_...  阅读全文

    posted @ 2015-01-15 19:16 奋斗成就男人 阅读(224) | 评论 (0)编辑 收藏

    PHP利用Curl、socket、file_get_contents POST数据

    <?php 
    /** 
    * Socket版本 
    * 使用方法: 
    * $post_string = "app=socket&version=beta"; 
    * request_by_socket('facebook.cn','/restServer.php',$post_string); 
    */ 
    function request_by_socket($remote_server,$remote_path,$post_string,$port 80,$timeout 30
    ){ 
        
    $socket fsockopen($remote_server,$port,$errno,$errstr,$timeout
    ); 
         if (!
    $socket) die("$errstr($errno)"
    ); 
        
        
    fwrite($socket,"POST $remote_path HTTP/1.0\r\n"
    ); 
        
    fwrite($socket,"User-Agent: Socket Example\r\n"
    ); 
        
    fwrite($socket,"HOST: $remote_server\r\n"
    ); 
        
    fwrite($socket,"Content-type: application/x-www-form-urlencoded\r\n"
    ); 
        
    fwrite($socket,"Content-length: ".strlen($post_string)+8."\r\n"
    ); 
        
    fwrite($socket,"Accept:*/*\r\n"
    ); 
        
    fwrite($socket,"\r\n"
    ); 
        
    fwrite($socket,"mypost=$post_string\r\n"
    ); 
        
    fwrite($socket,"\r\n"
    ); 
        
        
    $header ""

         while (
    $str trim(fgets($socket,4096
    ))) { 
            
    $header.=$str

         } 
        
        
    $data ""

         while (!
    feof($socket
    )) { 
            
    $data .= fgets($socket,4096
    ); 
         } 
        
         return 
    $data

    }

    /** 
    * Curl版本 
    * 使用方法: 
    * $post_string = "app=request&version=beta"; 
    * request_by_curl('http://facebook.cn/restServer.php',$post_string); 
    */ 
    function request_by_curl($remote_server,$post_string
    ){ 
        
    $ch curl_init
    (); 
        
    curl_setopt($ch,CURLOPT_URL,$remote_server
    ); 
        
    curl_setopt($ch,CURLOPT_POSTFIELDS,'mypost='.$post_string
    ); 
        
    curl_setopt($ch,CURLOPT_RETURNTRANSFER,true
    ); 
        
    curl_setopt($ch,CURLOPT_USERAGENT,"Jimmy's CURL Example beta"
    ); 
        
    $data curl_exec($ch
    ); 
        
    curl_close($ch
    ); 
         return 
    $data


    /** 
    * 其它版本 
    * 使用方法: 
    * $post_string = "app=request&version=beta"; 
    * request_by_other('http://facebook.cn/restServer.php',$post_string); 
    */ 
    function request_by_other($remote_server,$post_string
    ){ 
        
    $context 
    = array( 
            
    'http'
    =>array( 
                
    'method'=>'POST'

                
    'header'=>'Content-type: application/x-www-form-urlencoded'."\r\n"

                          
    'User-Agent : Jimmy\'s POST Example beta'."\r\n"

                          
    'Content-length: '.strlen($post_string)+8

                
    'content'=>'mypost='.$post_string

             ); 
        
    $stream_context stream_context_create($context
    ); 
        
    $data file_get_contents($remote_server,FALSE,$stream_context
    ); 
         return 
    $data

    }

    function curl_file_get_contents($durl) {     

            $ch = curl_init ();     
            curl_setopt ( $ch, CURLOPT_URL, $durl );        
            curl_setopt ( $ch, CURLOPT_POST, 1 );
            curl_setopt ( $ch, CURLOPT_TIMEOUT, 5 );        
            curl_setopt ( $ch, CURLOPT_USERAGENT, _USERAGENT_ );        
            curl_setopt ( $ch, CURLOPT_REFERER, _REFERER_ );        
            curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, 1 );
            $r = curl_exec ( $ch );
            curl_close ( $ch );     
            return $r;

        }




    php读取网络文件 curl, fsockopen ,file_get_contents 几个方法的效率对比

    curl效率及稳定原来可以远远超越file_get_contents

     

    最近需要获取别人网站上的音乐数据。用了file_get_contents函数,但是总是会遇到获取失败的问题,尽管按照手册中的 例子设置了超时,可多数时候不会奏效:


    $config['context'] = stream_context_create(array(‘http’ => array(‘method’ => “GET”,
       ’timeout’ => 5//这个超时时间不稳定,经常不奏效
       )
      ));

    这时候,看一下服务器的连接池,会发现一堆类似的错误,让我头疼万分:
    file_get_contents(http://***): failed to open stream…

    现在改用了curl库,写了一个函数替换:
    function curl_file_get_contents($durl){
      $ch = curl_init();
      curl_setopt($ch, CURLOPT_URL, $durl);
      curl_setopt($ch, CURLOPT_TIMEOUT, 5);
      curl_setopt($ch, CURLOPT_USERAGENT, _USERAGENT_);
      curl_setopt($ch, CURLOPT_REFERER,_REFERER_);
      curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
      $r = curl_exec($ch);
      curl_close($ch);
       return $r;
    }

    如此,除了真正的网络问题外,没再出现任何问题。
    这是别人做过的关于curl和file_get_contents的测试:
    file_get_contents抓取google.com需用秒数:

     

    2.31319094

    2.30374217
    2.21512604
    3.30553889
    2.30124092

    curl使用的时间:

     

    0.68719101

    0.64675593
    0.64326
    0.81983113
    0.63956594

    差距很大?呵呵,从我使用的经验来说,这两个工具不只是速度有差异,稳定性也相差很大。

    建议对网络数据抓取稳定性要求比较高的朋友使用上面的 curl_file_get_contents函数,不但稳定速度快,还能假冒浏览器欺骗目标地址哦!

     

     

     

    看到的其他文章收藏于此===============================

    php fsockopen

    方法1: 用file_get_contents 以get方式获取内容
    <?php
    $url='http://www.domain.com/';
    $html = file_get_contents($url);
    echo $html;
    ?>

    方法2: 用fopen打开url, 以get方式获取内容
    <?php
    $fp = fopen($url, 'r');
    stream_get_meta_data($fp);
    while(!feof($fp)) {
    $result .= fgets($fp, 1024);
    }
    echo "url body: $result";
    fclose($fp);
    ?>



    方法3:用file_get_contents函数,以post方式获取url
    <?php
    $data = array ('foo' => 'bar');
    $data = http_build_query($data);

    $opts = array (
    'http' => array (
    'method' => 'POST',
    'header'=> "Content-type: application/x-www-form-urlencoded\r\n" .
    "Content-Length: " . strlen($data) . "\r\n",
    'content' => $data
    )
    );

    $context = stream_context_create($opts);
    $html = file_get_contents('http://localhost/e/admin/test.html', false, $context);

    echo $html;
    ?>


    方法4:用fsockopen函数打开url,以get方式获取完整的数据,包括header和body

    <?php
    function get_url ($url,$cookie=false)
    {
    $url = parse_url($url);
    $query = $url[path]."?".$url[query];
    echo "Query:".$query;
    $fp = fsockopen( $url[host], $url[port]?$url[port]:80 , $errno, $errstr, 30);
    if (!$fp) {
    return false;
    } else {
    $request = "GET $query HTTP/1.1\r\n";
    $request .= "Host: $url[host]\r\n";
    $request .= "Connection: Close\r\n";
    if($cookie) $request.="Cookie:   $cookie\n";
    $request.="\r\n";
    fwrite($fp,$request);
    while()) {
    $result .= @fgets($fp, 1024);
    }
    fclose($fp);
    return $result;
    }
    }
    //获取url的html部分,去掉header
    function GetUrlHTML($url,$cookie=false)
    {
    $rowdata = get_url($url,$cookie);
    if($rowdata)
    {
    $body= stristr($rowdata,"\r\n\r\n");
    $body=substr($body,4,strlen($body));
    return $body;
    }

        return false;
    }
    ?>



    方法5:用fsockopen函数打开url,以POST方式获取完整的数据,包括header和body

    <?php
    function HTTP_Post($URL,$data,$cookie, $referrer="")
    {

        // parsing the given URL
    $URL_Info=parse_url($URL);

        // Building referrer
    if($referrer=="") // if not given use this script as referrer
    $referrer="111";

        // making string from $data
    foreach($data as $key=>$value)
    $values[]="$key=".urlencode($value);
    $data_string=implode("&",$values);

        // Find out which port is needed - if not given use standard (=80)
    if(!isset($URL_Info["port"]))
    $URL_Info["port"]=80;

        // building POST-request:
    $request.="POST ".$URL_Info["path"]." HTTP/1.1\n";
    $request.="Host: ".$URL_Info["host"]."\n";
    $request.="Referer: $referer\n";
    $request.="Content-type: application/x-www-form-urlencoded\n";
    $request.="Content-length: ".strlen($data_string)."\n";
    $request.="Connection: close\n";

        $request.="Cookie:   $cookie\n";

        $request.="\n";
    $request.=$data_string."\n";

        $fp = fsockopen($URL_Info["host"],$URL_Info["port"]);
    fputs($fp, $request);
    while(!feof($fp)) {
    $result .= fgets($fp, 1024);
    }
    fclose($fp);

        return $result;
    }

    ?>


    方法6:使用curl库,使用curl库之前,可能需要查看一下php.ini是否已经打开了curl扩展

    <?php
    $ch = curl_init();
    $timeout = 5;
    curl_setopt ($ch, CURLOPT_URL, 'http://www.domain.com/');
    curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
    $file_contents = curl_exec($ch);
    curl_close($ch);

    echo $file_contents;
    ?>

     

     

     

     

    php中 curl, fsockopen ,file_get_contents 三个函数 都可以实现采集模拟发言 。 三者有什么区别,或者讲究么  

    赵永斌:
    有些时候用file_get_contents()调用外部文件,容易超时报错。换成curl后就可以.具体原因不清楚
    curl 效率比file_get_contents()和fsockopen()高一些,原因是CURL会自动对DNS信息进行缓存(亮点啊 有我待亲测)

    范佳鹏:
    file_get_contents curl fsockopen
    在当前所请求环境下选择性操作,没有一概而论:
    具我们公司开发KBI应用来看:
    刚开始采用:file_get_contents
    后来采用:fsockopen
    最后到至今采用:curl

    (远程)我个人理解到的表述如下(不对请指出,不到位请补充)
    file_get_contents 需要php.ini里开启allow_url_fopen,请求http时,使用的是http_fopen_wrapper,不会keeplive.curl是可以的。
    file_get_contents()单个执行效率高,返回没有头的信息。
    这个是读取一般文件的时候并没有什么问题,但是在读取远程问题的时候就会出现问题。
    如果是要打一个持续连接,多次请求多个页面。那么file_get_contents和fopen就会出问题。
    取得的内容也可能会不对。所以做一些类似采集工作的时候,肯定就有问题了。
    sock较底层,配置麻烦,不易操作。 返回完整信息。

    潘少宁-腾讯:

    file_get_contents 虽然可以获得某URL的内容,但不能post  get啊。
    curl 则可以post和get啊。还可以获得head信息
    而socket则更底层。可以设置基于UDP或是TCP协议去交互
    file_get_contents 和 curl 能干的,socket都能干。
    socket能干的,curl 就不一定能干了
    file_get_contents  更多的时候 只是去拉取数据。效率比较高  也比较简单。
    赵的情况这个我也遇到过,我通过CURL设置host 就OK了。  这和网络环境有关系

    posted @ 2014-12-31 19:05 奋斗成就男人 阅读(305) | 评论 (0)编辑 收藏

    php的curl和socket的区别

    首先说下啥是socket:
           php使用berkely的socket库来创建他的连接,socket是一个数据结果,你可以通过这个socket来开启服务器和客户端的会话。服务器端一直处于监听状态,当一个客户端连接服务器,他就打开服务器端正在监听的一个端口进行会话。这时服务器端接收客户端的连接请求,那么就进行一次循环。现在这个客户端就能够发送信息到服务器,服务器也可以发送信息给客户端。
          产生一个socket你一共需要三个变量:
         1、一个协议
         2、一个socket类型
         3、一个公共协议类型
         以下是对这三个变量的详细解释,大概了解下吧
         协议:产生一个socket有三个协议供选择:
        1、AF_INET  这个是使用比较广泛的产生socket的协议,使用tcp或者udp协议传输,使用ipv4地址
        2、AF_INET6 显而易见哈,同上,不同的是使用ipv6地址
        3、AF_UNIX  使用在unix或者linux机器上,这个很少使用,仅在服务器端和客户端均为unix或者linux系统上使用。
       
         socket类型:
         1、SOCK_STREAM  这个协议是按照顺序的、可靠的、数据完整的基于字节流的连接。这是一个使用最多的socket类型,这个socket是使用TCP来进行传输。
         2、SOCK_DGRAM  这个协议是无连接的、固定长度的传输调用。该协议是不可靠的,使用UDP来进行它的连接。
         3、SOCK_SEQPACKET  这个协议是双线路的、可靠的连接,发送固定长度的数据包进行传输。必须把这个包完整的接受才能进行读取。
         4、SOCK_RAW  这个socket类型提供单一的网络访问,这个socket类型使用ICMP公共协议。(ping、traceroute使用该协议)
         5、SOCK_RDM  这个类型是很少使用的,在大部分的操作系统上没有实现,它是提供给数据链路层使用,不保证数据包的顺序
         
         公共协议类型:
        1、ICMP (Internet Control Message Protocol)互联网控制报文协议,主要用在网关和主机上,用来检测网络状况和报告错误信息
        2、TCP  (Transmission Control Protocol) 传输控制协议,他是使用最广泛的协议,他能够保证数据包到达接收者那里,如果中途出现错误,那么此协议从新发送数据包。
       3、UDP   (User Datagram Protocol)用户数据包协议,他是无连接的,不可靠的数据传输协议。

       好啦,你现在知道了产生一个socke需要三个元素,那么在php中socket_create()就需要三个参数,一个协议,一个socket类型,一个公共协议。如果创建成功,socket_create()返回一个socket资源类型,如果不成功,嘿嘿,那你会收到一个false.
        
    CURL
    cURL  是利用URL语法规定来传输文件和数据的工具。他支持HTTP、FTP、TELNET。
        为啥要使用cURL呢?
       因为,如果我们有时候想灵活的获取网页上的内容,例如处理coockies、验证、表单提交、文件上传等等等等。那么你就需要用到cURL.据说php有着功能强大的cURL库(因为偶也说不清强大在哪里啦,
        php使用cURL的选项基本步骤如下:
        1、初始化
        2、参数设置
        3、页面内容获取或者操作
        4、释放句柄

    看看下面这个简单的例子吧。
    <?php  
    //初始化curl  
    $ch = curl_init ();  
    /* 
     * 设置curl 
     * php手册对于curl_setopt的解释为:设置对于curl传输的操作 
     * curl_setopt有三个参数:资源(一般为你建立的curl句柄)、操作(你将对这个句柄作何操作)、参数(对于这个操作你给出的参数) 
     
    */  
    //例如你想对百度进行某些操作  
    curl_setopt ( $ch, CURLOPT_URL, "http://www.baidu.com");  
    //现在看来你要向百度post数据  
    curl_setopt ( $ch, CURLOPT_POST, 1 );  
    /*给出了要post的数据:$post_string,post的数据可以是一个文件, 
    *那么你需要以@加上文件的全路径给出,或者你要post一些数据, 
    *那么你可以按照数组形式给出,或者按照字符串给出, 
    *如果你想按照字符串形式给出,请把字符串urlencode,嘿嘿 
    */  
    curl_setopt ( $ch, CURLOPT_POSTFIELDS, $post_string );  
    /* 
     *把curl操作的结果以字符串形式 从curl_exec ()返回,而不是直接就输出了 
     
    */  
    curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, true );  
    //得到操作返回结果  
    $result = curl_exec ( $ch );  
    //关闭curl句柄  
    curl_close ( $ch );   
    ?>  
    因为php的curl有很多操作,要都记住估计很困难,反正偶记不住啦,说些大家可能用的上的吧。大笑
    获取服务器的一些信息
    [php] view plaincopy
    <?php  
      
      
    //初始化curl  
    $ch = curl_init ();  
      
    curl_setopt ( $ch, CURLOPT_URL, "http://www.baidu.com");  
    curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, true );  
    curl_exec($ch);  
    $info = curl_getinfo($ch);  
      
    var_dump($info);  
    ?>  

    通过上面的例子,你将会获得如下信息:
    “url” //资源网络地址
    “content_type” //内容编码
    “http_code” //HTTP状态码
    “header_size” //header的大小
    “request_size” //请求的大小
    “filetime” //文件创建时间
    “ssl_verify_result” //SSL验证结果
    “redirect_count” //跳转技术  
    “total_time” //总耗时
    “namelookup_time” //DNS查询耗时
    “connect_time” //等待连接耗时
    “pretransfer_time” //传输前准备耗时
    “size_upload” //上传数据的大小
    “size_download” //下载数据的大小
    “speed_download” //下载速度
    “speed_upload” //上传速度
    “download_content_length”//下载内容的长度
    “upload_content_length” //上传内容的长度  
    “starttransfer_time” //开始传输的时间
    “redirect_time”//重定向耗时

    利用curl你还可以做以下操作:
    模拟页面的post操作
    文件上传
    HTTP 认证
    FTP 上传
    回调函数
    以上关于curl的大前提是你的php在安装编译时加了 --with-curlwrappers ,你可以通过phpinfo()操作来查看你是不是在编译时加了这个扩展库。
    如果加载了这个扩展,你将能看见类似:
    如果你没有这个扩展,你需要改一下php.ini文件,去掉extension=php_curl.dll前面的分号。
    好啦,现在我们知道socket和curl是咋回事了,socket是一种数据结构,他可以用来在服务器和客户端进行对话。而curl是利用url语法规定来传输文件和数据的规定,支持很多协议,例如FTP,HTTP、TELNET等。

    posted @ 2014-12-31 19:03 奋斗成就男人 阅读(501) | 评论 (0)编辑 收藏

    php中使用Curl、socket、file_get_contents三种方法POST提交数据

    抓取远程内容,之前一直都在用file_get_content函数,其实早就知道有curl这么一个好东西的存在,但是看了一眼后感觉使用颇有些复杂,没有file_get_content那么简单,再就是需求也不大,所以没有学习使用curl。
    直到最近,要做一个网页小偷程序的时候才发现file_get_content已经完全不能满足需求了。我觉得,在读取远程内容的时候,file_get_content除了使用比curl便捷以外,其他都没有curl好。

    php中curl和file_get_content的一些比较

    主要区别:

    学习才发现,curl支持很多协议,有FTP, FTPS, HTTP, HTTPS, GOPHER, TELNET, DICT, FILE以及LDAP,也就是说,它能做到很多file_get_content做不到的事情。curl在php可以实现远程获取和采集内容;实现PHP网页版的FTP上传下载;实现模拟登陆;实现接口对接(API),数据传输;实现模拟Cookie;下载文件断点续传等等,功能十分强大。

    了解curl一些基本的使用后,才发现其实并不难,只不过记住里面一些设置参数,难弄一点,但是我们记住几个常用的就可以了。

    开启curl:

    因为PHP默认是不支持curl功能的,因此如果要用curl的话,首先需要在php.ini中开启该功能,即去掉 ;extension= php_curl.dll 前面的分号,然后保存后重启apache/iis就好了。

    基本语法:

    复制代码代码如下:

    $my_curl = curl_init();    //初始化一个curl对象
    curl_setopt($my_curl, CURLOPT_URL, "http://www.jb51.net");    //设置你需要抓取的URL
    curl_setopt($my_curl,CURLOPT_RETURNTRANSFER,1);    //设置是将结果保存到字符串中还是输出到屏幕上,1表示将结果保存到字符串
    $str = curl_exec($curl);    //执行请求
    echo $str;    //输出抓取的结果
    curl_close($curl);    //关闭url请求

    最近需要获取别人网站上的音乐数据。用了file_get_contents函数,但是总是会遇到获取失败的问题,尽管按照手册中的例子设置了超时,可多数时候不会奏效:

    $config['context'] = stream_context_create(array('http' => array('method' => "GET",
    'timeout' => 5//这个超时时间不稳定,经常不奏效
    )
    ));

    这时候,看一下服务器的连接池,会发现一堆类似的错误,让我头疼万分:
    file_get_contents(http://***): failed to open stream…

    现在改用了curl库,写了一个函数替换:
    function curl_file_get_contents($durl){
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $durl);
    curl_setopt($ch, CURLOPT_TIMEOUT, 5);
    curl_setopt($ch, CURLOPT_USERAGENT, _USERAGENT_);
    curl_setopt($ch, CURLOPT_REFERER,_REFERER_);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    $r = curl_exec($ch);
    curl_close($ch);
    return $r;
    }

    如此,除了真正的网络问题外,没再出现任何问题。
    这是别人做过的关于curl和file_get_contents的测试:
    file_get_contents抓取google.com需用秒数:

    2.31319094
    2.30374217
    2.21512604
    3.30553889
    2.30124092

    curl使用的时间:

    0.68719101
    0.64675593
    0.64326
    0.81983113
    0.63956594

    差距很大?呵呵,从我使用的经验来说,这两个工具不只是速度有差异,稳定性也相差很大。

    建议对网络数据抓取稳定性要求比较高的朋友使用上面的 curl_file_get_contents函数,不但稳定速度快,还能假冒浏览器欺骗目标地址哦!

    方法1: 用file_get_contents 以get方式获取内容

    复制代码代码如下:

    <?php
    $url='http://www.domain.com/';
    $html = file_get_contents($url);
    echo $html;
    ?>

    方法2: 用fopen打开url, 以get方式获取内容

    复制代码代码如下:

    <?php
    $fp = fopen($url, 'r');
    stream_get_meta_data($fp);
    while(!feof($fp)) {
    $result .= fgets($fp, 1024);
    }
    echo "url body: $result";
    fclose($fp);
    ?>

    方法3:用file_get_contents函数,以post方式获取url

    复制代码代码如下:

    <?php
    $data = array ('foo' => 'bar');
    $data = http_build_query($data);

    $opts = array (
    'http' => array (
    'method' => 'POST',
    'header'=> "Content-type: application/x-www-form-urlencodedrn" .
    "Content-Length: " . strlen($data) . "rn",
    'content' => $data
    )
    );
    $context = stream_context_create($opts);
    $html = file_get_contents('http://localhost/e/admin/test.html', false, $context);
    echo $html;
    ?>

    方法4:用fsockopen函数打开url,以get方式获取完整的数据,包括header和body

    复制代码代码如下:

    <?php
    function get_url ($url,$cookie=false)
    {
    $url = parse_url($url);
    $query = $url[path]."?".$url[query];
    echo "Query:".$query;
    $fp = fsockopen( $url[host], $url[port]?$url[port]:80 , $errno, $errstr, 30);
    if (!$fp) {
    return false;
    } else {
    $request = "GET $query HTTP/1.1rn";
    $request .= "Host: $url[host]rn";
    $request .= "Connection: Closern";
    if($cookie) $request.="Cookie: $cookien";
    $request.="rn";
    fwrite($fp,$request);
    while()) {
    $result .= @fgets($fp, 1024);
    }
    fclose($fp);
    return $result;
    }
    }
    //获取url的html部分,去掉header
    function GetUrlHTML($url,$cookie=false)
    {
    $rowdata = get_url($url,$cookie);
    if($rowdata)
    {
    $body= stristr($rowdata,"rnrn");
    $body=substr($body,4,strlen($body));
    return $body;
    }
    return false;
    }
    ?>

    方法5:用fsockopen函数打开url,以POST方式获取完整的数据,包括header和body

    复制代码代码如下:

    <?php
    function HTTP_Post($URL,$data,$cookie, $referrer="")
    {
    // parsing the given URL
    $URL_Info=parse_url($URL);

    // Building referrer
    if($referrer=="") // if not given use this script as referrer
    $referrer="111″;

    // making string from $data
    foreach($data as $key=>$value)
    $values[]="$key=".urlencode($value);
    $data_string=implode("&",$values);

    // Find out which port is needed – if not given use standard (=80)
    if(!isset($URL_Info["port"]))
    $URL_Info["port"]=80;

    // building POST-request:
    $request.="POST ".$URL_Info["path"]." HTTP/1.1n";
    $request.="Host: ".$URL_Info["host"]."n";
    $request.="Referer: $referern";
    $request.="Content-type: application/x-www-form-urlencodedn";
    $request.="Content-length: ".strlen($data_string)."n";
    $request.="Connection: closen";

    $request.="Cookie: $cookien";

    $request.="n";
    $request.=$data_string."n";

    $fp = fsockopen($URL_Info["host"],$URL_Info["port"]);
    fputs($fp, $request);
    while(!feof($fp)) {
    $result .= fgets($fp, 1024);
    }
    fclose($fp);

    return $result;
    }
    ?>

    方法6:使用curl库,使用curl库之前,可能需要查看一下php.ini是否已经打开了curl扩展

    复制代码代码如下:

    <?php
    $ch = curl_init();
    $timeout = 5;
    curl_setopt ($ch, CURLOPT_URL, 'http://www.domain.com/');
    curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
    $file_contents = curl_exec($ch);
    curl_close($ch);
    echo $file_contents;
    ?>

    php中 curl, fsockopen ,file_get_contents 三个函数 都可以实现采集模拟发言 。三者有什么区别,或者讲究么

    赵永斌:
    有些时候用file_get_contents()调用外部文件,容易超时报错。换成curl后就可以.具体原因不清楚
    curl 效率比file_get_contents()和fsockopen()高一些,原因是CURL会自动对DNS信息进行缓存(亮点啊有我待亲测)

    范佳鹏:
    file_get_contents curl fsockopen
    在当前所请求环境下选择性操作,没有一概而论:
    具我们公司开发KBI应用来看:
    刚开始采用:file_get_contents
    后来采用:fsockopen
    最后到至今采用:curl

    (远程)我个人理解到的表述如下(不对请指出,不到位请补充)
    file_get_contents 需要php.ini里开启allow_url_fopen,请求http时,使用的是http_fopen_wrapper,不会keeplive.curl是可以的。
    file_get_contents()单个执行效率高,返回没有头的信息。
    这个是读取一般文件的时候并没有什么问题,但是在读取远程问题的时候就会出现问题。
    如果是要打一个持续连接,多次请求多个页面。那么file_get_contents和fopen就会出问题。
    取得的内容也可能会不对。所以做一些类似采集工作的时候,肯定就有问题了。
    sock较底层,配置麻烦,不易操作。 返回完整信息。

    潘少宁-腾讯:
    file_get_contents 虽然可以获得某URL的内容,但不能post get啊。
    curl 则可以post和get啊。还可以获得head信息
    而socket则更底层。可以设置基于UDP或是TCP协议去交互
    file_get_contents 和 curl 能干的,socket都能干。
    socket能干的,curl 就不一定能干了
    file_get_contents 更多的时候 只是去拉取数据。效率比较高 也比较简单。
    赵的情况这个我也遇到过,我通过CURL设置host 就OK了。 这和网络环境有关系

    复制代码代码如下:

    <?php 
    /** 
    * Socket版本 
    * 使用方法: 
    * $post_string = "app=socket&version=beta"; 
    * request_by_socket('jb51.net','/restServer.php',$post_string); 
    */ 
    function request_by_socket($remote_server,$remote_path,$post_string,$port = 80,$timeout = 30){ 
    $socket = fsockopen($remote_server,$port,$errno,$errstr,$timeout); 
    if (!$socket) die("$errstr($errno)"); 
    fwrite($socket,"POST $remote_path HTTP/1.0"); 
    fwrite($socket,"User-Agent: Socket Example"); 
    fwrite($socket,"HOST: $remote_server"); 
    fwrite($socket,"Content-type: application/x-www-form-urlencoded"); 
    fwrite($socket,"Content-length: ".strlen($post_string)+8.""); 
    fwrite($socket,"Accept:*/*"); 
    fwrite($socket,""); 
    fwrite($socket,"mypost=$post_string"); 
    fwrite($socket,""); 
    $header = ""; 
    while ($str = trim(fgets($socket,4096))) { 
    $header.=$str; 

    $data = ""; 
    while (!feof($socket)) { 
    $data .= fgets($socket,4096); 

    return $data; 

    /** 
    * Curl版本 
    * 使用方法: 
    * $post_string = "app=request&version=beta"; 
    * request_by_curl('http://jb51.net/restServer.php',$post_string); 
    */ 
    function request_by_curl($remote_server,$post_string){ 
    $ch = curl_init(); 
    curl_setopt($ch,CURLOPT_URL,$remote_server); 
    curl_setopt($ch,CURLOPT_POSTFIELDS,'mypost='.$post_string); 
    curl_setopt($ch,CURLOPT_RETURNTRANSFER,true); 
    curl_setopt($ch,CURLOPT_USERAGENT,"Jimmy's CURL Example beta"); 
    $data = curl_exec($ch); 
    curl_close($ch); 
    return $data; 

    /** 
    * 其它版本 
    * 使用方法: 
    * $post_string = "app=request&version=beta"; 
    * request_by_other('http://jb51.net/restServer.php',$post_string); 
    */ 
    function request_by_other($remote_server,$post_string){ 
    $context = array( 
    'http'=>array( 
    'method'=>'POST', 
    'header'=>'Content-type: application/x-www-form-urlencoded'."". 
    'User-Agent : Jimmy's POST Example beta'."". 
    'Content-length: '.strlen($post_string)+8, 
    'content'=>'mypost='.$post_string) 
    ); 
    $stream_context = stream_context_create($context); 
    $data = file_get_contents($remote_server,FALSE,$stream_context); 
    return $data; 

    ?> 

    posted @ 2014-12-31 18:59 奋斗成就男人 阅读(641) | 评论 (0)编辑 收藏

    怎么用PHP发送HTTP请求(POST请求、GET请求)?

    /**
     * 发送post请求
     * 
    @param string $url 请求地址
     * 
    @param array $post_data post键值对数据
     * 
    @return string
     
    */
    function send_post($url, $post_data) {

        $postdata = http_build_query($post_data);
        $options = array(
            'http' =>; array(
                'method' =>; 'POST',
                'header' =>; 'Content-type:application/x-www-form-urlencoded',
                'content' =>; $postdata,
                'timeout' =>; 15 * 60 // 超时时间(单位:s)
            )
        );
        $context = stream_context_create($options);
        $result = file_get_contents($url, false, $context);

        return $result;
    }

    使用如下:
    post_data = array(
        'username' => 'stclair2201',
        'password' => 'handan'
    );
    send_post('http://blog.snsgou.com', $post_data);


    实战经验:

    当我利用上述代码给另一台服务器发送http请求时,发现,如果服务器处理请求时间过长,本地的PHP会中断请求,即所谓的超时中断,第一个怀疑的是PHP本身执行时间的超过限制,但想想也不应该,因为老早就按照这篇文章设置了“PHP执行时间限制”(【推荐】PHP上传文件大小限制大全 ),仔细琢磨,想想,应该是http请求本身的一个时间限制,于是乎,就想到了怎么给http请求时间限制搞大一点。。。。。。查看PHP手册,果真有个参数 “ timeout ”,默认不知道多大,当把它的值设大一点,问题得已解决


    Socket版本:

    /**
     * Socket版本
     * 使用方法:
     * $post_string = "app=socket&amp;version=beta";
     * request_by_socket('blog.snsgou.com', '/restServer.php', $post_string);
     
    */
    function request_by_socket($remote_server,$remote_path,$post_string,$port = 80,$timeout = 30) {
        $socket = fsockopen($remote_server, $port, $errno, $errstr, $timeout);
        if (!$socket) die("$errstr($errno)");
        fwrite($socket, "POST $remote_path HTTP/1.0");
        fwrite($socket, "User-Agent: Socket Example");
        fwrite($socket, "HOST: $remote_server");
        fwrite($socket, "Content-type: application/x-www-form-urlencoded");
        fwrite($socket, "Content-length: " . (strlen($post_string) + 8) . "");
        fwrite($socket, "Accept:*/*");
        fwrite($socket, "");
        fwrite($socket, "mypost=$post_string");
        fwrite($socket, "");
        $header = "";
        while ($str = trim(fgets($socket, 4096))) {
            $header .= $str;
        }

        $data = "";
        while (!feof($socket)) {
            $data .= fgets($socket, 4096);
        }

        return $data;
    }

    Curl版本:
    /**
     * Curl版本
     * 使用方法:
     * $post_string = "app=request&version=beta";
     * request_by_curl('
    http://blog.snsgou.com/restServer.php', $post_string);
     
    */
    function request_by_curl($remote_server, $post_string) {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $remote_server);
        curl_setopt($ch, CURLOPT_POSTFIELDS, 'mypost=' . $post_string);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_USERAGENT, "snsgou.com's CURL Example beta");
        $data = curl_exec($ch);
        curl_close($ch);

        return $data;
    }

    Curl版本(2)

    /**
     * 发送HTTP请求
     *
     * 
    @param string $url 请求地址
     * 
    @param string $method 请求方式 GET/POST
     * 
    @param string $refererUrl 请求来源地址
     * 
    @param array $data 发送数据
     * 
    @param string $contentType 
     * 
    @param string $timeout
     * 
    @param string $proxy
     * 
    @return boolean
     
    */
    function send_request($url, $data, $refererUrl = '', $method = 'GET', $contentType = 'application/json', $timeout = 30, $proxy = false) {
        $ch = null;
        if('POST' === strtoupper($method)) {
            $ch = curl_init($url);
            curl_setopt($ch, CURLOPT_POST, 1);
            curl_setopt($ch, CURLOPT_HEADER,0 );
            curl_setopt($ch, CURLOPT_FRESH_CONNECT, 1);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
            curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
            if ($refererUrl) {
                curl_setopt($ch, CURLOPT_REFERER, $refererUrl);
            }
            if($contentType) {
                curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type:'.$contentType));
            }
            if(is_string($data)){
                curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
            } else {
                curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
            }
        } else if('GET' === strtoupper($method)) {
            if(is_string($data)) {
                $real_url = $url. (strpos($url, '?') === false ? '?' : ''). $data;
            } else {
                $real_url = $url. (strpos($url, '?') === false ? '?' : ''). http_build_query($data);
            }

            $ch = curl_init($real_url);
            curl_setopt($ch, CURLOPT_HEADER, 0);
            curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type:'.$contentType));
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
            if ($refererUrl) {
                curl_setopt($ch, CURLOPT_REFERER, $refererUrl);
            }
        } else {
            $args = func_get_args();
            return false;
        }

        if($proxy) {
            curl_setopt($ch, CURLOPT_PROXY, $proxy);
        }
        $ret = curl_exec($ch);
        $info = curl_getinfo($ch);
        $contents = array(
                'httpInfo' => array(
                        'send' => $data,
                        'url' => $url,
                        'ret' => $ret,
                        'http' => $info,
                )
        );

        curl_close($ch);
        return $ret;
    }
    调用 WCF接口 的一个例子:$json = restRequest($r_url,'POST', json_encode($data));

    posted @ 2014-12-31 18:57 奋斗成就男人 阅读(467) | 评论 (0)编辑 收藏

    magento怎么配置paypal

    实际上magento模版默认就是接入了paypal的,用户只需要到magento的后台,对Paypal帐户进行设置即可。

    如何在magento后台设置paypal呢? 这边我简单跟大家分享一下。

    1、System -> Configuration -> Paypal
    如果没看到Paypal,则在
    magento怎么配置paypal

    2: 


    3: 
    magento怎么配置paypal


    后台设定好了,保存,然后刷新缓存,就可以支付了。
    注意可能会出现的问题:(测试的时候很容易出现的问题)
    magento怎么配置paypal

    因为测试的时候大家一般随便写地址,所以测试的时候会出现错误:无法处理付款。由于商家提供的送货地址无效,而且商家要求您的订单必须送到该地址,因此,请与该商家进行联系。
     
    解决方法:找到Paypal/Mode/Standard.php,里面有’address_override’ =1,这一行改成’address_override’=0,就可以了,大致在158行。
     
    设置二、app/code/core/mage/paypal/model/api/standard.php 237行
    $request['address_override'] = 1;将这个值设置为0 ,填写假的地址也可以跳转过去了!










    posted @ 2014-12-16 00:34 奋斗成就男人 阅读(258) | 评论 (0)编辑 收藏

    程序员常去的103个网站

         摘要: 1 J2me开发网 http://www.j2medev.com/bbs/index.asp2 J2me社区 http://www.j2meforums.com/forum/3 csdn http://www.csdn.net/4 Vc知识库 http://www.vckbase.com/5 codeproject http://www.codep...  阅读全文

    posted @ 2014-12-13 21:34 奋斗成就男人 阅读(234) | 评论 (0)编辑 收藏

    ckeditor的详细配置

    一、使用方法:

    1、在页面<head>中引入ckeditor核心文件ckeditor.js

    <script type="text/javas cript" src="ckeditor/ckeditor.js"></script>

    2、在使用编辑器的地方插入HTML控件<textarea>

    <textarea id="TextArea1" cols="20" rows="2" class="ckeditor"></textarea>

    如果是ASP.NET环境,也可用服务器端控件<TextBox>

    <asp:TextBox ID="tbContent" runat="server" TextMode="MultiLine" class="ckeditor"></asp:TextBox>

    注意在控件中加上 class="ckeditor" 。

    3、将相应的控件替换成编辑器代码

    <script type="text/javas cript">
    CKEDITOR.replace('TextArea1');
    //如果是在ASP.NET环境下用的服务器端控件<TextBox>
    CKEDITOR.replace('tbContent');
    //如果<TextBox>控件在母版页中,要这样写
    CKEDITOR.replace('<%=tbContent.ClientID.Replace("_","$") %>');
    </script>

    4、配置编辑器

        ckeditor的配置都集中在 ckeditor/config.js 文件中,下面是一些常用的配置参数:

    // 界面语言,默认为 'en'

        config.language = 'zh-cn';

    // 设置宽高

        config.width = 400;

        config.height = 400;

    // 编辑器样式,有三种:'kama'(默认)、'office2003'、'v2'

        config.skin = 'v2';

    // 背景颜色

        config.uiColor = '#FFF';

    // 工具栏(基础'Basic'、全能'Full'、自定义)plugins/toolbar/plugin.js

        config.toolbar = 'Basic';

        config.toolbar = 'Full';

        这将配合:
    config.toolbar_Full = [
    ['Source','-','Save','NewPage','Preview','-','Templates'],
    ['Cut','Copy','Paste','PasteText','PasteFromWord','-','Print', 'SpellChecker', 'Scayt'],
    ['Undo','Redo','-','Find','Replace','-','SelectAll','RemoveFormat'],
    ['Form', 'Checkbox', 'Radio', 'TextField', 'Textarea', 'Select', 'Button', 'ImageButton', 'HiddenField'],
    '/',
    ['Bold','Italic','Underline','Strike','-','Subscript','Superscript'],
    ['NumberedList','BulletedList','-','Outdent','Indent','Blockquote'],
    ['JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock'],
    ['Link','Unlink','Anchor'],
    ['Image','Flash','Table','HorizontalRule','Smiley','SpecialChar','PageBreak'],
    '/',
    ['Styles','Format','Font','FontSize'],
    ['TextColor','BGColor']
    ];

        //工具栏是否可以被收缩
    config.toolbarCanCollapse = true;

        //工具栏的位置
    config.toolbarLocation = 'top';//可选:bottom

        //工具栏默认是否展开
    config.toolbarStartupExpanded = true;

    // 取消 “拖拽以改变尺寸”功能 plugins/resize/plugin.js
    config.resize_enabled = false;

        //改变大小的最大高度

        config.resize_maxHeight = 3000;

        //改变大小的最大宽度
    config.resize_maxWidth = 3000;

        //改变大小的最小高度
    config.resize_minHeight = 250;

        //改变大小的最小宽度
    config.resize_minWidth = 750;
    // 当提交包含有此编辑器的表单时,是否自动更新元素内的数据
    config.autoUpdateElement = true;

    // 设置是使用绝对目录还是相对目录,为空为相对目录
    config.baseHref = ''

        // 编辑器的z-index值
    config.baseFloatZIndex = 10000;

    //设置快捷键
    config.keystrokes = [
    [ CKEDITOR.ALT + 121 /*F10*/, 'toolbarFocus' ], //获取焦点
    [ CKEDITOR.ALT + 122 /*F11*/, 'elementsPathFocus' ], //元素焦点

           [ CKEDITOR.SHIFT + 121 /*F10*/, 'contextMenu' ], //文本菜单

           [ CKEDITOR.CTRL + 90 /*Z*/, 'undo' ], //撤销
    [ CKEDITOR.CTRL + 89 /*Y*/, 'redo' ], //重做
    [ CKEDITOR.CTRL + CKEDITOR.SHIFT + 90 /*Z*/, 'redo' ], //

            [ CKEDITOR.CTRL + 76 /*L*/, 'link' ], //链接

            [ CKEDITOR.CTRL + 66 /*B*/, 'bold' ], //粗体
    [ CKEDITOR.CTRL + 73 /*I*/, 'italic' ], //斜体
    [ CKEDITOR.CTRL + 85 /*U*/, 'underline' ], //下划线

            [ CKEDITOR.ALT + 109 /*-*/, 'toolbarCollapse' ]
    ]

        //设置快捷键 可能与浏览器快捷键冲突 plugins/keystrokes/plugin.js.
    config.blockedKeystrokes = [
    CKEDITOR.CTRL + 66 /*B*/,
    CKEDITOR.CTRL + 73 /*I*/,
    CKEDITOR.CTRL + 85 /*U*/
    ]

        //设置编辑内元素的背景色的取值 plugins/colorbutton/plugin.js.
    config.colorButton_backStyle = {
    element : 'span',
    styles : { 'background-color' : '#(color)' }
    }

        //设置前景色的取值 plugins/colorbutton/plugin.js
    config.colorButton_colors = '000,800000,8B4513,2F4F4F,008080,000080,4B0082,696969,B22222,A52A2A,DAA520,

            006400,40E0D0,0000CD,800080,808080,F00,FF8C00,FFD700,008000,0FF,00F,EE82EE,

            A9A9A9,FFA07A,FFA500,FFFF00,00FF00,AFEEEE,ADD8E6,DDA0DD,D3D3D3,FFF0F5,

            FAEBD7,FFFFE0,F0FFF0,F0FFFF,F0F8FF,E6E6FA,FFF’

        //是否在选择颜色时显示“其它颜色”选项 plugins/colorbutton/plugin.js
    config.colorButton_enableMore = false

        //区块的前景色默认值设置 plugins/colorbutton/plugin.js
    config.colorButton_foreStyle = {
    element : 'span',
    styles : { 'color' : '#(color)' }
    };

        //所需要添加的CSS文件 在此添加 可使用相对路径和网站的绝对路径
    config.contentsCss = './contents.css';

        //文字方向
    config.contentsLangDirection = 'rtl'; //从左到右

        //CKeditor的配置文件 若不想配置 留空即可
    CKEDITOR.replace( 'myfiled', { customConfig : './config.js' } );

        //界面编辑框的背景色 plugins/dialog/plugin.js
    config.dialog_backgroundCoverColor = '#fffefd'; //可设置参考
    config.dialog_backgroundCoverColor = 'white' //默认

        //背景的不透明度 数值应该在:0.0~1.0 之间 plugins/dialog/plugin.js
    config.dialog_backgroundCoverOpacity = 0.5

        //移动或者改变元素时 边框的吸附距离 单位:像素 plugins/dialog/plugin.js
    config.dialog_magnetDistance = 20;

        //是否拒绝本地拼写检查和提示 默认为拒绝 目前仅firefox和safari支持 plugins/wysiwygarea/plugin.js.
    config.disableNativeSpellChecker = true

        //进行表格编辑功能 如:添加行或列 目前仅firefox支持 plugins/wysiwygarea/plugin.js
    config.disableNativeTableHandles = true; //默认为不开启

        //是否开启 图片和表格 的改变大小的功能 config.disableObjectResizing = true;
    config.disableObjectResizing = false //默认为开启

        //设置HTML文档类型
    config.docType = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd%22' ;

        //是否对编辑区域进行渲染 plugins/editingblock/plugin.js
    config.editingBlock = true;

        //编辑器中回车产生的标签
    config.enterMode = CKEDITOR.ENTER_P; //可选:CKEDITOR.ENTER_BR或CKEDITOR.ENTER_DIV

        //是否使用HTML实体进行输出 plugins/entities/plugin.js
    config.entities = true;

        //定义更多的实体 plugins/entities/plugin.js
    config.entities_additional = '#39'; //其中#代替了&

        //是否转换一些难以显示的字符为相应的HTML字符 plugins/entities/plugin.js
    config.entities_greek = true;

        //是否转换一些拉丁字符为HTML plugins/entities/plugin.js
    config.entities_latin = true;

        //是否转换一些特殊字符为ASCII字符 如"This is Chinese: 汉语."转换为"This is Chinese: 汉语." plugins/entities/plugin.js
    config.entities_processNumerical = false;

        //添加新组件
    config.extraPlugins = 'myplugin'; //非默认 仅示例

        //使用搜索时的高亮色 plugins/find/plugin.js
    config.find_highlight = {
    element : 'span',
    styles : { 'background-color' : '#ff0', 'color' : '#00f' }
    };

        //默认的字体名 plugins/font/plugin.js
    config.font_defaultLabel = 'Arial';

        //字体编辑时的字符集 可以添加常用的中文字符:宋体、楷体、黑体等 plugins/font/plugin.js
    config.font_names = 'Arial;Times New Roman;Verdana';

        //文字的默认式样 plugins/font/plugin.js
    config.font_style = {
    element   : 'span',
    styles   : { 'font-family' : '#(family)' },
    overrides : [ { element : 'font', attributes : { 'face' : null } } ]
    };

        //字体默认大小 plugins/font/plugin.js
    config.fontSize_defaultLabel = '12px';

        //字体编辑时可选的字体大小 plugins/font/plugin.js
    config.fontSize_sizes ='8/8px;9/9px;10/10px;11/11px;12/12px;14/14px;16/16px;18/18px;20/20px;22/22px;24/24px;26/26px;28/28px;36/36px;48/48px;72/72px'

        //设置字体大小时 使用的式样 plugins/font/plugin.js
    config.fontSize_style = {
    element   : 'span',
    styles   : { 'font-size' : '#(size)' },
    overrides : [ { element : 'font', attributes : { 'size' : null } } ]
    };

        //是否强制复制来的内容去除格式 plugins/pastetext/plugin.js
    config.forcePasteAsPlainText =false //不去除

        //是否强制用“&”来代替“&amp;”plugins/htmldataprocessor/plugin.js
    config.forceSimpleAmpersand = false;

        //对address标签进行格式化 plugins/format/plugin.js
    config.format_address = { element : 'address', attributes : { class : 'styledAddress' } };

        //对DIV标签自动进行格式化 plugins/format/plugin.js
    config.format_div = { element : 'div', attributes : { class : 'normalDiv' } };

        //对H1标签自动进行格式化 plugins/format/plugin.js
    config.format_h1 = { element : 'h1', attributes : { class : 'contentTitle1' } };

        //对H2标签自动进行格式化 plugins/format/plugin.js
    config.format_h2 = { element : 'h2', attributes : { class : 'contentTitle2' } };

        //对H3标签自动进行格式化 plugins/format/plugin.js
    config.format_h1 = { element : 'h3', attributes : { class : 'contentTitle3' } };

        //对H4标签自动进行格式化 plugins/format/plugin.js
    config.format_h1 = { element : 'h4', attributes : { class : 'contentTitle4' } };

        //对H5标签自动进行格式化 plugins/format/plugin.js
    config.format_h1 = { element : 'h5', attributes : { class : 'contentTitle5' } };

        //对H6标签自动进行格式化 plugins/format/plugin.js
    config.format_h1 = { element : 'h6', attributes : { class : 'contentTitle6' } };

        //对P标签自动进行格式化 plugins/format/plugin.js
    config.format_p = { element : 'p', attributes : { class : 'normalPara' } };

        //对PRE标签自动进行格式化 plugins/format/plugin.js
    config.format_pre = { element : 'pre', attributes : { class : 'co
     de' } };

        //用分号分隔的标签名字 在工具栏上显示 plugins/format/plugin.js
    config.format_tags = 'p;h1;h2;h3;h4;h5;h6;pre;address;div';

        //是否使用完整的html编辑模式 如使用,其源码将包含:<html><body></body></html>等标签
    config.fullPage = false;

        //是否忽略段落中的空字符 若不忽略 则字符将以“”表示 plugins/wysiwygarea/plugin.js
    config.ignoreEmptyParagraph = true;

        //在清除图片属性框中的链接属性时 是否同时清除两边的<a>标签 plugins/image/plugin.js
    config.image_removeLinkByEmptyURL = true;

        //一组用逗号分隔的标签名称,显示在左下角的层次嵌套中 plugins/menu/plugin.js.
    config.menu_groups ='clipboard,form,tablecell,tablecellproperties,tablerow,tablecolumn,table,anchor,link,image,flash,checkbox,radio,textfield,hiddenfield,imagebutton,button,select,textarea';

        //显示子菜单时的延迟,单位:ms plugins/menu/plugin.js
    config.menu_subMenuDelay = 400;

        //当执行“新建”命令时,编辑器中的内容 plugins/newpage/plugin.js
    config.newpage_html = '';

        //当从word里复制文字进来时,是否进行文字的格式化去除 plugins/pastefromword/plugin.js
    config.pasteFromWordIgnoreFontFace = true; //默认为忽略格式

        //是否使用<h1><h2>等标签修饰或者代替从word文档中粘贴过来的内容 plugins/pastefromword/plugin.js
    config.pasteFromWordKeepsStructure = false;

        //从word中粘贴内容时是否移除格式 plugins/pastefromword/plugin.js
    config.pasteFromWordRemoveStyle = false;

        //对应后台语言的类型来对输出的HTML内容进行格式化,默认为空
    config.protectedSource.push( /<\?[\s\S]*?\?>/g );   // PHP Co
     de
    config.protectedSource.push( //g );   // ASP Co
     de
    config.protectedSource.push( /(]+>[\s|\S]*?<\/asp:[^\>]+>)|(]+\/>)/gi );   // ASP.Net Co
     de

        //当输入:shift+Enter时插入的标签
    config.shiftEnterMode = CKEDITOR.ENTER_P; //可选:CKEDITOR.ENTER_BR或CKEDITOR.ENTER_DIV

        //可选的表情替代字符 plugins/smiley/plugin.js.
    config.smiley_descriptions = [
    ':)', ':(', ';)', ':D', ':/', ':P',
    '', '', '', '', '', '',
    '', ';(', '', '', '', '',
    '', ':kiss', '' ];

        //对应的表情图片 plugins/smiley/plugin.js
    config.smiley_images = [
    'regular_smile.gif','sad_smile.gif','wink_smile.gif','teeth_smile.gif','confused_smile.gif','tounge_smile.gif',
    'embaressed_smile.gif','omg_smile.gif','whatchutalkingabout_smile.gif','angry_smile.gif','angel_smile.gif','shades_smile.gif',
    'devil_smile.gif','cry_smile.gif','lightbulb.gif','thumbs_down.gif','thumbs_up.gif','heart.gif',
    'broken_heart.gif','kiss.gif','envelope.gif'];

        //表情的地址 plugins/smiley/plugin.js
    config.smiley_path = 'plugins/smiley/images/';

        //页面载入时,编辑框是否立即获得焦点 plugins/editingblock/plugin.js plugins/editingblock/plugin.js.
    config.startupFocus = false;

        //载入时,以何种方式编辑 源码和所见即所得 "source"和"wysiwyg" plugins/editingblock/plugin.js.
    config.startupMode ='wysiwyg';

        //载入时,是否显示框体的边框 plugins/showblocks/plugin.js
    config.startupOutlineBlocks = false;

        //是否载入样式文件 plugins/stylescombo/plugin.js.
    config.stylesCombo_stylesSet = 'default';
    //以下为可选
    config.stylesCombo_stylesSet = 'mystyles';
    config.stylesCombo_stylesSet = 'mystyles:/editorstyles/styles.js';
    config.stylesCombo_stylesSet = 'mystyles:http://www.example.com/editorstyles/styles.js';

        //起始的索引值
    config.tabIndex = 0;

        //当用户键入TAB时,编辑器走过的空格数,(&nbsp;) 当值为0时,焦点将移出编辑框 plugins/tab/plugin.js
    config.tabSpaces = 0;

        //默认使用的模板 plugins/templates/plugin.js.
    config.templates = 'default';

        //用逗号分隔的模板文件plugins/templates/plugin.js.
    config.templates_files = [ 'plugins/templates/templates/default.js' ]

        //当使用模板时,“编辑内容将被替换”框是否选中 plugins/templates/plugin.js
    config.templates_replaceContent = true;

        //主题
    config.theme = 'default';

        //撤销的记录步数 plugins/undo/plugin.js
    config.undoStackSize =20;

    // 在 CKEditor 中集成 CKFinder,注意 ckfinder 的路径选择要正确。
    //CKFinder.SetupCKEditor(null, '/ckfinder/');

    二、 一些使用技巧

    1、在页面中即时设置编辑器

    <script type="text/javas cript">
    //示例1:设置工具栏为基本工具栏,高度为70
    CKEDITOR.replace('<%=tbLink.ClientID.Replace("_","$") %>',
    { toolbar:'Basic', height:70 });
    //示例2:工具栏为自定义类型
    CKEDITOR.replace( 'editor1',
    {
    toolbar :
    [
    //加粗     斜体,     下划线      穿过线      下标字        上标字
    ['Bold','Italic','Underline','Strike','Subscript','Superscript'],
    //数字列表          实体列表            减小缩进    增大缩进
    ['NumberedList','BulletedList','-','Outdent','Indent'],
    //左对齐             居中对齐          右对齐          两端对齐
    ['JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock'],
    //超链接 取消超链接 锚点
    ['Link','Unlink','Anchor'],
    //图片    flash    表格       水平线            表情       特殊字符        分页符
    ['Image','Flash','Table','HorizontalRule','Smiley','SpecialChar','PageBreak'],
    '/',
    //样式       格式      字体    字体大小
    ['Styles','Format','Font','FontSize'],
    //文本颜色     背景颜色
    ['TextColor','BGColor'],
    //全屏           显示区块
    ['Maximize', 'ShowBlocks','-']
    ]
    }
    );
    </script>

    三、精简ckeditor

        在部署到Web服务器上时,下列文件夹和文件都可以删除:

        /_samples :示例文件夹;

        /_source :未压缩源程序;

        /lang文件夹下除 zh-cn.js、en.js 以外的文件(也可以根据需要保留其他语言文件);

        根目录下的 changes.html(更新列表),install.html(安装指向),license.html(使用许可);


    from:http://robin88129.iteye.com/blog/1123222

    posted @ 2014-11-24 13:10 奋斗成就男人 阅读(523) | 评论 (0)编辑 收藏

    iframe去除边框 .

    iframe去除边框

     

    <iframe name="file_frame" src="UploadFile.jsp" frameborder=no  border=0  marginwidth=0  marginheight=0  scrolling=no></iframe>

     

    iframe元素的功能是在一个文档里内嵌一个文档,创建一个浮动的帧。iframe参数列表

      name:内嵌帧名称
      width:内嵌帧宽度(可用像素值或百分比)
      height:内嵌帧高度(可用像素值或百分比)
      frameborder:内嵌帧边框 是否显示边缘;填”1″表示”是”,填”0″表示”否”
      marginwidth:帧内文本的左右页边距
      marginheight:帧内文本的上下页边距
      scrolling:是否出现滚动条(“auto”为自动,“yes”为显示,“no”为不显示)
      src:内嵌入文件的地址
      style:内嵌文档的样式(如设置文档背景等)
      allowtransparency:是否允许透明

    posted @ 2014-09-26 08:57 奋斗成就男人 阅读(230) | 评论 (0)编辑 收藏

    JS 跳出iframe框架

    (1)session过期后登陆页面跳出iframe页面问题
    登陆页面增加javascript:
    function window.onload()
        {
            if(window.parent.length>0)
             window.parent.location=location;
        }

    或者:

    <script>

    if (window != top)
    top.location.href = location.href;

    </script>


    (2)自动跳出iframe的代码
    <script type="text/javascript">
    if (top.location !== self.location) {
        top.location=self.location;
    }
    </script> 



    (3)在框架页内的退出操作:
    <script type="text/javascript">
    if (top.location !== self.location) {
        top.location = "../index.jsp";//跳出框架,并回到首页
    }
    </script> 

    posted @ 2014-09-26 08:55 奋斗成就男人 阅读(255) | 评论 (0)编辑 收藏

    10个PHP开源框架

    symfony

    symfony

    简单的模板功能symfony是一个开源的PHP Web框架。基于最佳Web开发实践,已经有多个网站完全采用此框架开发,symfony的目的是加速Web应用的创建与维护。它的特点如下:缓存管理 、自定义URLs、搭建了一些基础模块、多语言与I18N支持、采用对象模型与MVC分离、Ajax支持、适用于企业应用开发。

    项目主页】【CODE托管地址】【查看教程及示例

    CodeIgniter

    CodeIgniter

    CodeIgniter 是一个简单快速的PHP MVC 框架。它为组织提供了足够的自由支持,允许开发人员更迅速地工作。使用 CodeIgniter 时,您不必以某种方式命名数据库表,也不必根据表命名模型。这使 CodeIgniter 成为重构遗留 PHP 应用程序的理想选择,在此类遗留应用程序中,可能存在需要移植的所有奇怪的结构。

    项目主页】【CODE托管地址】【查看教程及示例

    Laravel

    Laravel

    Laravel 是一个简单优雅的 PHP web 开发框架,将你从意大利面条式的代码中解放出来。通过简单的、表达式语法开发出很棒的 Web 应用。

    项目主页】【CODE托管地址】【查看教程及示例

    CakePHP

    CakePHP

    CakePHP是一个运用了诸如ActiveRecord、Association Data Mapping、Front Controller和MVC等著名设计模式的快速开发框架。该项目主要目标是提供一个可以让各种层次的PHP开发人员快速地开发出健壮的Web应用,而 又不失灵活性。

    项目主页】【CODE托管地址】【查看教程及示例

    Yii

    Yii

    Yii是一个高性能的PHP5的web应用程序开发框架。通过一个简单的命令行工具 yiic 可以快速创建一个web应用程序的代码框架,开发者可以在生成的代码框架基础上添加业务逻辑,以快速完成应用程序的开发。

    项目主页】【CODE托管地址】【查看教程及示例

    PHPUnit

    PHPUnit

    PHPUnit是一个轻量级的PHP测试框架。它是在PHP5下面对JUnit3系列版本的完整移植。这个工具也可以被Xdebug扩展用来生成代码覆盖率报告 ,并且可以与phing集成来自动测试,最合它还可以和Selenium整合来完成大型的自动化集成测试。

    项目主页】【CODE托管地址】【查看教程及示例

    SlimFramework

    SlimFramework

    这是一个简单的 PHP5 框架用来创建 RESTful 的 Web 应用。可以帮助你快速编写简单功能强大的 RESTful 风格的web应用程序 和APIs。Slim很简单,可以让新手和专业人士使用。

    项目主页】【CODE托管地址】【查看教程及示例

    PHP Silex

    PHP Silex

    Symfony团队出品的php5.3微框架, 可大量复用Symfony2组件。Silex是Symfony 2的简化版本,比大多数PHP框架更适合开发简单应用。

    项目主页】【CODE托管地址】【查看教程及示例

    FUEL

    FuelPHP

    FuelPHP 是一个简单、灵活的 PHP 5.3 的 Web 框架,其思路结合了来自主流框架的优点。

    项目主页】【代码托管地址】【查看教程及示例

    thinkphp

    ThinkPHP

    ThinkPHP是一个快速、简单、面向对象的轻量级PHP开发框架,遵循Apache2协议,为了敏捷Web应用开发和简化企业应用开发而诞生。

    项目主页】【CODE托管地址】【查看教程及示例

    posted @ 2014-09-18 00:13 奋斗成就男人 阅读(159) | 评论 (0)编辑 收藏

    ZenCart 1.5.x 后台管理密码过期修改办法

    目前 ZenCart 最新版本是 1.5.1,在 1.5 版本后,ZenCart 就多了一项密码保护功能,后台的密码只能使用 90 天,90 天后自动过期。
    这是强制人家修改密码,我觉得这功能有点鸡肋,而且很添乱,会修改密码的会很神经质的经常修改,像我这样不修改密码的,都是可悲的什么时候过期都忘记了,最最郁闷的是,它的数据库中的 md5 密码还加后缀,不是随便复制个通用的密码就可以用,所以每次我只能看着后台那个简陋的登陆界面抓耳挠腮。
    今天已经是第三次遇到这个问题了,于是我决定把方法记录下来。
    方法还是复制通用的密码的 MD5 格式,官方提供的。进入 phpMyAdmin,在对应的数据库下运行下面的 SQL 语句:
    DELETE FROM admin WHERE admin_name = 'Admin'; 
    INSERT INTO admin (admin_name, admin_email, admin_pass, admin_profile) 
    VALUES ('Admin', 'admin@localhost', '351683ea4e19efe34874b501fdbf9792:9b', 1);
    如果你后台登陆名不是 Admin,那就得改成你的登录名,邮箱当然也要改。这个通用密码直接复制是不行的,必须清空整个 admin 项后再写入才有效。哦,对了,这个通用密码是:admin。
    修改后用密码 admin 登陆后会提示你修改密码,当然,修改后的密码仍然是90天有效。
    那有没有办法去掉这个 1.5 版本后的 ZenCart 这个 90 天的密码设定呢?老外提供了个办法,不知道管用不管用。
    方法一:找到 admin/login.php 文件内的 define('ADMIN_PASSWORD_EXPIRES_INTERVAL', strtotime('- 90 day'));,把里面的 90 改成大大的数字,比如 36500 ,嗯,100年应该够了。
    方法二:找到 admin/includes/functions/admin_access.php 文件内的 zen_check_for_password_problems() 函数,在函数下的第一行插入 return FALSE;
    方法三:也是在方法二的这个文件里,修改某个函数里的天数,像方法一那样改的无限大,不过都没经过测试,就不要发了,还是用数据库修改法吧。
    后面的三种方法你如果想测试,最后搞个 DEMO 站测试,因为老外是这么提示的,好像很严重的样子,英文我看不懂,但或许你懂得:
    *** Warning: This change will violate the PCI status of your cart. You should only do this on test carts on your own PC or on carts which do not require PCI certification. ***

    posted @ 2014-06-17 02:05 奋斗成就男人 阅读(301) | 评论 (0)编辑 收藏

    安装环境PHP curl函数 服务器不支持 curl_exec 的解决办法

    网友安装的时候,最长遇到的就是PHP curl函数不支持。这里有几种解决方法。

    windows下开启方法:
    1、拷贝PHP目录中的libeay32.dll, ssleay32.dll, php5ts.dll, php_curl.dll文件到 system32 目录。
    2、修改php.ini:配置好 extension_dir ,去掉 extension = php_curl.dll 前面的分号。

    3、重起apache或者IIS。

    测试是否安装成功:

    <?php
    $ch = curl_init();
    curl_setopt($ch,CURLOPT_URL,"http://www.google.cn");
    curl_setopt($ch,CURLOPT_HEADER,1);
    curl_exec($ch);
    curl_close($ch);
    ?>

    linux下开启方法:

    方法一

    安装cURL
       # wget http://curl.haxx.se/download/curl-7.17.1.tar.gz
       # tar -zxf curl-7.17.1.tar.gz
       # ./configure --prefix=/usr/local/curl
       # make; make install

    安装php

       只要打开开关 --with-curl=/usr/local/curl

       就可以了。

       这个扩展库还是非常棒,是fsockopen等等相关的有效的替代品。



    方法二
    进入安装php 的源码目录,

    cd ext
    cd curl
    phpize
    ./configure --with-curl =DIR
    make
    就会在PHPDIR/ext/curl /moudles/下生成curl .so的文件。

    复制curl .so文件到extensions的配置目录,修改php .ini就好了


    posted @ 2014-06-10 00:03 奋斗成就男人 阅读(1967) | 评论 (0)编辑 收藏

    PHP获取当前的域名

    1. <?  
      //获取当前的域名:   
      echo $_SERVER['SERVER_NAME'];  
      //获取来源网址,即点击来到本页的上页网址   
      echo $_SERVER["HTTP_REFERER"];  
      $_SERVER['REQUEST_URI'];//获取当前域名的后缀   
      $_SERVER['HTTP_HOST'];//获取当前域名   
      dirname(__FILE__);//获取当前文件的物理路径   
      dirname(__FILE__)."/../";//获取当前文件的上一级物理路径   
      ?>  

     

    posted @ 2014-05-30 13:22 奋斗成就男人 阅读(154) | 评论 (0)编辑 收藏

    网站漏洞扫描/弱口令扫描工具大全

    Shadow Security Scanner v 网络入侵机_V2.0 波尔远程控制V6.32 VIP破解版 
    superscan4.0扫描器 HttpsMimTools nohackasp木马生成器 
    拿站和思路 Oracle_专用注射器 远程控制软件ntshell v1.0(开源 
    挖掘鸡4.02 Willcome急速批量抓鸡全能 PcShare远程控制软件 
    多功能S扫描器 php168漏洞利用工具 中华经典网络军刀NC 
    小马上线及绑困和抓鸡 iebho攻击程序 终极Rootkit 
    超详细讲解鸽子上线 QQEAMIL攻击器 PHP木马修改增强版 
    金豹多顶下载者 framework-2.6-snapshot 提权工具集 
    EditPlus v2.31 Buil     
    最新过XP2网马     
    剑煞BetaV7.6.8     
    扫描端口V2.0     
    X-way扫描器     
    SpyNet Sniffer     
    网站猎手2.0     
    X-Scan-v3.3     
    流光5.0黑客基地专用破解版     
    NBSI网站漏洞检测工具     
    明小子旁注工具3.5     
    端口过滤扫描器     
    mysql_pwd_crack     
    Advanced IP Scanner v1.5     
    IPScanner     
    扫描软件THC-Amap v5.0     
    php注入辅助工具:phpsend     
    PackInter,sniffer工具含源代码     
    X-Scan-v3.2-cn     
    X-Scan-v3.2-beta版     
    超级扫描工具:nmap-3.81-win32     
    流光 5.0 时间限制破解     
    Domain3.2正式版(5.2修正)     
    sql扫描加自动攻击工具:Sqlpoke     
    THC-Amap v4.8     
    mysql字段扫描:numscan     
    第一款php漏洞扫描器:rpvs     
    Oscanner     
    端口扫描器红魂专用版     
    atk-3.1     
    金山毒霸可疑文件扫描工具 v2.01     
    GUI界面的WED和WIS综合工具     
    超强adsl破解器     
    俄罗斯专业扫描工具SSS6.67.58破解版     
    Attack Toolkit 3.0     
    Roman ADSL帐号扫描工具升级版     
    针对广东电信漏洞的扫描工具     
    IPv4和IPv6通用扫描工具:scan6     
    adsl帐号扫描工具+动画     
    MS Webserver 漏洞扫描器     
    网络主机扫描(HostScan)     
    T-PsKit     
    Retina Network Security Scanner     
    WildPackets ProCovert     
    Angry IP Scanner     
    wlan无线网络诊断/WildPackets AiroPe     
    APort     
    铁血扫描器     
    无处藏身(Seekyou)     
    nScan     
    SQL Injection测试工具     
    FloodScan     
    rpcscan信息扫描工具     
    优秀的ShadowScan     
    经典扫描程序Amap     
    Superscan     
    漏洞扫描Nessus     
    ipc批处理扫描工具     
    Angry IP Scanner 汉化版     
    强大的漏洞扫描NessusWX     
    WindowsNT/2000自动攻击探测机     
    网络黑客控制中心使用教程+工具     
    扫描工具SuperScan4     
    NMap最新版本:nmap-3.70-win32     
    Retina DCOM Scanner     
    SQLScan     
    很好的扫描工具 NetScanTools     
    ipc扫描工具scanipc     
    非常有名的扫描 工具X-way     
    流光 for win98/ME     
    最好的ipc$扫描essential nettools


    不错的扫描工具easyscan      
    鼎鼎大名的扫描工具 流光     
    大范围网段快速ipc$猜解机ipscan     
    N.E.W.T.网络扫描器     
    端口扫描A Complete Subnet Scanner     
    自动攻击探测机     
    扫描工具:Vsan     
    IIS漏洞扫描Easyscan     
    高速端口扫描Bluesportscanner     
    扫描工具X-port     
    最好的扫描器:X-SAN 3.0 beta     
    扫描工具:STAT Scanner Pro     
    阿拉丁扫描器     
    小巧的黑客工具:NBTScan     
    非常优秀的扫描工具X-scan 2.3     
    扫描工具IPScanner     
    扫描工具Dsns     
    著名的且功能强大的WEB扫描工具Wnikto32     
    小巧的端口扫描NetBurn     
    扫描工具GFI LANguard Scanner     
    不错的扫描工具:Scan     
    中华经典网络军刀     
    优秀的扫描工具Nmap命令行版本     
    多线程扫描XPortScan     
    专业的扫描工具Shadow Security Scanner     
    ASP漏洞集     
    扫描工具Retina Network Security Scann     
    快速端口扫描Shadowscan     
    优秀的WEB扫描工具Nikto     
    扫描Shadow Security Scanner v6.6.41     
    SuperScan V4.0汉化版     
    极为优秀的Shadow Security Scanner     
    基于命令行下的RPC扫描器     
    多线程扫描SinScan     
    局域网扫描大师 V1.0     
    推荐:免费短信发送工具     
    IP端口扫描软件     
    最新漏洞扫描器MS05051Scan     
    推荐:图形界面的NMAP扫描器     
    dcomrpc漏洞X-Scan23插件     
    啊D网络工具包2.专用免杀版     
    极速漏洞扫描攻击器[升级版]     
    猎手-旁注工具     
    黑客基地专用极速漏洞扫描器     
    X-Scan v3.3     
    超强扫描器:NMAP 3.90     
    IP地址扫描器     
    地址分类搜索机     
    多线程后台扫描器     
    超强扫描器superscan4.0      
    nmap-3.81源代码(Linux平台)     
    nmap-3.81源代码(FreeBSD平台)     
    X-Scan-v3.3     
    mysql弱口令扫描工具:mysqlweak      
    DFind_v0.83扫描工具     
    MySql Weak Pass Scanner     
    Cain & Abel v2.68 for Win      
    阿D工具包2.01      
    HScan v1.20     
    动网大扫描     
    多线程网站后台扫描工具     
    MS06040漏洞扫描器     
    挖掘鸡v3.5     
    BluesPortScan超快的端口扫描工具     
    动网大扫描 1.0测试版     
    啊D网络工具包2.1免杀版     
    sql注入中文转换器     
    明小子Domain3.6      
    guastbook漏洞利用     
    德国的SQL注射工具     
    流光FluXay 5 闪亮发布!     
    注入攻击综合软件包     
    BBSXP论坛漏洞完全注射工具     
    MS06007漏洞扫描器     
    高速扫描:风雪端口扫描器     
    动易2005 sp2漏洞利用工具     
    webhacking-WEB渗透超级助手     
    简洁高速的扫描器:HScan     
    BBS论坛群发机 破解版

    mssql注射辅助工具-getwebsehll      
    软件名称超级扫描器nmap-4.00     
    挖掘鸡 V2.2     
    啊D注入工具 V2.32 免杀版     
    SQL注射综合程序     
    扫描器IPtools2.5破解版     
    SSPort高速端口扫描器 V1.0     
    局域网查看工具V1.60     
    NCPH影子扫描器     
    目前最完美的注入工具     
    IP物理地址探测器     
    网站猎手     
    网络端口扫描工具     
    震荡波扫描工具:Sasser Scanner     
    MS04-011漏洞扫描器RetinaSasser     
    SQL跨库查询动画教程     
    命令行下NohackerScanner扫描器     
    IP扫描IPScanner 1.79中文破解版     
    嗅探监听:局域网密码查看工具1.46      
    经典工具:X-Scan-v3.1     
    监听工具:PromiScan v3.0     
    扫描工具:FtpList 1.13     
    经典漏洞扫描:X-Scan v3.0     
    扫描工具:Remoxec     
    数据扫描工具:Oracle Auditing Tools     
    Web漏洞扫描工具Trapserver     
    著名的漏洞扫描:SSS     
    扫描工具:RpcScan v1.1.1     
    经典的扫描工具:nmap 3.50     
    漏洞扫描:GFI LANguard Scanner     
    小巧的IPC扫描工具     
    CC6.0扫描程序     
    nmap 3.75 for win     
    rootkit扫描工具:Rkdscan     
    动画教程:JOEKOE留言本漏洞     
    NBWS网站后台路径猜测工具     
    web路径猜解工具:ScanWebPath     
    未公布的动力系统漏洞演示     
    SQL扫描工具:SQL ping      
    IIS权限探测:IIS Write Scanner V1.0     
    扫描软件SImpsons'CGI Scanner及使用教程     
    LANguard Network Security Scanner 5.0     
    加密工具:Morphine v1.3+GUI     
    DFind v0.8     
    L-ScanPort2.0      
    扫描工具:Scanner     
    X-Scan-v3.1-cn     
    Advanced IP Scanner V1.4 汉化版     
    飞狐-网络扫描工具试用版     
    Linux/UNIX扫描软件:XTHC-Amap v4.6     
    动画教程:动力破解任何收费漏洞     
    动画教程:'or''='漏洞最新演示     
    天意阿里巴巴企业商务网V3.7上传漏洞     
    代理猎手获取ADSL帐号冲Q币     
    扫描器:nessuswx-1.4.4-install      
    IP扫描软件:Angry IP Scanner     
    端口/漏洞/组件扫描工具:DFind v0.6     
    可获取Web Server类型的端口扫描器     
    135端口扫描器RpcScan v1.2.1      
    4899空口令探测器     
    经典工具:namp v3.50 命令行版      
    猜解后台路径工具     
    流光5.0黑客基地专用破解版     
    免验证版NBSI(附加扫描器)     
    U-scan(UNICODE漏洞扫描器)     
    自定义多线程后台扫描程序:ScanLogin     
    75款全球强劲工具大集合之一 Nessus     
    75款全球强劲工具大集合之二 NessusWX     
    Accessdiver 汉化版+使用教程     
    优秀的X-way     
    75款全球强劲工具大集合之十八SuperScan     
    75款全球强劲工具大集合之十六Nikto     
    75款全球强劲工具大集合之十一Libwhisker     
    75款全球强劲工具大集合之十二JOHN16     
    75款全球强劲工具大集合之十二John     
    75款全球强劲工具大集合之十三SSH     
    75款全球强劲工具大集合之十五Tripwire     
    最快的端口扫描工具     
    高速端口扫描PortScanner源代码


    ScanMs Tool     
    PHP扫描器

    posted @ 2014-05-21 01:18 奋斗成就男人 阅读(2801) | 评论 (1)编辑 收藏

    MySQL创建用户与授权方法

    注:我的运行环境是widnows xp professional + MySQL5.0

    一, 创建用户:

    命令:CREATE USER 'username'@'host' IDENTIFIED BY 'password';

    说 明:username - 你将创建的用户名, host - 指定该用户在哪个主机上可以登陆,如果是本地用户可用localhost, 如果想让该用户可以从任意远程主机登陆,可以使用通配符%. password - 该用户的登陆密码,密码可以为空,如果为空则该用户可以不需要密码登陆服务器.

    例子: CREATE USER 'dog'@'localhost' IDENTIFIED BY '123456';
    CREATE USER 'pig'@'192.168.1.101_' IDENDIFIED BY '123456';
    CREATE USER 'pig'@'%' IDENTIFIED BY '123456';
    CREATE USER 'pig'@'%' IDENTIFIED BY '';
    CREATE USER 'pig'@'%';

    二,授权:

    命令:GRANT privileges ON databasename.tablename TO 'username'@'host'

    说 明: privileges - 用户的操作权限,如SELECT , INSERT , UPDATE 等(详细列表见该文最后面).如果要授予所的权限则使用ALL.;databasename - 数据库名,tablename-表名,如果要授予该用户对所有数据库和表的相应操作权限则可用*表示, 如*.*.

    例子: GRANT SELECT, INSERT ON test.user TO 'pig'@'%';
    GRANT ALL ON *.* TO 'pig'@'%';

    注意:用以上命令授权的用户不能给其它用户授权,如果想让该用户可以授权,用以下命令:
    GRANT privileges ON databasename.tablename TO 'username'@'host' WITH GRANT OPTION;

    三.设置与更改用户密码

    命令:SET PASSWORD FOR 'username'@'host' = PASSWORD('newpassword');如果是当前登陆用户用SET PASSWORD = PASSWORD("newpassword");

    例子: SET PASSWORD FOR 'pig'@'%' = PASSWORD("123456");

    四.撤销用户权限

    命令: REVOKE privilege ON databasename.tablename FROM 'username'@'host';

    说明: privilege, databasename, tablename - 同授权部分.

    例子: REVOKE SELECT ON *.* FROM 'pig'@'%';

    注 意: 假如你在给用户'pig'@'%'授权的时候是这样的(或类似的):GRANT SELECT ON test.user TO 'pig'@'%', 则在使用REVOKE SELECT ON *.* FROM 'pig'@'%';命令并不能撤销该用户对test数据库中user表的SELECT 操作.相反,如果授权使用的是GRANT SELECT ON *.* TO 'pig'@'%';则REVOKE SELECT ON test.user FROM 'pig'@'%';命令也不能撤销该用户对test数据库中user表的Select 权限.

    具体信息可以用命令SHOW GRANTS FOR 'pig'@'%'; 查看.

    五.删除用户

    命令: DROP USER 'username'@'host';

    附表:在MySQL中的操作权限

    ALTER Allows use of ALTER TABLE.
    ALTER ROUTINE Alters or drops stored routines.
    CREATE Allows use of CREATE TABLE.
    CREATE ROUTINE Creates stored routines.
    CREATE TEMPORARY TABLE Allows use of CREATE TEMPORARY TABLE.
    CREATE USER Allows use of CREATE USER, DROP USER, RENAME USER, and REVOKE ALL PRIVILEGES.
    CREATE VIEW Allows use of CREATE VIEW.
    DELETE Allows use of DELETE.
    DROP Allows use of DROP TABLE.
    EXECUTE Allows the user to run stored routines.
    FILE Allows use of SELECT... INTO OUTFILE and LOAD DATA INFILE.
    INDEX Allows use of CREATE INDEX and DROP INDEX.
    INSERT Allows use of INSERT.
    LOCK TABLES Allows use of LOCK TABLES on tables for which the user also has SELECT privileges.
    PROCESS Allows use of SHOW FULL PROCESSLIST.
    RELOAD Allows use of FLUSH.
    REPLICATION Allows the user to ask where slave or master
    CLIENT servers are.
    REPLICATION SLAVE Needed for replication slaves.
    SELECT Allows use of SELECT.
    SHOW DATABASES Allows use of SHOW DATABASES.
    SHOW VIEW Allows use of SHOW CREATE VIEW.
    SHUTDOWN Allows use of mysqladmin shutdown.
    SUPER Allows use of CHANGE MASTER, KILL, PURGE MASTER LOGS, and SET GLOBAL SQL statements. Allows mysqladmin debug command. Allows one extra connection to be made if maximum connections are reached.
    UPDATE Allows use of UPDATE.
    USAGE Allows connection without any specific privileges.

    posted @ 2014-05-18 01:06 奋斗成就男人 阅读(203) | 评论 (0)编辑 收藏

    MySQL 请选择合适的列

    思维导图
    点击图片,可查看大图。

    介绍
     
    情况:如果你的表结构设计不良或你的索引设计不佳,那么请你优化你的表结构设计和给予合适的索引,这样你的查询性能就能提高几个数量级。——数据越大,索引的价值越能体现出来。
     
    我们要提高性能,需要考虑的因素:
    1、设计架构
    2、设计索引
    3、评估查询性能
     

    今天要讲的是表列的设计,暂不谈索引设计。我会在下一章讲索引设计。
     
    选择数据类型
     
    选择正确的数据类型,对于提高性能至关重要。
    下面给出几种原则,有利于帮助你选择何种类型。
     
    1、更小通常更好。
      使用最小的数据类型。——更少的磁盘空间,内存和CPU缓存。而且需要的CPU的周期也更少。
     
    2、简单就好。
      整数代价小于字符。——因为字符集和排序规则使字符比较更复杂。
      1>mysql内建类型(如timestamp,date)优于使用字符串保存。
      2>使用整数保存ip地址。
     
    3、尽量避免NULL——如果计划对列进行索引,尽量避免把列设置为NULL
      尽可能把字段定义为NOT NULL。——可以放置一个默认值,如‘',0,特殊字符串。
      原因:
        (1)MYSQL难以优化NULL列。NULL列会使索引,索引统计和值更加复杂。
        (2)NULL列需要更多的存储空间,还需要在MYSQL内部进行特殊处理。
        (3)NULL列加索引,每条记录都需要一个额外的字节,还导致MyISAM中固定大小的索引变成可变大小的索引。
     

    决定列的数据类型,我们应该遵循下面两步。

    第一步、大致决定数据类型。——判断是数字,字符串还是时间等。这通常很直观。

    第二步、确定特定的类型。

      很多数据类型能够保存同类型的数据,但是我们要发现,他们在存储的范围,精度和物理空间之间的差别(磁盘或内存空间)。如:datetime和timestamp能保存同样类型的数据:日期和时间。——timestamp使用datetime一半的空间;能保存时区;拥有特殊的自动更新能力。 

    品味数据类型
     
    整数
     
    1、存储类型——数据范围为-2^(n-1)到2^(n-1)-1,这里的n是所需存储空间的位数。
         类型名称    占用位数      数据范围    TINYINT     8   -2^7 ~ 2^7-1   SMALLINT     16     -2^15~2^15-1     MEDIUMINT       24      -2^23~2^23-1   INT     32   -2^31~2^23-1   BIGINT     64    -2^63~2^63-1

     2、unsigned属性表示不允许负数,并大致把正上限提高了一倍。如TINYINT UNSIGNED保存的范围为0到255而不是-127到128

     

    3、MYSQL对整数类型定义宽度,比如int(1)和int(22)对于存储和计算是一样的。只规定了MYSQL的交互工具(如命令行客户端)用来显示字符的个数。

     

    实数
     
    实数有分数部分(小数部分)。
    存储类型:FLOAT和DOUBLE,DECIMAL。
    占用大小:FLOAT 4个字节,DOUBLE 8个字节。DECIMAL受到MYSQL版本影响,早期版本254个数字,5.0以上65个数字。
    区别:1、FLOAT和DOUBLE支持标准浮点运算进行近似计算。
       2、DECIMAL进行DECIMAL运算,CPU并不支持对它进行直接计算。浮点运算会快一点,因为计算直接在CPU上进行。
         3、DECIMAL只是一个存储格式,在计算时会被转换为DOUBLE类型。
       4、DECIMAL(18,9)使用9个字节,小数点前4个字节,小数点1个字节,小数点后4个字节。
       5、DECIMAL只有对小数进行精确计算的时候才使用它,如保存金融数据。
     

     
    字符串类型
     
    1、varchar
      (1)保存可变长字符串。
        理解:比固定长度占用更少的存储空间,因为它只占用自己需要的空间。例外情况:使用ROW_FORMAT=FIXED创建的MyISAM表,它为每行使用固定长度的空间,可能会造成浪费。
      (2)存储长度信息。如果定义的列小于或等于255,则使用1个字节存储长度值,假设使用latin1字符集,如varchar(10)将占用11个字节的存储空间。反过来,varchar(1000),则占用1002个字节的存储空间。
      (3)节约空间,对性能有帮助。
      (4)5.0版本以上,无论是取值还是保存,MySQL都会保留字符串末尾的空格。
    只分配真正需要的空间
    使用varchar(5)和varchar(200)保存'hello'占用空间是一样的。——这里应该指的是磁盘上的空间。
    那么使用较短列有何优势?——巨大的优势
      较大的列会使用更多的内存,因为MySQL通常会分配固定大小的内存块(如varchar(200)会用200个字符大小的内存空间)来保存值(然后对值进行trim操作,最后放入磁盘)或取值。——这对排序或使用基于内存的临时表尤其不好。

    2、char
      (1)固定长度。
      (2)保存值时,去掉末尾的空格。

                 咱们再看看varchar

      (3)char常用于很短字符串或长度近似相同的字符串的时候很有用。如存储用户密码的MD5哈希值,它的长度总是一样的。
      char优于varchar的地方?
      1>> 对于经常改变的值,char优于varchar,因为固定长度行不容易产生碎片。——当最长长度远大于平均长度,并且很少发生更新的时候,通常适合使用varchar。
      2>>对于很短的列,char的效率也是高于varchar的。如对于单字节字符集(如latin1),char(1)只会占用1个字节,而varchar(2)会占用2个字节(有一个字节用来存储长度的信息)。
     

     
     3、text
    用于保存大量数据。
      (1)InnoDB在它们较大的时候会使用“外部”存储区域来进行保存。——所以需要足够的外部存储空间来保存实际的值。
      (2)排序方式不同于其他字符类型,不会按照完整长度进行排序,而只是按照max_sort_length规定的前若干个字节进行排序。
     

     
    4、使用ENUM代替字符串类型
      (1)ENUM列可以存储65 535个不同的字符串。
      (2)以紧凑方式保存。根据列表中值的数量,把它们压缩到1到2个字节中。
      (3)MySQL在内部把每个值都保存为整数,以表示值在列表中的位置。
      (4)保留了一份“查找表”,来表示整数和字符串在表的.frm文件中的映射关系。
      (5)ENUM字符列是固定的,添加、删除字符串须使用ALTER TABLE。
      (6)使用案例:权限表中使用ENUM来保存Y值和N值。
     使用方法:

                 

    在对enum列使用order by的时候,是按数字排序的,而不是字符串排序。

    日期和时间类型

    DATETIME:保存大范围的值。封装格式:YYYYMMDDHHMMSS。——与时区无关,使用8字节存储空间。

    TIMESTAMP:保存自1970年1月1日午夜(格林尼治标准时间)以来的秒数。——使用4字节存储空间。

    通常使用TIMESTAMP,它比DATETIME更节约空间。有时人们把Unix的时间戳保存为整数值,但是这通常没有任何好处。——这种格式处理起来不太方便,我们并不推荐它。

     
     
     经验交谈
     
      1、我们在为列选择数据类型的时候,不仅要考虑存储类型大小,还要考虑MySQL如何对它们进行计算和比较。例如:MySQL在内部把ENUM和SET类型保存为整数,但是在比较的时候把它们转换为字符串。
     
      2、我们要在相关表中使用同样的类型,类型之间要精确匹配,包括诸如UNSIGNED这样的属性。
     
      3、混合不同的数据类型会导致性能问题,即使没有性能问题,隐式的类型转换也能导致难以察觉的错误。
     
      4、选择最小的数据类型要考虑将来留出的增长空间。如,中国的省份,我们知道不会有成千上万个,因此不必用INT。TINYINT就足够了,它比INT小3字节。
     
      5、整数通常是最佳的数据类型,因为它速度快,并且能使用AUTO_INCREMENT。
     
      6、要尽可能避免字符串做为列的数据类型,因为它们占用了很多空间并且通常必整数类型要慢。MyISAM默认情况下为字符串使用了压缩索引,这使查找更为缓慢。

    posted @ 2014-05-18 01:05 奋斗成就男人 阅读(194) | 评论 (0)编辑 收藏

    深入理解where 1=1的用处

    where 1=1有什么用?在SQL语言中,写这么一句话就跟没写一样。

    select * from table1 where 1=1与select * from table1完全没有区别,甚至还有其他许多写法,1<>2,'a'='a','a'<>'b',其目的就只有一个,where 的条件为永真,得到的结果就是未加约束条件的。

    在SQL注入时会用到这个,例如select * from table1 where name='lala'给强行加上select * from table1 where name='lala' or 1=1这就又变成了无约束的查询了。

    最近发现的妙用在于,在不定数量查询条件情况下,1=1可以很方便的规范语句。例如一个查询可能有name,age,height,weight约束,也可能没有,那该如何处理呢?

    String sql=select * from table1 where 1=1

    为什么要写多余的1=1?马上就知道了。

    if(!name.equals("")){
    sql=sql+"name='"+name+"'";
    }
    if(!age.equals("")){
    sql=sql+"age'"+age+"'";
    }
    if(!height.equals("")){
    sql=sql+"height='"+height+"'";
    }
    if(!weight.equals("")){
    sql=sql+"weight='"+weight+"'";
    }

    如果不写1=1呢,那么在每一个不为空的查询条件面前,都必须判断有没有where字句,否则要在第一个出现的地方加where

     

    where 1=1的写法是为了检化程序中对条件的检测
    打个比方有三个参数a, b, c
    @sql=select * from tb'
    这三个参数都可能为空
    这时你要构造语句的话,一个个检测再写语句就麻烦
    比如
    if @a is not null
    @sql=@sql + " where a=' + @a
    if @b is not null
    这里你怎么写?要不要加where 或直接用 and ?,你这里还要对@a是否为空进行检测

    用上 where 1=1 之后,就不存在这样的问题, 条件是 and 就直接and ,是or就直接接 or

    拷贝表
    create   table_name   as   select   *   from   Source_table   where   1=1;

    复制表结构
    create   table_name   as   select   *   from   Source_table   where   1 <> 1; 

    posted @ 2014-05-18 01:04 奋斗成就男人 阅读(245) | 评论 (0)编辑 收藏

    Groovy入门教程

         摘要: Groovy入门教程 kmyhy@126.com  2009-5-13 一、groovy是什么 简单地说,Groovy 是下一代的java语言,跟java一样,它也运行在 JVM 中。 作为跑在JVM中的另一种语言,groovy语法与 Java 语言的语法很相似。同时,Groovy 抛弃了java烦琐的文法。同样的语句,使用groovy能在最大限度上减少你的击键次数—R...  阅读全文

    posted @ 2014-04-25 23:23 奋斗成就男人 阅读(202) | 评论 (0)编辑 收藏

    response.encodeRedirectURL作用

    response.encodeRedirectURL作用

    session对象能和客户建立意义对应的关系依赖于客户的浏览器是否支持cookie,如果客户的浏览器不支持的话,那么客户再不同网页之间的session对象可能时互不相同的,因为服务器无法将ID存放到客户端,就不能建立session对象和客户的一一对应关系。可以通过URL重写来实现session对象的唯一性。所谓URL重写就是当客户从一个页面重新连接到一个页面时,通过向这个新的URL添加参数,把session对象的id传过去,这样能够保证session对象是完全相同的。可以使用response对象调用encodeURL()或encodeRedirectURL()方法实现URL重写。

    eg:

    String str=response.encodeRedirectURL("hope.jsp");

    连接目标写成:<%=str%>即可。

    encodeURL()是本应用级别的,encodeRedirectURL()是跨应用的。  

     

    以下时网上搜索到的解析:

    第一种解释:

    作用:

    Encodes the specified URL for use with redirect( ) by adding an necessary session ID.

    Example

    Response.redirect( Response( ).encodeRedirectURL( url ) )

    第二种解释:

    1.response.encodeRedirectURL(url)是一个进行URL重写的方法, 使用这个方法的作用是为了在原来的url后面追加上Jsessionid 。 目的是保证即使在客户端浏览器禁止了cookie的情况下,服务器端仍然能够对其进行事务跟踪.
    2.response.sendRedirect(url) 是一个url重定向的方法, 服务器端的通过该方法,“告诉”客户端的浏览器去访问url所指向的资源

    第三种解释:

    对于要进行跳转时把url   encode  
    如:   response.sendRedirect(response.encodeRedirectURL("dfddf.jsp?na=上海"));  
    不encode时getParameter("na")是乱码

    posted @ 2014-04-17 10:19 奋斗成就男人 阅读(256) | 评论 (0)编辑 收藏

    paypal几种集成方式有什么区别?

    paypal集成到网站一般有两种:Website Payment Standard WPS 网站付款专业版和 Express Checkout快速结账;

    但是有的用户也会问道 Website Payments Pro,这里就来给大家讲讲这三者的区别。

    一、Website Payment Standard WPS(IPN)网站标准版,客户需要在网站注册才可以完成购买流程。不会在购物车显示paypal按钮。

    二、Express Checkout快速结账专业版的与WPS主要区别是:check out为快速支付,在购物车页面直接显示paypal支付的按钮,可直接进入paypal页面付款,不注册成网店会员即可完成购买,但是也可以走正常的注册会员流程。

    三、Website Payments Pro需要是美国的账号才可以用。且收取月服务费用。

    另外美国账户在国内是无法享受客户服务和顾问服务的,一般的商家不建议使用



    注意:这三个paypal只能集成其中的一个,如果同时出现多个,会导致冲突,收款出错。

    一般的商家,如果有自己专业的技术团队,可选择Express Checkout,如果没有专门的技术维护,建议选择WPS.

    posted @ 2014-04-16 13:16 奋斗成就男人 阅读(523) | 评论 (0)编辑 收藏

    html里title属性换行的方法

    众所周知,对于链接和图片,我们可以通过添加title属性以显示一些说明文字,一般情况下,这些文字都是显示成一行,那么有没有办法让它以多行的方式显示呢?解决的方法有两种:

    1.将title属性分成几行来写,例如:
    <a href=#" title="说明一
    说明二
    说明三">印象派</a>

    2.第一行相对来说不够直观,我们还可以在需换行的地方添加 (将&改为半角,下同)或 来实现:
    <a href=#" title="说明一 说明二 说明三">印象派</a>
    <a href=#" title="说明一 说明二 说明三">印象派</a>



    ==================


    response.write " title='标    题:" & rsArticleList("Title") & vbcrlf & "作    者:" & rsArticleList("Author") & vbcrlf & "转 贴 自:" & rsArticleList("CopyFrom") & vbcrlf & "更新时间:" & rsArticleList("UpdateTime") & vbcrlf
        response.write "点 击 数:" & rsArticleList("Hits") & vbcrlf & "关 键 字:" & mid(rsArticleList("Key"),2,len(rsArticleList("Key"))-2) & vbcrlf & "推荐等级:"


    直接换行就可以


    =======================


    <a href='http://www.updateweb.cn' target='_ablank' title='标    题:更新网络
    作    者:Sundy
    转 贴 自:本站原创
    更新时间:2008-6-6 10:31:00
    点 击 数:0
    关 键 字:更新网络
    推荐等级:无
    分页方式:不分页
    阅读等级:游客
    阅读点数:0'>更新网络</a>
        <div title="123&quot; 456">text</div>
        <p><a href=#" title="说明一 说明二 说明三">印象派</a>
                    <a href=#" title="说明一 说明二 说明三">印象派</a></p>


    ===========================


    function decodeHTML(fString)
    if not isnull(fString) then
        fString = replace(fString, "&gt;", ">")
        fString = replace(fString, "&lt;", "<")


        fString = Replace(fString, "&nbsp;", CHR(32))
        fString = Replace(fString, "&nbsp;", CHR(9))
        fString = Replace(fString, "&quot;", CHR(34))
        fString = Replace(fString, CHR(39),"'")
        fString = Replace(fString, "</P><P> ",CHR(10) & CHR(10))
        fString = Replace(fString, "<BR> ", CHR(10))
        decodeHTML = fString
    end if
    end function


    function encodeHtml()


    替换成unicode字符就可以

    posted @ 2014-03-17 14:08 奋斗成就男人 阅读(175) | 评论 (0)编辑 收藏

    分享php中四种webservice实现的简单架构方法及实例

         摘要: 一:PHP本身的SOAP所有的webservice都包括服务端(server)和客户端(client)。要使用php本身的soap首先要把该拓展安装好并且启用。下面看具体的code首先这是服务端实现:PHP Code复制内容到剪贴板<?php   class test   {      &nb...  阅读全文

    posted @ 2014-03-11 18:52 奋斗成就男人 阅读(1424) | 评论 (0)编辑 收藏

    PHP获取客户端IP和服务器IP

    function get_client_ip() {
      if(getenv('HTTP_CLIENT_IP')){
          $client_ip = getenv('HTTP_CLIENT_IP');
      } elseif(getenv('HTTP_X_FORWARDED_FOR')) {
          $client_ip = getenv('HTTP_X_FORWARDED_FOR');
      } elseif(getenv('REMOTE_ADDR')) {
          $client_ip = getenv('REMOTE_ADDR');
      } else {
          $client_ip = $_SERVER['REMOTE_ADDR'];
      }
      return $client_ip;
    }

    获取服务器端IP地址

    function get_server_ip() {
    if (isset($_SERVER)) {
        if($_SERVER['SERVER_ADDR']) {
            $server_ip = $_SERVER['SERVER_ADDR'];
        } else {
            $server_ip = $_SERVER['LOCAL_ADDR'];
        }
    else {
        $server_ip = getenv('SERVER_ADDR');
    }
        return $server_ip;

    }

    posted @ 2014-03-07 18:20 奋斗成就男人 阅读(227) | 评论 (0)编辑 收藏

    打动面试官的五大技能

    如何让自己在面试中脱颖而出,给招聘人员留下深刻的影响,想必很多求职者都想过这类问题?本文作者通过对国外大中小的面试调查,发现他们看重面试者以下技能:定量分析、Excel、创造性思维、沟通能力和谦逊的品格。


    Becky Fisher是Beyond Business Summer Bootcamp公司的创始人,最近她总结了面试者在面试过程中招聘方最看重的技能。以下为译文: 

    不管你是大学生还是刚打算找工作,或是想在一个新的领域重新开始工作,你都该反问下自己:“我想找什么样的工作?”或者是“怎样才能获得一份更好的工作?”

    通过对Google、Amazon、Facebook这样的巨头公司,和类似Castlight、Room77的中小型企业的面试调查,我们发现,他们招聘员工时,看重很多技能,出人意料的是,他们并不看重员工是否精明。而他们特别需要的技能都是可以通过后天学习取得的。一起来看下可以让你从众多招聘者中脱颖而出的5个技能吧。

    1. 定量分析

    定量分析是对社会现象的数量特性、数量关系与数量变化的分析。数据是许多组织的重要组成部分,所以你的组织、分析、解释和呈现数据能力是很重要的。不管是在做应用程序还是寻找不同的办法来吸引用户。特别说明下,招聘公司很重视组织数据和基于数据进行组织的能力。如果你有挖掘数据的能力,并有自己的见解,那么在竞争中将很有优势。(面试时,你可以带上曾经做过的关于数据分析的项目)。

    技能获得方法:MOOCs是学习数据分析的重要资源。你可点击进入Exploratory Data AnalysisUdemy或者EdX,学习定量分析的方法。

    2. Excel

    管理数据分析中最主要工具是什么?Excel。Excel在工作中会经常遇到,而且公司不会花时间去教你怎样使用Excel。所以,如果你能精通Excel,在录取中也会占有一定的优势。

    技能获得方法:可以上网搜索下Excel的使用方法教程,或者点击进入微软免费的Excel视频教程,进入学习。

    3. 创造性思维

    当今企业界发展步伐异常快,招聘企业对那些有创新能力和能超越现状的求职者很感兴趣。他们希望自己的员工能够有拓展性思维,不安于现状,从第一天上班时起就能有与其他员工分享自己的想法,最好可以提高公司当前的工作系统。但是,创造性思维有点不好学习。

    技能获得方法:实际上,根本没有什么教程可以帮你提高创造性思维,但你可通过斯坦福大学的Design Thinking Class或者Creative Confidence进行学习。

    4. 沟通能力

    一般情况下,招聘公司都想找一些沟通能力比较强的员工。因为公司日后需要你可以有效的与客户进行电话、邮件及日常生活的交流,你的一言一行都将代表公司的形象。更重要的是,公司希望你能以简洁专业的语言来表达自己的某些看法。所以,在面试过程中,多向招聘人员展示下你的沟通能力。

    技能获得方法:多与他人进行沟通,可以提高你的沟通能力,而且还要听取别人的反馈意见。

    5. 谦逊的品格

    有人看到谦逊会觉得奇怪,但是这个技能却是招聘人员看中的重要技能之一。当然,招聘公司需要有自信、有激情,也要乐于学习的员工。在面试时,如果被要求分享自己的想法或主意的时候,大胆的说出来。如果被指出错误,虚心的接受。多问面试人员一些问题,比如公司的一些情况和应聘岗位的一些工作。

    技能获得方法:就像Nike说的,Just Do It。大方一点、谦逊,证明自己不仅工作灵活性强,还乐于接受别人的意见。最重要的是,还能把别人提的有利意见融入到工作中。

    posted @ 2014-02-28 01:40 奋斗成就男人 阅读(214) | 评论 (0)编辑 收藏

    7K月薪面试题----交通灯管理系统

         摘要: 【题目要求】模拟实现十字路口的交通灯管理系统逻辑,具体有以下需求1). 异步随机生成按照各个路线行驶的车辆举例说明如下:. 由南向北行驶的车辆 ----直行车辆. 由西向南行驶的车辆 ----右转车辆. 由东向南行驶的车辆 ----左转车辆…2). 信号灯颜色选择范围忽略黄灯,只考虑红灯和绿灯3). 左转车辆和右转车辆的要求. 左转车辆受到控制信号灯的控制. 但是右转车辆不受信号灯控制...  阅读全文

    posted @ 2014-02-28 01:36 奋斗成就男人 阅读(218) | 评论 (0)编辑 收藏

    Java 线程池的原理与实现

         摘要: 这几天主要是狂看源程序,在弥补了一些以前知识空白的同时,也学会了不少新的知识(比如 NIO),或者称为新技术吧。线程池就是其中之一,一提到线程,我们会想到以前《操作系统》的生产者与消费者,信号量,同步控制等等。一提到池,我们会想到数据库连接池,但是线程池又如何呢?建议:在阅读本文前,先理一理同步的知识,特别是syncronized同步关键字的用法。关于我对同步的认识,要缘于大三年的一本书,书名好像...  阅读全文

    posted @ 2014-02-28 01:32 奋斗成就男人 阅读(224) | 评论 (0)编辑 收藏

    7K月薪面试题----银行业务调度系统

         摘要: 题目要求:银行业务调度系统模拟实现银行业务调度系统逻辑,具体需求如下:*银行内有6个业务窗口,1 - 4号窗口为普通窗口,5号窗口为快速窗口,6号窗口为VIP窗口。*有三种对应类型的客户:VIP客户,普通客户,快速客户(办理如交水电费、电话费之类业务的客户)。*异步随机生成各种类型的客户,生成各类型用户的概率比例为:VIP客户 :普通客户 :快速客户  =  1 :6 :3。*...  阅读全文

    posted @ 2014-02-28 01:31 奋斗成就男人 阅读(246) | 评论 (0)编辑 收藏

    Tomcat配置多域名绑定和虚拟目录

    tomcat采用默认安装,要想tamcat直接绑定多个域名,这里我们需要修改配置文件:C:\Program Files\Apache Software Foundation\Tomcat 5.5\conf\server.xml

    server.xml 的修改方式如下:

    (一)多域名绑定

    1.如果你要绑定网站,首先是要把tomcat的默认访问端口8080,修改成80

    原始:
    <Connector port="8080" maxHttpHeaderSize="8192" maxThreads="150" minSpareThreads="25" maxSpareThreads="75" enableLookups="false" redirectPort="8443" acceptCount="100" connectionTimeout="20000" disableUploadTimeout="true" />

    修改后:
    <Connector port="80" maxHttpHeaderSize="8192" maxThreads="150" minSpareThreads="25" maxSpareThreads="75" enableLookups="false" redirectPort="8443" acceptCount="100" connectionTimeout="20000" disableUploadTimeout="true" />

    其实这里就是把port:8080,修改成port:80就可以了,其他的参数不变

    2.接下来就是重点了哈哈...
    原始:
    <Engine name="Catalina" defaultHost="localhost">
    <Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true" xmlValidation="false" xmlNamespaceAware="false" /> 
    </Engine>
    当然这里我把注释代码统统删除掉了,省的碍眼

    修改后:
    <Engine name="Catalina" defaultHost=www.abc.com>

    <Host name="www.abc.com" appBase=="abcapps" unpackWARs="true" autoDeploy="true" xmlValidation="false" xmlNamespaceAware="false"

    <Host name=www.cba.com appBase=="D:\cba" unpackWARs="true" autoDeploy="true" xmlValidation="false" xmlNamespaceAware="false" />

    <Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true" xmlValidation="false" xmlNamespaceAware="false"   />
    </Engine>

    这里解释一下上面的配置
    Engine 的 dafaultHost :表示访问该tomcat默认进入的主机,注意一定不能是localhost,不然别人通过你的ip访问,就会默认进入tomcat的管理界面.

    Host 的 name:表示该主机绑定的域名,如果绑定localhost则可以通过在浏览器中输入localhost访问该Host.

    Host的 appBase:表示该主机绑定的文件存放路径,可以使用相对路径或绝对路径.

    按照上面的配置:
    1.如果我在浏览器中输入http://localhost 则访问 C:\Program Files\Apache Software Foundation\Tomcat 5.5\webapps\ROOT 下的网站
    2.如果输入http://www.abc.com 则访问 C:\Program Files\Apache Software Foundation\Tomcat 5.5\abcapps\ROOT 下的网站
    3.如果输入http://www.cba.com 则访问 D:\cba\ROOT 下的网站.

    注意这里有一个ROOT目录需要创建,我们只要把网站放到相应的ROOT目录向下面,即可通过相应域名访问了.

    这里面的参数还有很多,我也不是很清楚,不过这样做确实可以实现多域名绑定哈哈.而且网站页面修改了只要直接覆盖就可以了,tomcat可以自动更新类和页面,当然如果修改了web.xml或lib,则需要重启tomcat才可以.

    (二)虚拟目录

    <Host name="localhost" appBase="webapps"
            unpackWARs="true" autoDeploy="true"
            xmlValidation="false" xmlNamespaceAware="false">
    <Context path="/cqq" docBase="f:\java\cqqapp" debug="0" reloadable="true" crossContext="true"> 
       </Host>

    其中,Host标记是用来配置虚拟主机的,就是可以多个域名指向一个tomcat,格式只要参考默认的就

    可以了。

    <context>是Host标记的子元素吧,表示一个虚拟目录,它主要有两个属性,path就相当于虚拟目录名字,

    而 docbase则是具体的文件位置。在这里我的虚拟路径名称为cqq,实际上我的程序也就是html、jsp、

    servlet都 放在了f:\java\cqqapp这个目录下了。

    这样我就可以通过 http://127.0.0.1/cqq/ 访问我的这个虚拟目录了。

    另外一种方法是:

    配置两个站点
    <Host name="www.xyz.com" debug="0" appBase="D:\Tomcat5.5\portal" unpackWARs="true" autoDeploy="true"> 
    <Context path="" docBase="D:/Tomcat5.5/portal" debug="0" reloadable="true"/> 
    </Host>

    <Host name="www.abc.com" appBase="D:\Tomcat5.5\hxw"
            unpackWARs="true" autoDeploy="true"
            xmlValidation="false" xmlNamespaceAware="false">
    <Context path="" docBase="D:\Tomcat5.5\abc" debug="0" reloadable="true"/> 
    </Host>

    这样设置以后,输入域名可以分别到两个站点

    但由于没有指定默认站点,所以直接输入IP的时候,无法访问。

    于是增加 D:\Tomcat5.5\conf\Catalina\localhost\ROOT.xml
    内容如
    <Context path="/" docBase="${catalina.home}/portal" debug="5" reloadable="true" crossContext="true">
    </Context>

    这样可以实现输入域名分别到个站点,输入IP就默认到D:/Tomcat5.5/portal这个站点

    可是,可是,问题出现了

    这两个站点启动相当消耗内存,TOMCAT内存设置我已经设到1400M了(再高TOMCAT5无法启动),所以不能同时启动三个应用。

    posted @ 2014-02-28 01:22 奋斗成就男人 阅读(283) | 评论 (0)编辑 收藏

    PHP和Ajax实现二级联动下拉菜单(代码、详细注释)

    数据库
    .

    .
    test.html
    ..
    <html>
    <head><title>php_ajax联动下拉菜单</title>
    <meta http-equiv="content-type" content="text/html;charset=gb2312">
    <script language="javascript" src="ajax.js"></script>
    <script language="javascript">
    function query(){
    var pid = document.getElementByIdx("bigClassName").value;
    if(pid!=""){
       createRequest('query.php?pid='+pid);
    }
    }
    </script>
    </head>
    <body>
    <form action="<?=$PHP_SELF?>?" name="class" method="get" >
    <select name="bigClassName" id="bigClassName" onchange="query()">
    <option value="">--选择大类--</option>
    <?php
    $link=mysql_connect("localhost","root","root");
    mysql_select_db("sortclass") or die("没有此数据库!");
    $sql="select cid,cname from class where pid=0";
    mysql_query("set names gb2312");
    $res=mysql_query($sql,$link);
    while($result=mysql_fetch_assoc($res)){
       echo "<option value='".$result["cid"]."'>".$result["cname"]."</option>";
    }
    ?>
    </select>
    &nbsp;
    <select name="smallClassName" id="smallClassName">
    <option value="">--选择小类--</option>
    </select>
    <input type="submit" value="提交" />
    </form>
    </body>
    </html>
    .
    ajax.js
    .
    var http_request = false;
    function createRequest(url) {
    //初始化对象并发出XMLHttpRequest请求
    http_request = false;
    if (window.XMLHttpRequest) {            //Mozilla等其他浏览器
       http_request = new XMLHttpRequest();
       if (http_request.overrideMimeType) {
        http_request.overrideMimeType("text/xml");
       }
    else if (window.ActiveXObject) {          //IE浏览器
       try {
        http_request = new ActiveXObject("Msxml2.XMLHTTP");
       } catch (e) {
        try {
         http_request = new ActiveXObject("Microsoft.XMLHTTP");
         } catch (e) {}
       }
    }
    if (!http_request) {
       alert("不能创建XMLHTTP实例!");
       return false;
    }
    http_request.onreadystatechange = alertContents;         //指定响应方法

    http_request.open("GET", url, true);         //发出HTTP请求
    http_request.send(null);
    }
    function alertContents() {                   //处理服务器返回的信息
    if (http_request.readyState == 4) {
       if (http_request.status == 200) {
        var smallClassName=document.getElementByIdx("smallClassName");
        var dataArray=[];
        //alert(http_request.responseText);
        myVariable=http_request.responseText;//形如: 1,新闻中心;2,学习园地;
        var stringArray = myVariable.split(";");//以;分隔字符串
        stringArray.pop();//移除数组最后一个元素,stringArray[0]==1,新闻中心 stringArray[1]==2,学习园地   
        var len=stringArray.length;
        for(var i=0;i<len;i++){   
         dataArray[i]= stringArray[i].split(",");// 循环数据条数按,分割字符串
        }
        //alert(dataArray[1][0]);//返回 新闻中心
        
    //初始化smallClassName的数据
        smallClassName.length=0;
        var alertOption=document.createElement_x("OPTION");
        alertOption.value="";
        alertOption.text="--选择小类--";
        smallClassName.add(alertOption);
       
        for(var j=0;j<len;j++){//添加数据
           var objOption=document.createElement_x("OPTION");
         objOption.value = dataArray[j][0];
         objOption.text = dataArray[j][1];
         smallClassName.add(objOption);
        }
       
       } else {
        alert('您请求的页面发现错误');
       }
    }
    }
    ..
    query.php
    ..
    <?php
    error_reporting(E_ERROR|E_WARNING|E_PARSE);
    $link=mysql_connect("localhost","root","root");
    mysql_select_db("sortclass",$link) or die("no such database!");
    //$GB2312string=iconv( 'UTF-8', 'gb2312//IGNORE' , $RequestAjaxString);    //Ajax中先用encodeURIComponent对要提交的中文进行编码
    mysql_query("set names gb2312");
    $pid=$_GET[pid];
    $res=mysql_query("select cid,cname from class where pid='$pid'",$link);
    header('Content-type: text/html;charset=GB2312');   //指定发送数据的编码格式为GB2312
    while($info=mysql_fetch_array($res)){
       $str.=$info["cid"].",".$info["cname"];
       $str.=";";
    }
    echo $str;
    ?>

    posted @ 2014-02-28 01:12 奋斗成就男人 阅读(891) | 评论 (0)编辑 收藏

    cookie的加强加深

    1、什么是cookie?

    0Cookie技术是一个非常有争议的技术,自经诞生它就成了广大网络用户和Web开发人员的一个争论焦点。有一些网络用户,甚至包括一些资深的Web专家也对它的产生和推广感到不满,这倒不是因为Cookie技术的功能太弱或别的技术性能上的原因,而仅仅是因为他们觉得Cookie的使用,对网络用户的隐私构成了危害。因为Cookie是由Web服务器保存在用户浏览器上的小文本文件,它包含有关用户的信息(如身份识别号码、密码、用户在Web站点上购物的方式或用户访问该站点的次数)。

        那么Cookie技术究竟怎样呢?是否真的给网络用户带来了个人隐私的危害呢?还是让我们看了下面的内容,再做回答吧。

          在WEB技术发展史上,Cookie技术的出现是一个重大的变革。最先是Netscape在它的Netscape Navigator 浏览器中引入了Cookie技术,从那时起,World Wide Web 协会就开始支持Cookie标准。以后又经过微软的大力推广(因为微软的IIS Web服务器所采用的ASP技术很大程度的使用了Cookie技术),即在微软的Internet Explorer浏览器中完全支持Cookie技术。到现在,绝大多数的浏览器都支持Cookie技术,或者至少兼容Cookie技术的使用。

          按照Netscape官方文档中的定义,Cookie是在HTTP协议下,服务器或脚本可以维护客户工作站上信息的一种方式。Cookie是由Web服务器保存在用户浏览器上的小文件,它可以包含有关用户的信息(如身份识别号码、密码、用户在Web站点购物的方式或用户访问该站点的次数)。无论何时用户链接到服务器,Web站点都可以访问Cookie信息。

       如果你使用的是windows系统,那么请打开C:\Documents and Settings\用户名\Cookies,你会发现该目录下有好多*.txt格式的小文件。那就是cookie文件。当然,在该目录下你也可能什么都发现不了,那时因为你新装了系统或者从未浏览过因特网,也或者你的浏览器禁用了cookie。否则该目录下总会有点东西的。

         通俗地讲,浏览器用一个或多个限定的文件来支持Cookie。这些文件在使用Windows操作系统的机器上叫做Cookie文件,在Macintosh 机器上叫做magic Cookie 文件,这些文件被网站用来在上面存储Cookie数据。网站可以在这些Cookie文件中插入信息,这样对有些网络用户就有些副作用。有些用户认为这造成了对个人隐私的侵犯,更糟的是,有些人认为Cookie是对个人空间的侵占,而且会对用户的计算机带来安全性的危害。

         目前有些Cookie是临时的,另一些则是持续的。临时的Cookie只在浏览器上保存一段规定的时间,一旦超过规定的时间该Cookie就会被系统清除。例如在PHP中Cookie被用来跟踪用户进程直到用户离开网站。持续的Cookie则保存在用户的Cookie文件中,下一次用户返回时,仍然可以对它进行调用。

         在Cookie文件中保存Cookie,一些用户会过分地认为这将带来很大的问题。主要是有些用户担心Cookie会跟踪用户网上冲浪的习惯,譬如用户喜爱到那些类型的站点、爱从事些什么活动等。害怕这种个人信息一旦落入一些别有用心的家伙手中,那么个人也就可能成为一大堆广告垃圾的对象,甚至遭到意外的损害。不过,这种担心压根儿不会发生,因为网站以外的用户是无法跨过网站来获得Cookie信息的。所以想以这种目的来应用Cookie是不可能的。不过,由于一些用户错误的理解以及“以讹传讹”,一些浏览器开发商别无选择,只好作出相适的响应(例如Netscape Navigator4.0和Internet Explorer3.0都提供了屏蔽Cookie的选项)。个人认为,无风不起浪,如果网站程序员没有严谨思路的话,cookie确实也存在些许安全问题,不过这些瑕疵并不足以掩盖cookie的优秀品质,大多数人还是非常乐意使用它的。

         对Cookie技术期待了这么久的结果是,迫使许多浏览器开发商在它们的浏览器中提供了对Cookie的灵活性控制功能。例如,目前的两大主流浏览器 Netscape Navigator 和 Internet Explorer是这样处理Cookie的:Netscape Navigator4.0不但可以接受Cookie进行警告,而且还可以屏蔽掉Cookie;InternetExplorer3.0也可以屏蔽 Cookie,但在Internet Explorer4.0中就只能进行接受警告而没有提供屏蔽选项,不过在Internet Explorer4.0之后的更新版本中又加入了屏蔽Cookie的功能选项。

         此外,很多最新的技术甚至已经可以在不能屏蔽Cookie的浏览器上进行Cookie的屏蔽了。例如,可以通过将Cookie文件设置成不同的类型来限制 Cookie的使用。但是,非常不幸地是,要是你想完全屏蔽Cookie的话,肯定会因此拒绝许多的站点页面。因为当今已经有许多Web站点开发人员爱上了Cookie技术的强大功能,例如Session对象的使用就离不开Cookie的支持。

    2、Cookie工作原理?

        当客户访问某个基于PHP技术的网站时,在PHP中可以使用setcookie函数生成一个cookie,系统经处理把这个cookie发送到客户端并保存在C:\Documents and Settings\用户名\Cookies目录下。cookie是 HTTP标头的一部分, 因此setcookie函数必须在任何内容送到浏览器之前调用。这种限制与header()函数一样(如需了解head()函数,请自行查阅)。当客户再次访问该网站时,浏览器会自动把C:\Documents and Settings\用户名\Cookies目录下与该站点对应的cookie发送到服务器,服务器则把从客户端传来的cookie将自动地转化成一个 PHP变量。在PHP5中,客户端发来的cookie将被转换成全局变量。你可以通过$_COOKIE[‘xxx’]读取。

         尽管今天仍有一些网络用户对于Cookie的争论乐此不倦,但是对于绝大多数的网络用户来说还是倾向于接受Cookie的。因此,我们尽可以放心地使用Cookie技术来开发我们的WEB页面。

    3、Cookie常见函数

    ● SetCookie 函数创建了一个Cookie,并且把它附加在HTTP头的后面。必须注意的一点是:Cookie是HTTP协议头的一部分,用于浏览器和服务器之间传递信息,所以必须在任何属于HTML文件本身的内容输出之前调用SetCookie函数,调用该函数前即使有空格、空白行都不行。如果setCookie()认了第二,就没有哪个元素敢认第一。使用setcookie()函数的前提是客户浏览器支持cookie,如果客户将之禁用的话,setcookie()也就英雄无用武之地了。

       int SetCookie(string name, string value, int expire, string path, string domain, int secure,bool httponly);

    参数说明:

       name;设置cookie变量的名称。

       value;设置cookie的值。

       expire;设置cookie过期时间。如果要把cookie保存为浏览器进程,即浏览器关闭后就失效。那么可以直接把expiretime设为0。 Eg:setcookie(“name”,”value”,0)。该参数不设置的话,关闭浏览器也能结束一个cookie。

        path:表示web服务器上的目录,默认为被调用页面所在目录. 这里还有一点要说明的,比如你的站点有几个不同的目录(比如一个购物目录,一个论坛目录),那么如果只用不带路径的Cookie的话,在一个目录下的页面里设的Cookie在另一个目录的页面里是看不到的,也就是说,Cookie是面向路径的。实际上,即使没有指定路径,WEB服务器会自动传递当前的路径给浏览器的,指定路径会强制服务器使用设置的路径。解决这个问题的办法是在调用 SetCookie时加上路径和域名,域名的格式可以是“http://www.phpuser.com/”,也可是“.phpuser.com”。 SetCookie函数里表示value的部分,在传递时会自动被encode,也就是说,如果value的值是“test value”在传递时就变成了“test%20value”,跟URL的方法一样。当然,对于程序来说这是透明的,因为在PHP接收Cookie的值时会自动将其decode。

        domain:cookie可以使用的域名,默认为被调用页面的域名。这个域名必须包含两个".",所以如果你指定你的顶级域名,你必须用 ".mydomain.com" 。设定域名后,必须采用该域名访问网站cookie才有效。如果你使用多个域名访问该页,那么这个地方可以为空或者访问这个cookie的域名都是一个域下面的。

        secure:如果设为"1",表示cookie只能被用户的浏览器认为是安全的服务器所记住。

        除了name之外所有的参数都是可选的。value,path,domain三个参数可以用空字符串""代换,表示没有设置;expire 和 secure两个参数是数值型的,可以用0表示。expire参数是一个标准的Unix时间标记,可以用time()或mktime()函数取得,以秒为单位。secure参数表示这个Cookie是否通过加密的HTTPS协议在网络上传输。

        httponly:如果设为1,则表示cookie只能被http协议所使用,任何脚本语言,比如javascrīpt是不能获取PHP所创建的 cookie的,这就有效削弱了来自XSS的攻击。(注意了:这是PHP5才有的选项,咱也没有用过。看了官方手册尝试着翻译的,如有疑问,请参考官方手册。)

       当前设置的Cookie不是立即生效的,而是要等到下一个页面或刷新后才能看到.这是由于在设置的这个页面里Cookie由服务器传递给客户浏览器,在下一个页面或刷新后浏览器才能把Cookie从客户的机器里取出传回服务器的原因。

    小道消息

    Cookie应用案例:

    ●创建一个cookie:

    SetCookie()

    ●创建cookie数组:

    其一:

    SetCookie("CookieArray[]", "Value 1");

    SetCookie("CookieArray[]", "Value 2");

    其二:

    SetCookie("CookieArray[0]", "Value 1");

    SetCookie("CookieArray[1]", "Value 2");

    ● 接收和处理Cookie

    PHP对Cookie的接收和处理的支持非常好,是完全自动的,跟GET,POST变量的原则一样,特别简单。

    比如设置一个名为MyCookier的Cookie,PHP会自动从WEB服务器接收的HTTP头里把它分析出来,并形成一个可直接使用的全局变量,名为$_COOKIE[‘MyCookie’],这个变量的值就是Cookie的值。数组同样适用。

    分别举例如下:(假设这些都在以前的页面里设置过了,并且仍然有效)

    echo $_COOKIE[‘MyCookie’];

    取出cookie数组的例子:

    <?php

    // 创建一个cookie数组

    setcookie("cookie[three]", "cookiethree");

    setcookie("cookie[two]", "cookietwo");

    setcookie("cookie[one]", "cookieone");

    // 页面刷新之后,用foreach提取cookie数组。

    if (isset($_COOKIE['cookie'])) {

    foreach ($_COOKIE['cookie'] as $name => $value) {

       echo "$name : $value <br />\n";

    }

    }

    ?>

    就这么简单。

    ● 删除Cookie

        要删除一个已经存在的Cookie,有两个办法:

    1、调用只带有name参数的SetCookie,那么名为这个name的Cookie将被从关系户机上删掉;

    setcookie(“MyCookie”); //删除MyCookie。

    2、设置Cookie的失效时间为time()或time()-1//time()减多少没有关系啦,只要是过期时间就行//,那么这个Cookie在这个页面的浏览完之后就被删除了(其实是失效了)。例如:

        setcookie(“MyCookie”,”Value”,time()-1); //删除MyCookie。

    要注意的是,当一个Cookie被删除时,它的值在当前页在仍然有效的。

        如果要把cookie保存为浏览器进程,即浏览器关闭后就失效。那么可以直接把expiretime设为0。例如:setcookie(“name”,”value”,0)。该参数不设置的话,关闭浏览器也能结束一个cookie。

    Cookie注意事项

    1、SetCookie()之前不能有任何html输出,它认了第二,没有哪个元素敢认第一,就是空格,空白行都不行。

    2、SetCookie()后,你在当前页调用echo $_COOKIE["name"]不会有输出。必须刷新或到下一个页面才可以看到Cookie值。原因很简单。SetCookie()执行之后,往客户端发送一个cookie,你不刷新或浏览下一个页面,客户端怎么把cookie给你送回去呀?浏览器创建了一个Cookie后,对于每一个针对该网站的请求,都会在Header中带着这个Cookie;不过,对于其他网站的请求Cookie是绝对不会跟着发送的。而且浏览器会这样一直发送,直到 Cookie过期为止。

    3、使用Cookie的限制。一个浏览器能创建的Cookie数量最多为30个,并且每个不能超过4KB,每个WEB站点能设置的Cookie总数不能超过20个。 (这是书上看到的说法,应该是一个web站点能创建的Cookie不能超过30个吧,要不然,我机子里的cookie少说也上百了,请达人指教!)

    4、Cookie是保存在客户端的,用户禁用了Cookie,你的Cookie自然也就没作用啦!现在的浏览器,每当咱发送一个Cookie给客户端,他就像看门狗一样给拦截住了,并询问用户是否允许Cookie进门。天,用户又不是专家,有几个人知道啥叫Cookie呀?搞不好都当病毒拒之门外了。

    posted @ 2014-02-28 01:11 奋斗成就男人 阅读(185) | 评论 (0)编辑 收藏

    实现验证码的代码(有注释)教会你怎样实现验证码!

    <?php
    $im = imagecreatetruecolor(80,23);//创建画布
    $bgcolor = imagecolorallocate($im,220,230,230);//调制背景色
    $bordercolor = imagecolorallocate($im,0,0,255);//调制边框颜色
    $tcolor = imagecolorallocate($im,255,0,0);
    $green = imagecolorallocate($im,0,255,0);
    imagefill($im,10,10,$bgcolor);//填充背景色
    imagerectangle($im,1,1,79,22,$bordercolor);//绘制边框
    for($i = 0;$i < 4; $i++){

    $num_case = rand(0,2);//产生随机数0-2,根据数值的不同决定产生的是数字|小写|大写
    switch($num_case){
     case 0:$num = rand(48,57);break;//数字
     case 1:$num = rand(65,90);break;//大写
     default:$num = rand(97,122);//小写
     
     }

    $text[$i] = sprintf("%c",$num);//将随机产生的ASCII码转换为相应的字符
    imagettftext($im,rand(10,20),rand(0,30),15*$i+5,20,$tcolor,"simkai.ttf",$text[$i]);//显示字符
    }
    for($i=0;$i<100;$i++){
    imagesetpixel($im,rand(1,79),rand(1,22),$green);
    }
    session_start();
    $_SESSION["ckcode"]=implode($text);
    header("Content-type:image/png");//设置输出类型
    imagepng($im);//输出图像
    imagedestroy($im);

    posted @ 2014-02-28 01:06 奋斗成就男人 阅读(184) | 评论 (0)编辑 收藏

    计算器简单实现

    <html>
    <head>
    <script>
      var flag = true;
      function getNum(num){
        if(!flag){
        document.getElementById('res').value = '';
        flag = true;
     }
        document.getElementById('res').value += num;
      }
      function getResult(){
        var result = eval(document.getElementById('res').value);
     document.getElementById('res').value = result;
     flag = false;
      }
    </script>
    </head>
    <body>
    <table border='1px' width='300px'>
    <caption>计算器</caption>
    <tr>
     <td colspan='4'><input type='text' id='res' size=47></td>
     
    </tr>
    <tr>
     <td><input type='button' value='1' style="width:75px" onclick="getNum(1)"></td>
     <td><input type='button' value='2' style="width:75px" onclick="getNum(2)"></td>
     <td><input type='button' value='3' style="width:75px" onclick="getNum(3)"></td>
     <td><input type='button' value='+' style="width:75px" onclick="getNum('+')"></td>
    </tr>
    <tr>
     <td><input type='button' value='4' style="width:75px" onclick="getNum(4)"></td>
     <td><input type='button' value='5' style="width:75px" onclick="getNum(5)"></td>
     <td><input type='button' value='6' style="width:75px" onclick="getNum(6)"></td>
     <td><input type='button' value='-' style="width:75px" onclick="getNum('-')"></td>
    </tr>
    <tr>
     <td><input type='button' value='7' style="width:75px" onclick="getNum(7)"></td>
     <td><input type='button' value='8' style="width:75px" onclick="getNum(8)"></td>
     <td><input type='button' value='9' style="width:75px" onclick="getNum(9)"></td>
     <td><input type='button' value='*' style="width:75px" onclick="getNum('*')"></td>
    </tr>
    <tr>
     <td><input type='button' value='0' style="width:75px" onclick="getNum(0)"></td>
     <td><input type='button' value='.' style="width:75px" onclick="getNum('.')"></td>
     <td><input type='button' value='=' style="width:75px" onclick="getResult()"></td>
     <td><input type='button' value='/' style="width:75px" onclick="getNum('/')"></td>
    </tr>
    </table>
    </body>
    </html>

    posted @ 2014-02-28 01:05 奋斗成就男人 阅读(175) | 评论 (0)编辑 收藏

    php上传思路很重要 举一反三

    1、FORM标签enctype属性
    表单中enctype="multipart/form-data"的意思,是设置表单的MIME编码。默认情况,
    这个编码格式是application/x-www-form-urlencoded,不能用于文件上传;
    只有使用了multipart/form-data,才能完整的传递文件数据
    <form enctype="multipart/form-data" method="post" name="upform">
    input标签 type 属性中的  "file"
    <input name="upfile" type="file">

    2、$_FILES 系统函数
    $_FILES['myFile']['name']   客户端文件的原名称。
    $_FILES['myFile']['type']   文件的 MIME 类型,例如"image/gif"。
    $_FILES['myFile']['size']   已上传文件的大小,单位为字节。
    $_FILES['myFile']['tmp_name']   储存的临时文件名,一般是系统默认。
    $_FILES['myFile']['error']   该文件上传相关的错误代码。

    3、move_uploaded_file函数
    上传后移动文件到目标位置的函数
    move_uploaded_file(临时文件,目标位置和文件名);

    4、is_uploaded_file 函数
    判断上传MIME类型的文件函数

    posted @ 2014-02-28 00:59 奋斗成就男人 阅读(203) | 评论 (0)编辑 收藏

    PHP通过使用工具类(PHPExcel)从操作数据库和Excel表

    关于用PHPExcel从数据库表导出到Excel表
    在网上查了好多关于这方面的资料,今天终于把这个问题解决了。
    我个人感觉 PHPExcel还是很好用的,首先到官方网站http://phpexcel.codeplex.com/下载最近版本的PHPExcel,解压后会发现里面有class、
    Documentation、Tests三个文件夹和三个txt的日志文件,主要用到的是Class文件,而Tests主要是一些demo示例
    下面来介绍一下PHPExcel的简单用法,这里是与数据库连接的:
    首先,要包含PHPExcel.php
    require_once 'Classes/PHPExcel.php';          //路径根据自己实际项目的路径进行设置
    $objPHPExcel = new PHPExcel();  //创建PHPExcel实例
    //下面是对mysql数据库的连接   
    $conn = mysql_connect("localhost","root","") or die("数据库连接失败!");   
    mysql_select_db("image",$conn);               //连接数据库
    mysql_query("set names 'GBK'");               //转换字符编码
    $sql = mysql_query("select * from test");     //查询sql语句
    /*
    --------------设置表头信息------------------*/
    $objPHPExcel->setActiveSheetIndex(0)
    ->setCellValue('A1', 'ID编号')
    ->setCellValue('B1', '月份')
    ->setCellValue('C1', '产品一')
    ->setCellValue('D1', '产品二')
    ->setCellValue('E1', '产品三');
    /*--------------开始从数据库提取信息插入Excel表中------------------*/
    $i=2;                //定义一个i变量,目的是在循环输出数据是控制行数
    while($rs=mysql_fetch_array($sql)){
    $rm = iconv("GB2312","UTF-8",$rs[1]);                 //对字符进行编码将数据库里GB2312的中文字符转换成UTF-8格式
    $objPHPExcel->setActiveSheetIndex(0)
    ->setCellValue("A".$i, $rs[0])
    ->setCellValue("B".$i, $rm)
    ->setCellValue("C".$i, $rs[2])
    ->setCellValue("D".$i, $rs[3])
    ->setCellValue("E".$i, $rs[4]);          
    $i++;
    }
    /*--------------下面是设置其他信息------------------*/
    $objPHPExcel->getActiveSheet()->setTitle('Example1');      //设置sheet的名称
    $objPHPExcel->setActiveSheetIndex(0);                      //设置sheet的起始位置
    $objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel5');   //通过PHPExcel_IOFactory的写函数将上面数据写出来
    $objWriter->save(str_replace('.php', '.xls', __FILE__));     //设置以什么格式保存,及保存位置
    至此,一个完整的将mysql数据库里的信息用PHP导出Excel实例做完,可能在运行的时候会发生一些问题,
    如中文乱码,表头可能显示不出来,这是因为文件编码格式的原因,将文件编码设置成UTF-8就行了,在此我就不做太多解释了。


    二: PHPExcel从excel表导入到mysql数据库 

    error_reporting(E_ALL);
    require './Common/Extend/Classes/PHPExcel.php';
    require './Common/Extend/Classes/PHPExcel/Reader/Excel2007.php';
    require './Common/Extend/Classes/PHPExcel/Reader/Excel5.php';
    $info =  $upload->getUploadFileInfo();
    $filepath = "./Upimg/".$info[0][savename];
    $PHPExcel = new PHPExcel();
    $PHPReader = new PHPExcel_Reader_Excel2007();
    $PHPExcel = $PHPReader->load($filepath);
    $sheet = $PHPExcel->getActiveSheet();
    $allCol=PHPExcel_Cell::columnIndexFromString($sheet->getHighestColumn());
    $allRow=$sheet->getHighestRow();
    $M=new Model;
    for($j=2;$j<=$allRow;$j++){
    $a = $PHPExcel->getActiveSheet()->getCell("A".$j)->getValue();//获取A列的值
    $b = $PHPExcel->getActiveSheet()->getCell("B".$j)->getValue();//获取B列的值
    $c = $PHPExcel->getActiveSheet()->getCell("C".$j)->getValue();//获取C列的值
    $d = $PHPExcel->getActiveSheet()->getCell("D".$j)->getValue();//获取D列的值
    $e = $PHPExcel->getActiveSheet()->getCell("E".$j)->getValue();//获取E列的值
    $f = $PHPExcel->getActiveSheet()->getCell("F".$j)->getValue();//获取F列的值
    $g = $PHPExcel->getActiveSheet()->getCell("G".$j)->getValue();//获取G列的值
    $h = $PHPExcel->getActiveSheet()->getCell("H".$j)->getValue();//获取X列的值
    $i = $PHPExcel->getActiveSheet()->getCell("I".$j)->getValue();//获取I列的值
    $jj = $PHPExcel->getActiveSheet()->getCell("J".$j)->getValue();//获取J列的值
    $k = $PHPExcel->getActiveSheet()->getCell("K".$j)->getValue();//获取K列的值
    $l = $PHPExcel->getActiveSheet()->getCell("L".$j)->getValue();//获取L列的值
    $m = $PHPExcel->getActiveSheet()->getCell("M".$j)->getValue();//获取M列的值
    $n = $PHPExcel->getActiveSheet()->getCell("N".$j)->getValue();//获取N列的值
    $p = $PHPExcel->getActiveSheet()->getCell("P".$j)->getValue();//获取P列的值
    $qq = $PHPExcel->getActiveSheet()->getCell("Q".$j)->getValue();//获取Q列的值
    $r = $PHPExcel->getActiveSheet()->getCell("R".$j)->getValue();//获取R列的值
    $sql="insert into law_constant(true_name,email,sex,birthday,certificate_num,first_date,law_firm_name,law_firm_address,lawer_xueli,professional,school,work_year,occup_language,word_experience,hobbies) values('".$c."','".$p."','".$d."','".$jj."','".$b."','".$e."','".$f."','".$h."','".$i."','".$k."','".$l."','".$m."','".$n."','".$qq."','".$r."');";
    $res=$M->query($sql);
    }
    if($res[0]==''){
    $this->success("导入数据库成功!",'__APP__/Lawerinfo/index');
    }else{
    $this->error("导入数据库失败!","__APP__/Lawerinfo/index");
    }
    }
    }
    }


    posted @ 2014-02-28 00:54 奋斗成就男人 阅读(571) | 评论 (0)编辑 收藏

    这篇文章值1500万元左右

    我的学历不高,不过就是一个路上比比皆是的专科生而已,再加上家中没
      
    有恒产,所以很早就出脱离学生单纯的生活,到处在为三餐温饱打拼。
      
    在这十几年的工作历程中,只有在从事业务行销工作时让我的年收入达到
      
    了千万,不仅有了进口豪华轿车,还拥有了独栋透天别墅,而当时我也不
      
    过才三十岁左右。
      
    今天在版面上看到有人批评业务工作的种种不是,其实我有着深刻的亲身
      
    经历,当各位业务急先锋在市场上真枪实弹搏斗时,低声下气根本就是一
      
    种太肤浅的形容词,请问有人被狗追过吗?有人被人家用扫把扫出来过吗
      
    ?如果没有,那我认为应该还需要再加强磨练一番。
      
    我认为干业务的绝对不需要跟人低声下气,除非你愿意跟人低声下气;业
      
    务工作是一个正正当当的职业,名片上印有响当当的头衔,不偷不抢没什
      
    么好丢脸的;没有业务的招揽,再好的产品也出不了工厂大门;业务人员
      
    的心中只有一句座右铭:成王败寇;业务员的人生是由他自己所定义的,
      
    要住什么样的房子、开什么样的车子、等等,自己可以掌握,连老板都无
      
    法为你定夺;业务员的养成不需要专门的科系来培训,但是的确需要一点
      
    天生的傻劲。
      
    我认为任何人都应该学习业务行销的技巧,因为你必须不断地推销你的理
      
    念让别人接受,哪怕你是文书工作人员、程序设计师、美工、总机小姐、
      
    乃至于董事长,我们每天都在推销我们的想法给别人,就像我老婆接受了
      
    我的求婚推销一样,其实一点都不难,也没什么了不起,我们每天都在作
      
    ,祇是没有察觉而已。
      
    所以说,千万不要再说不喜欢从事推销、我讨厌干业务,那是骗人的,事
      
    实上我们每天都在作,就像我现在打字的这一篇文章一样,我在将我的想
      
    法推销给你,你的反应只有四种:YesNoYes ButNo But,如此而已,
      
    不要太排斥,因为我从来都不认为全世界的人会百分之百相信我,连上帝
      
    都也有人反对,不是吗?
      
    一些社会应对进退技巧或人格特质的确是可以被后天塑造出来的,这一点
      
    我持肯定态度,因为我是一个极为渴望安静的人,我不喜欢一天到晚出门
      
    奔波,常常喜欢自己静静地窝在一个小天地里作我感兴趣的事情,但是我
      
    却被我以前的公司训练成超级业务高手,打破公司所有的历史纪录,这是
      
    如何做到的呢?说穿了不稀奇,已经有人说过了, 什么卡内基、火凤凰.
      
    ....等等的,它的确有效,至少在我以及我周遭的同事身上发挥了作
      
    用,而且屡试不爽,因为我也用在我的部属身上,真的蛮有效的。
      
    但是我还是不快乐,因为我已经失去了自我价值,而追寻自我价值这件事
      
    对于我而言又是一件很重要的人生大事,但是我还是去做了,原因很简单
      
    ,因为我娶妻生子,每个月付不完的帐单逼得我必须去做一大堆我不喜欢
      
    的事情,甚至连我老婆也是一样,没什么好抱怨的,因为这就是人生,一
      
    个非常真实在你我身边发生的事情,我在这个版面上看到好多人说如果景
      
    气好转的话,他就要跳槽到比较具规模的公司去上班,唉,我就来说明一
      
    下企业主的想法吧。
      
    现在的我早已是一位公司负责人,我经常要陪客户应酬,推销我的产品及
      
    服务,每个月要张罗员工薪资,遇到员工身体有病痛或是心情不佳,我还
      
    得小心伺候,免得他一时之间突然离职,日常作业会陷入停顿,这一阵子
      
    实在是很不景气,客户的预算大幅缩水不说,连决行的时程都一再往后延
      
    ,造成业务及生产单位极大的困扰。
      
    然后一下子是下大雨,一下子淹水,搞得我都不知道该怎么办,在我的立
      
    场来说(我要特别强调这是我作为老板的立场),每放一天假我就损失多
      
    少钱,每泡掉一台计算机我就损失多钱,钱、钱、钱、钱、钱、钱、钱,通
      
    通都要钱,我常在想说万一不幸有一天我垮台了,有多少员工会替这家公
      
    司或这个事业来着想?
      
    当景气还不错的时候,我得用很多花招来吸引这些所谓的人才,其中股票
      
    选择权是我最反感的一件事情,我常想为什么我用我多年来辛苦存下来的
      
    钱创办一个事业,而这些员工却要轻易跟我分享我辛苦的成果?
      
    当景气变差的时候,就像是现在,有多少员工会念在当初曾经一起奋斗的
      
    情谊呢?不会,因为我永远叫老板,你永远叫员工,这是千古以来无法保
      
    持和谐的关系。
      
    用比较感性的角度来看,与员工们朝夕相处共同奋斗,所以日久生情算大
      
    家一份股份,这倒也无可厚非,但是刚面试就急着问说这家公司福利政策
      
    如何?薪资待遇如何?的这些人,通常我都会请他们自己创业比较好,因
      
    为这些问题永远没有办法找到平衡点。
      
    如果用比较理性的角度来看,既然这个现实社会都是要用钱才能生存得下
      
    去,那么废话就不要说太多,直接了当说明工作内容为何,期限到了的时
      
    候该产出多少产品或是业绩,那这个样子的情况之下薪资及福利为何,我
      
    想如此还比较节省彼此双方的时间。情?那就别闹了!
      
    这些话听起来很刺耳,几乎所有的求职者听完一定会破口大骂,但是我只
      
    能说这个就是绝大多数企业主的想法,这些基本上都是根据一个简单不过
      
    的逻辑:「我一样每个月要花这么多钱来聘请员工作事情,我为什么没有
      
    权利去选择那些已经有技巧、有经验,甚至于是有客户在手上的新人呢?
      
    如果有一天这位员工表现突出,那么我就酌予提拔或奖励,再过一阵子,
      
    当这位员工表现大不如前,或是突然出现了薪资待遇更便宜的高手来加入
      
    公司,那我实在没有理由还要留着这位坐领高薪及福利的前朝重臣,却拒
      
    绝掉一位这么价廉物美的新人。这位前朝重臣的丰功伟业呢?别傻了,老
      
    板会回你一句话:我当初不是已经给了你相对的报酬吗?」
      
    最刚开始的时候,台商找去大陆上班的台籍干部差不多都有三倍于台湾行
      
    情的薪资,到了今天差不多已经掉到1.2倍而已了。台湾工厂的女工大
      
    约一个月可以领个1.5~2万元,大陆工厂相同的工作却只需要600
      
    ~1000元人民币,但是生产出来的产品品质却都差不多。请问如果你
      
    是老板,你会作何决定?当贸易商持续给你压力要求你降价,不然就要把
      
    订单转给你认识的同业时,你的心情会好才奇怪!
      
    各位可以不相信我所说的话,但是务必去查证一下我所讲的,如果没去过
      
    大陆,那么趁失业中的空档前进一下东莞或是广州(大约只要准备三万元
      
    就很够用了)。随便去一家工厂门口,从早上七点一直到下午六点,你会
      
    发现到门口都有人排队想争取应征的机会,甚至贿赂门口警卫,为的是希
      
    望获得一份300元起薪的现场操作员工作。
      
    300元人民币大约等于1300元台币,当我从香港搭机回台湾,在机
      
    场买了一瓶香水给我老婆,结帐时我才发现我花掉了两个大陆工厂新人的
      
    一个月薪资所得,结果害得我整个人在飞机上心情都好不起来。
      
    其实我蛮赞成神奇狮子文中的一些说法,在上海找一个什么工具软件都很
      
    厉害的美工,一个月最高也只要4000元人民币(这已经是很高很高了
      
    ),比照到台湾的行情,没有7~8万,你大概别想请得到人。
      
    前一阵子我有一些朋友应聘到大陆内地,而且是到大陆人开设的公司上班
      
    ,要我帮他恶补一下大陆文化,我才惊然发现我也快要被淘汰了,因为我
      
    根本无法跟计算机沟通:中文输入法的问题!
      
    先前我都没感觉到,那是因为我都是到台商公司去交货,碰到的计算机青一
      
    色都是繁体中文的操作系统,这难不倒我,而且大陆员工都已经学会了仓
      
    颉或是其它的输入法。但是大陆人开设的公司就只有简体中文的操作系统
      
    了,这个时候换做是你,怎么办?
      
    我要讲的意思是说接下来的二三十年,我们这一代或是下一代到底要跟谁
      
    竞争?跟多少人竞争?我已经很慎重地在思考这个问题,各位想过没有?
      
    我去了大陆这样子走马看花的逛了一下子,就觉得快活不下去了,各位的
      
    危机意识到底在哪里?
      
    大陆员工其实是相当糟糕的,几乎完全没有主动积极进取的精神,我看了
      
    这么多公司工厂,只让我看到一个人会自己动脑筋想解决方案,这个就是
      
    我们目前台湾员工的优势所在,但是能维持多久呢?
      
    侏罗纪公园中很清晰的一句话:生命自会寻找出路!只要我们脑袋里确实
      
    有料,其实企业老板是不太看学历的,有朝一日他必会回馈相当的报酬给
      
    你。但如果你让老板觉得不放心你的时候,就算是需要作出违法的行为,
      
    他还是会毅然下决心请你走路的。呆伯特这本书其实害了好多年轻人,这
      
    是我的真实感觉。
      
    最后谈到经验。经验是一种非常宝贵的人类资产,我绝对不会录用一个刚
      
    出校门的年轻人,因为我曾经吃足了苦头,大学或大专资管资工科班毕业
      
    ,竟然还要我花费十几万元送去接受半个月的专业讲习训练,结训回来后
      
    叫他们集思广益改写一个javascript,竟然在搞了一个星期之后跟我说这是
      
    不可能写得出来的东西,然后在二个月之后的发薪日,因为香港机场罢工
      
    我赶不回来(公司大小章刚好带在身上),以致晚了两天发薪水,这些新
      
    人竟然就联合起来指着我说这是一家骗人的公司,当时那种情况,你认为
      
    我的感觉会好吗?



       
    后来我请一位朋友的小孩,帮我看一下系统分析纪录, 不到三个小时程序
      
    就已经寄到我的电子邮件信箱了。这两者之间的差别在哪里 ?在经验!
      
    这位朋友的小孩平时就在帮人家写案子,收费非常便宜,因为他把这件事
      
    情当成是在作作业,练习练习,以便为将来出社会时找工作之用;而这些
      
    花了大把钞票的国立大学大专同学,心中老是以为自己是全世界的重心,
      
    一看到公司只有四十几坪,人没几个,听也没听说过,于是就....!
      
    所以我现在宁愿用极高的薪资,来聘请一位二专毕业,但是拥有相当丰富
      
    经验的人来帮我作事情,那些连接个电话留个信息在别人桌上的基本技巧
      
    都不懂的人,我是绝对敬而远之的。
      
    人类只是一种智商比较高级一点的动物,如果你常看Discovery或是国家地
      
    理频道的话,你就会发现老年的动物最可怜,因为又不能狩猎,又不能保
      
    卫家园,群体行动时还经常拖泥带水,影响整个行程进度,这是我们所谓
      
    的动物界。其实我们人类也好不到哪里去,顶多批着一张道德的皮在身上
      
    ,当我们走进浴室衣服一脱掉,哪有什么不一样,眼、耳、鼻、口、四肢
      
    、生殖器官...,差不多的啦!但是又为什么会出现圣人、先贤、总统
      
    呢?因为脑袋里的东西不一样。
      
    我们一辈子活在世上,无非就是要想尽办法来创造出被人家利用的价值。
      
    如果我每天只被老板利用一个小时,但是老板没有我这一个小时的帮忙,
      
    他就会赚不到钱,而且又找不到什么替代方案的话,那么我这一个小时就
      
    会相当值钱,比如说我担任这家公司的技术总顾问。
      
    反之如果我的被利用价值相当低,随便一个人或一套硬设备就可以取代
      
    掉我,那么就算是我花了十几个小时,累得跟狗一样,老板还是会随时请
      
    我走路,因为我没有被利用的价值,比如说我客户的一些总机小姐。
      
    常常有很久没联络的朋友或客户突然打电话给我,霹雳啪啦的问了一大堆
      
    问题,我也几哩呱啦地回答他们,生意就上门了,因为我有一些特定的印
      
    象停留在他们的脑海中,凡是他们遇到这一方面的问题时,通常都会先来
      
    问我,他们知道像这种事情找我准没错,这就是我个人独具的被利用价值
      
       你的被利用价值在哪里?有多少?能持续产生新的价值吗?跟得上时代脉
      
    动吗?
      
    我想这才是老板最想了解的,其它的,我认为都不是重点。
      
    愿共勉之!祝大家都能找到理想的工作! 主管欣賞的人 在職場上,苦勞不會成功,其實企業最欣賞的人才,是具有高度common sense的人,換句話說,就是要work hardwork smartwork happy,特質的A級人才。 努力工作績效  是不是最努力工作的人就一定受到主管賞識呢?
    有三個檢視標準或許可以提供 大家做為一個參考:
    Work Hard, Work Smart, Work Happy
    你是不是很努力工作,但不快樂呢?這時或許可以檢核自己一下,工作的方式是不是夠smart
    在這裡跟大家分享一個故事,或許可以引發大家一些思考與想法。
    小芬與小美畢業於某國立大學企管系,同時進入一家中型企業,擔任企劃專員的工作。小芬做事努力認真、守分務實,常常自動留下來為公司加班,工作到很晚才下班。
    小美呢?只見她每天嘻嘻哈哈,工作輕鬆又愉快,每天都會主動去找主管聊天,給人一種跟主管感情很好的印象。
    1
    年後,小美獲得主管升遷,委以重任,小芬則只獲得象徵性的加薪鼓勵。這讓小芬非常不平,認為小美工作又沒自己認真,只會逢迎拍主管馬屁,憑什麼考績反而比她好?而且還受到公司的重用。自己為公司付出許多,夙夜匪懈地工作,
    反而落得一場空,於是遞了辭呈。
    少了一根筋 
    就在小芬工作的最後一天,總經理找小芬晤談。剛好中秋節快到了,公司正在考慮該買什麼中秋禮送給客戶。總經理說,「小芬,可不可以請妳到南門巿場跑一趟,看看有沒有賣大閘蟹?」
    小芬心裡很疑惑,不知道主管為什麼要她跑這一趟,因為這並不是她負責的工作啊!但她還是乖乖地依照主管的要求,搭計程車到南門巿場。過了20分鐘,小芬回到辦公室,向總經理報告,「南門巿場有賣大閘蟹。」
    總經理接著問她,「南門巿場的大閘蟹怎麼賣?算斤?還是算隻?」小芬一臉茫然,無法回答。於是又跑了一趟南門巿場,30分鐘後又回來報告,「南門巿場大閘蟹算隻賣,每隻350元。」 
    總經理聽了之後,當著小芬的面,把小美找了進來,並吩咐小美,「麻煩妳到南門巿場去一趟,看看有沒有賣大閘蟹?」
    小美馬上問總經理,「請問大閘蟹是有什麼用途嗎?」
    總經理回答她,「中秋節快到了,打算送客戶大閘蟹做為中秋賀禮。」
    小美立即出門。過了1個多小時,小美回來了。
    一進門,就見她眉飛色舞地拎著兩隻大閘蟹。向總經理報告,「南門巿場有兩家攤位賣大閘蟹。第一家的大閘蟹,每隻平均4兩重,每隻賣350元。第二家的大閘蟹,每隻平均6兩重,一隻550元。我建議,如果總經理自家食用可以買4兩重的,肚白、背綠、金毛,看起來很新鮮。如果總經理要送人,我建議買6兩重的,看起來比較有份量。我各買了一隻帶回來給總經理參考。」
    做事Smart有方法 
    聽完小美的報告之後,總經理轉頭問小芬,「妳看出妳們之間有什麼不同了嗎?」小芬一副恍然大悟的神情,趕忙點頭表示她明白了!
    總經理向小芬進一步說明,「一樣是去南門巿場看看有沒有賣大閘蟹,妳們蒐集回來的巿場情報與態度截然不同。小芬,妳很認真沒有錯,但是妳並沒有思考這項任務的需求是什麼?只是一個口令一個動作,得來來回回好幾趟才能把一件事情做好。而小美呢?不用我多交待,一次就把事情搞定,她不僅蒐集了完整的巿場情報,甚至也提出建議與分析,協助我做為判斷的參考。」
    苦勞不會成功 
    小芬聽了不禁自慚形穢,她最感慚愧的是,為何她與小美是最好的同學,居然沒有學習小美的做事優點,暗地嫉妒她。同時她也很謝謝總經理為她上了一堂寶貴的一課,點醒她的負面思維。
    在職場上,苦勞不會成功,其實企業最欣賞的人才,是具有高度common sense的人,換句話說,就是要有work hard, work smart, work happy特質的A級人才。這樣的人才能快速掌握主管的需求與期待,為公司開創更大的格局。
    The race is not to the swift or the battle to the strong, nor does food come to wise or wealth to the brilliant or favor to the learned: but time and chance happen to them all. 
    快跑的未必能贏,力戰的未必得勝;
    智慧的未必得糧食,明哲的未必得資財,靈巧的未必得喜悅;
    所臨到眾人的,是因為「時間」與「機會」。 
    親愛的好友們!你們學到了嗎?
    你我是不是只懂得做個『努力工作、認真、守分務實』的人呢?

    posted @ 2014-02-22 14:46 奋斗成就男人 阅读(222) | 评论 (0)编辑 收藏

    图解SQL的inner join、left join、right join、full outer join、union、union all的区别

    对于SQL的Join,在学习起来可能是比较乱的。我们知道,SQL的Join语法有很多inner的,有outer的,有left的,有时候,对于Select出来的结果集是什么样子有点不是很清楚。Coding Horror上有一篇文章,通过文氏图 Venn diagrams 解释了SQL的Join。我觉得清楚易懂,转过来。

    假设我们有两张表。Table A 是左边的表。Table B 是右边的表。其各有四条记录,其中有两条记录name是相同的,如下所示:让我们看看不同JOIN的不同

    A表
    id name
    1 Pirate
    2 Monkey
    3 Ninja
    4 Spaghetti
    B表
    id name
    1 Rutabaga
    2 Pirate
    3 Darth Vade
    4 Ninja

    1.INNER JOIN

    SELECT * FROM TableA INNER JOIN TableB ON TableA.name = TableB.name

    结果集
    (TableA.) (TableB.)
    id name id name
    1 Pirate 2 Pirate
    3 Ninja 4 Ninja

    Inner join 产生的结果集中,是A和B的交集。

    2.FULL [OUTER] JOIN 
    (1)
    SELECT * FROM TableA FULL OUTER JOIN TableB ON TableA.name = TableB.name 
    结果集
    (TableA.) (TableB.)
    id name id name
    1 Pirate 2 Pirate
    2 Monkey null null
    3 Ninja 4 Ninja
    4 Spaghetti null null
    null null 1 Rutabaga
    null null 3 Darth Vade
    Full outer join 产生A和B的并集。但是需要注意的是,对于没有匹配的记录,则会以null做为值。
    可以使用IFNULL判断。
    (2)
    SELECT * FROM TableA FULL OUTER JOIN TableB ON TableA.name = TableB.name
    WHERE TableA.id IS null OR TableB.id IS null
    结果集
    (TableA.) (TableB.)
    id name id name
    2 Monkey null null
    4 Spaghetti null null
    null null 1 Rutabaga
    null null 3 Darth Vade
     产生A表和B表没有交集的数据集。
     
    3.LEFT [OUTER] JOIN
    (1)
    SELECT * FROM TableA LEFT OUTER JOIN TableB ON TableA.name = TableB.name
    结果集
    (TableA.) (TableB.)
    id name id name
    1 Pirate 2 Pirate
    2 Monkey null null
    3 Ninja 4 Ninja
    4 Spaghetti null null
    Left outer join 产生表A的完全集,而B表中匹配的则有值,没有匹配的则以null值取代。
    (2)
    SELECT * FROM TableA LEFT OUTER JOIN TableB ON TableA.name = TableB.nameWHERE TableB.id IS null
    结果集
    (TableA.) (TableB.)
    id name id name
    2 Monkey null null
    4 Spaghetti null null

    产生在A表中有而在B表中没有的集合。

    4.RIGHT [OUTER] JOIN
    RIGHT OUTER JOIN 是后面的表为基础,与LEFT OUTER JOIN用法类似。这里不介绍了。
    5.UNION UNION ALL
    UNION 操作符用于合并两个或多个 SELECT 语句的结果集。
    请注意,UNION 内部的 SELECT 语句必须拥有相同数量的列。列也必须拥有相似的数据类型。同时,每条 SELECT 语句中的列的顺序必须相同。UNION 只选取记录,而UNION ALL会列出所有记录。
    (1)SELECT name FROM TableA UNION SELECT name FROM TableB
    新结果集
    name
    Pirate
    Monkey
    Ninja
    Spaghetti
    Rutabaga
    Darth Vade
    选取不同值
    (2)SELECT name FROM TableA UNION ALL SELECT name FROM TableB
    新结果集
    name
    Pirate
    Monkey
    Ninja
    Spaghetti
    Rutabaga
    Pirate
    Darth Vade
    Ninja

    全部列出来

    (3)注意:

    SELECT * FROM TableA UNION SELECT * FROM TableB
    新结果集
    id name
    1 Pirate
    2 Monkey
    3 Ninja
    4 Spaghetti
    1 Rutabaga
    2 Pirate
    3 Darth Vade
    4 Ninja
    由于 id 1 Pirate   与 id 2 Pirate 并不相同,不合并
     
    还需要注册的是我们还有一个是“交差集” cross join, 这种Join没有办法用文式图表示,因为其就是把表A和表B的数据进行一个N*M的组合,即笛卡尔积。表达式如下:SELECT * FROM TableA CROSS JOIN TableB
    这个笛卡尔乘积会产生 4 x 4 = 16 条记录,一般来说,我们很少用到这个语法。但是我们得小心,如果不是使用嵌套的select语句,一般系统都会产生笛卡尔乘积然再做过滤。这是对于性能来说是非常危险的,尤其是表很大的时候。

    posted @ 2014-02-15 08:46 奋斗成就男人 阅读(278) | 评论 (0)编辑 收藏

    Java中判断Object对象类型

    Object param = params.get(i);
       if (param instanceof Integer) {
        int value = ((Integer) param).intValue();
        prepStatement.setInt(i + 1, value);
       } else if (param instanceof String) {
        String s = (String) param;
        prepStatement.setString(i + 1, s);
       } else if (param instanceof Double) {
        double d = ((Double) param).doubleValue();
        prepStatement.setDouble(i + 1, d);
       } else if (param instanceof Float) {
        float f = ((Float) param).floatValue();
        prepStatement.setFloat(i + 1, f);
       } else if (param instanceof Long) {
        long l = ((Long) param).longValue();
        prepStatement.setLong(i + 1, l);
       } else if (param instanceof Boolean) {
        boolean b = ((Boolean) param).booleanValue();
        prepStatement.setBoolean(i + 1, b);
       } else if (param instanceof Date) {
        Date d = (Date) param;
        prepStatement.setDate(i + 1, (Date) param);
       }  

    posted @ 2014-02-12 13:18 奋斗成就男人 阅读(774) | 评论 (0)编辑 收藏

    oracle,字母大小写转换

    函数:upper()
    功能:将字符串中的小写字母转换为大写字母。
    语法:Upper( string )
    参数string:要将其中的小写字母转换为大写字母的字符串返回值String。函数执行成功时返回将小写字母转换为大写字母后的字符串,发生错误时返回空字符串("")。如果string参数的值为NULL,Upper()函数返回NULL。


    更新table表的name列为大写:
    UPDATE table SET name = upper(name);

    在程序中实现大写查询:
    select * from table where name=upper('admin');

    在程序中实现大小写忽略查训:
    select * from table where upper(name)=upper('admin'); 

    posted @ 2014-02-07 14:15 奋斗成就男人 阅读(1066) | 评论 (0)编辑 收藏

    JavaScript函数及其参数

    1.Js函数可以传入不同的参数,如

    function writeNString(strMsg){

    document.write(strMsg + "<br>");

    }

    2.Js函数返回值,js函数可以将运行的结果返回,函数可以视为一个黑盒子,使用参数输入数据后产生所需的运行结果,如

    function one2N(intnumber){

    var intTotal = 0;

    for(var i=0;i<=intnumber;i++){

        intTotal +=i;}

    return intTotal;

    }

    3.Js函数的传值和传址参数

    传值:只是将变量的值传入函数,函数会另外配置内存保存参数值,所以并不会改变原变量的值。

    传址:将变量实际保存的内存位置传入函数,所以如果在函数中变更参数的值,也会同时变动原参数的值。

    数字、字符串和布尔----传值

    对象、数组和函数----传址

    字符串对象-------传址

    4.Js函数的参数数组

    Js的函数都拥有一个参数数组(Arguments Array)对象,叫做arguments对象。当调用函数传入参数时,函数即使没有指明参数名称,也一样可以使用参数数组的对象获取参数的个数和个别的参数值。

    function sumInteger(){

       var total = 0;

      for(var i=0; i<sumInteger.arguments.length;i++){

           total += sumInteger.arguments[i];

            }

         return total;

    }

    //调用函数

    inntotal = sumInteger(100,45,567,234);

    document.write("函数sumInteger(100,45,567,234):"+inttotal+"<br>");

    5.JS函数的变量范围

    JS函数有两种变量:

    局部变量(local Variables)在函数内声明的变量,变量只能在函数内的程序行内使用,函数外的程序代码并无法访问此变量。

    全局变量(Global Variables)在函数外声明的变量,整个JS程序的函数和程序代码都能访问此变量。

    posted @ 2014-01-23 09:17 奋斗成就男人 阅读(201) | 评论 (0)编辑 收藏

    jstl标签调用java类的方法

    1. 实现函数类

    JSTL对函数类没有任何要求,只要求方法类是公开的,方法必须是静态的、公用的方法。下面是这个函数实现的代码,把它编译后放到 WEB-INF\classes\demo 目录下。

    package demo;

    /**
    * 用于JSTL的函数类
    * @author Winter Lau
    */
    public class EmailFunction {

    /**
    * 转换EMAIL地址为链接的形式
    * @param email
    * @return
    */
    public static String emailLink(String email){
    StringBuffer sb = new StringBuffer();
    sb.append("<a href=\"mailto:");
    sb.append(email);
    sb.append("\">");
    sb.append(email);
    sb.append("</a>");
    return sb.toString();
    }

    }

    2. 描述文件

    接下来我们必须通知JSTL怎么来使用这个函数,跟标签库一样,我们必须编写一个tld文件,姑且把文件名叫做email.tld,该文件存放在{webapp}/WEB-INF目录下,该文件中包含对该函数的说明,文件如下:

    <?xml version="1.0" encoding="GB2312" ?>

    <taglib xmlns=" http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi=" http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation=" http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
    version="2.0">

    <description>Demo</description>
    <display-name>Email functions</display-name>
    <tlib-version>1.1</tlib-version>
    <short-name>mail</short-name>
    <uri> http://www.javayou.com/dev/jsp/jstl/mail

    <function>
    <description>
    用于将电子邮件转成链接形式
    </description>
    <name>emailLink</name>
    <function-class>demo.EmailFunction</function-class>
    <function-signature>java.lang.String emailLink(java.lang.String)</function-signature>
    <example>
    ${mail:emailLink("javayou@gmail.com")}
    </example>
    </function>

    </taglib>

    3. 测试页面

    万事俱备,接下来就是这个测试页面了,页面的代码如下

    <%@ page language="java" contentType="text/html; charset=UTF-8" %>
    <%@ taglib prefix="em" uri=" http://www.javayou.com/dev/jsp/jstl/mail" %>

    Click ${em:emailLink("javayou@gmail.com")} to feedback.

    打开浏览器运行该页面,显示的结果如下:

    Click javayou@gmail.com to feedback.



     

    posted @ 2014-01-15 01:09 奋斗成就男人 阅读(2881) | 评论 (0)编辑 收藏

    Eclipse程序员要掌握的常用快捷键

    判断一个人的编程水平,就看他用键盘多,还是鼠标多。用键盘一是为了输入代码(当然了,也包括注释),再有就是熟练使用快捷键。
     
    所以在网上找了一下,自己也总结了些用得比较多的,和大家一起分享一下。
     
    Ctrl+K 光标放在一个变量上(注意,是变量,如果你的光标放在了字符串上,如http://keleyi.com则没有任何作用的),按下Ctrl+K光标会定位到下一个相同的变量 
    Shift+Ctrl+K 跟Ctrl+K功能一样,方向相反
    Ctrl+O 打开类似大纲视图的小窗口
    Alt+ 左右方向键,跳到前一次/后一次的编辑位置 (经常会用到)
    双击左括号(小括号,中括号,大括号),将选择括号内的所有内容
    F3打开声明该引用的文件
    F4打开类型层次结构
    Ctrl+H打开搜索窗口
    Shift+Ctrl+S保存全部
    Shift+Ctrl+R打开资源
    Ctrl+Q回到最后一次编辑的地方
    Ctrl+Shift+G在workspace中搜索引用
    Alt+上、下方向键,将选中的行向上或向下移动
     
    Shift+Enter在当前行的下面添加一个空行,光标可以当前行的任意位置
    Ctrl+L跳转到某行
    Ctrl+M最大化当前的Edit或View,再按则反之
    Ctrl+/注释当前行,再按则反之
    Ctrl+T显示当前类的继承情况(可以查看类的目录树)
     
    Ctrl+E显示当前Edit的下拉列表
    Ctrl+/(小键盘) 折叠当前类中的所有代码
    Ctrl+*(小键盘) 展开当前类中的所有代码
     
    Alt+/代码助手,提示代码
    Ctrl+J正向增量查找
    Ctrl+Shift+J反向增量查找
     
    Ctrl+Shift+F4关闭所有打开的edit
    Ctrl+Shift+R查找文件
    Ctrl+Shift+T查找类
     
    Alt+Shift+R重名命
    Alt+Shift+M抽取方法
    Alt+Shift+Z取消重构
     
    磨刀不误砍柴工啊,一定要用熟来。。。。

    posted @ 2014-01-15 01:02 奋斗成就男人 阅读(186) | 评论 (0)编辑 收藏

    JSTL 标签库 下载及配置

    下载地址:http://archive.apache.org/dist/jakarta/taglibs/standard/binaries/

    JSTL 标签库的配置:

    按照上面的地址下载 jar 包。然后按照下面的步骤在 tomcat 服务器上进行配置。

    首先,在 Tomcat 的工作目录,也就是安装目录下的 webapps/Root 目录下,新建一个 WEB-INF 文件夹,并在 WEB-INF 文件夹下新建一个 lib 文件夹,然后把下载下来的压缩包中 lib 文件夹中的 standard.jar 和 jstl.jar 复制到该 lib 文件夹中,接下来把压缩包中整个 tld 文件夹复制到 WEB-INF 文件夹下。在 WEB-INF 文件夹中的 web.xml 中修改(如果没有,新建一个):

    <?xml version="1.0" encoding="utf-8"?>

    <web-app xmlns="http://java.sun.com/xml/ns/javaee"
       xmlns:xsi
    ="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation
    ="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
       version
    ="2.5">

      
    <display-name>Welcome to Tomcat</display-name>
      
    <description>
         Welcome to Tomcat
      
    </description>
      
      
    <taglib>
            
    <taglib-uri>http://java.sun.com/jstl/fmt</taglib-uri>
            <taglib-location>/WEB-INF/tld/fmt.tld</taglib-location>
        
    </taglib>
        
    <taglib>
            
    <taglib-uri>http://java.sun.com/jstl/core</taglib-uri>
            <taglib-location>/WEB-INF/tld/c.tld</taglib-location>
        
    </taglib>
        
    <taglib>
            
    <taglib-uri>http://java.sun.com/jstl/sql</taglib-uri>
            <taglib-location>/WEB-INF/tld/sql.tld</taglib-location>
        
    </taglib>
        
    <taglib>
            
    <taglib-uri>http://java.sun.com/jstl/x</taglib-uri>
            <taglib-location>/WEB-INF/tld/x.tld</taglib-location>
        
    </taglib>

    </web-app>

    posted @ 2014-01-15 00:57 奋斗成就男人 阅读(249) | 评论 (0)编辑 收藏

    JSTL标签 参考手册

         摘要: 前言=========================================================================JSTL标签库,是日常开发经常使用的,也是众多标签中性能最好的。把常用的内容,放在这里备份一份,随用随查。尽量做到不用查,就可以随手就可以写出来。这算是Java程序员的基本功吧,一定要扎实。 JSTL全名为JavaServer Pages ...  阅读全文

    posted @ 2014-01-15 00:51 奋斗成就男人 阅读(268) | 评论 (0)编辑 收藏

    JSTL(c标签)与Struts2(s标签)标签的常用功能对比

         摘要: 1. 条件标签 JSTL<c:if test="${user.password == 'hello'}">     <c:choose>         <c:when test="${user.age <...  阅读全文

    posted @ 2014-01-15 00:38 奋斗成就男人 阅读(400) | 评论 (0)编辑 收藏

    struts2&jstl标签总结

    struts2&jstl标签总结

    引入STRUTS2标签库和JSTL标签库 
    Java代码  
    <%@ taglib prefix="s" uri="/struts-tags"%>  
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>  

    1、if 标签 
    Java代码  
    <s:if test="#parameters['siteId']!=null">  
    </s:if>  

    因为JSTL没有else标签 所以比较好的方法是 
    Java代码  
    <c:if var="current" test="${page.pageNo == i}">  
    ${i}  
    </c:if>  
    <c:if test="${not current}">  
    </c:if>  

    action里有boolean属性 
    Java代码  
    <s:if test="!emptySite"></s:if>  

    Java代码  
    <c:if test="${emptySite}"></c:if>  


    2、select 标签 
    Java代码  
    <s:select list="pageList" listKey="key" id="swpTplCata" listValue="value" name="pageId" />  

    pageList 对应action里的pageList属性 arrayList 
    listKey="key" listValue="value" 为固定写法 
    name="pageId" 为下拉框的默认值 pageId也是action里的属性 要提供get方法 

    3、radio 标签 
    Java代码  
    <s:if test="checkedRoleIds.size() == 0">  
    <s:radio name="checkedRoleIds" list="allRoleList" listKey="id" listValue="desc" />  
    </s:if>  
    <s:else>  
    <s:radio name="checkedRoleIds" list="allRoleList" listKey="id" listValue="desc" value="checkedRoleIds[0]" />  
    </s:else>  

    value="checkedRoleIds[0]" 默认选中的值 
    Java代码  
    private List<Long> checkedRoleIds; //用户角色  
      
        public List<Long> getCheckedRoleIds() {  
            return checkedRoleIds;  
        }  
        public void setCheckedRoleIds(List<Long> checkedRoleIds) {  
            this.checkedRoleIds = checkedRoleIds;  
        }  


    4、form 标签 
    Java代码  
    <s:form method="post" action="%{#request.contextPath}/account/user!save"  
        theme="simple" enctype="multipart/form-data" id="register_form"  
        name="form">  


    5、iterator 标签 
    Java代码  
    <s:iterator value="page.result">  
    </s:iterator>  


    6、jstl循环 
    Java代码  
    <c:forEach var="i" begin="1" end="${page.totalPages}" step="1">  
    ${i}  
    </c:forEach>  


    7、jstl循环map 
    Java代码  
    <c:forEach items="${model}" var="model">  
        ${model.key}  
        ${model.value}  
        <br />  
    </c:forEach>  

    自定义标签 
    http://dingbuoyi.iteye.com/admin/blogs/818950


    struts2标签与jstl标签的混合使用
     
    1.在jstl中使用struts2
    <c:forEach var="ee" items="${requestScope.serviceList}" >
            jstl:<c:out value="${ee.id}"></c:out>
            el:${ee.id}
            struts2: <s:property value="Ettr.ee.id"/>
    </c:forEach>
     通过struts2标签取jstl标签的变量时,如果有设置scope,可以从scope中取值如果没有就需要用Ettr来取值

    2.从jstl标签中获取值
    <c:set var="ctime" value="${el.createtime}" scope="request"/>
    <c:set var="ctime2" value="${el.createtime}" />
    <s:property value="#request.ctime"/>
    <s:property value="Ettr.ctime2"/>

     3.在struts2标签中使用jstl
    <s:iterator value="#request.serviceList" id="bs">
          struts2:<s:property value="#bs.keyid"/>
          el:${bs.keyid}
          jstl:<c:out value="${bs.keyid}"></c:out>
    </s:iterator>
     
    4.从struts2标签中取值
    <!-- 数字类型-->
    <s:set name="pp" value="11"></s:set> 
    struts2:<s:property value="#pp"/>
    el:${pp}
    jstl:<c:out value="${pp}"></c:out>      

    <!-- 字符串类型-->
    <s:set name="pp2" value="'abc'" scope="request"></s:set>
    struts2:<s:property value="#request.pp2"/>
    el:${pp2}
    jstl:<c:out value="${pp2}"></c:out> 

    --选择和循环

    <c:choose>
        <c:when test="${empty sessionScope.indexList}">
                没有你搜索的歌曲..<br />
        </c:when>
        <c:otherwise>
            <c:forEachitems="${sessionScope.indexList}" var="list"
                varStatus="vs">
                <a href="#"> ${list.tone_name}</a> -- ${list.singer}
                 <br />
            </c:forEach>
        </c:otherwise>
    </c:choose>


    <s:if test="#session.indexList==null">
         没有你搜索的歌曲..<br />
    </s:if>
    <s:else>
     <s:iterator value="#session.indexList" var="list">
        <a href="#"><s:property value="#list.tone_name" /></a>--
             <s:property value="#list.singer" />
             <br/>
     </s:iterator>
    </s:else>
    </div> 

    posted @ 2014-01-15 00:35 奋斗成就男人 阅读(643) | 评论 (0)编辑 收藏

    Struts2常用标签总结

    Struts2常用标签总结
    一 介绍
    1.Struts2的作用
    Struts2标签库提供了主题、模板支持,极大地简化了视图页面的编写,而且,struts2的主题、模板都提供了很好的扩展性。实现了更好的代码复用。Struts2允许在页面中使用自定义组件,这完全能满足项目中页面显示复杂,多变的需求。
    Struts2的标签库有一个巨大的改进之处,struts2标签库的标签不依赖于任何表现层技术,也就是说strtus2提供了大部分标签,可以在各种表现技术中使用。包括最常用的jsp页面,也可以说Velocity和FreeMarker等模板技术中的使用
    2.Struts2分类
    (1)UI标签:(User  Interface, 用户界面)标签,主要用于生成HTML元素标签,UI标签又可分为表单标签非表单标签
    (2)非UI标签,主要用于数据访问,逻辑控制等的标签。非UI标签可分为流程控制标签(包括用于实现分支、循环等流程控制的标签)和数据访问标签(主要包括用户输出ValueStack中的值,完成国际化等功能的)
    (3)ajax标签
    3.Struts2标签使用前的准备:
    (1)在要使用标签的jsp页面引入标签库:
    <%@ taglib uri="/struts-tags" prefix="s"%>
    (2)在web.xml中声明要使用的标签 这样是struts2 2.3.1.2版本的引入方式
    <filter>
    <filter-name>struts2</filter-name>
    <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
    </filter>
    4.标签的使用
    (1)property标签
    用于输出指定的值:
    <s:property value="%{@cn.csdn.hr.domain.User@Name}"/><br/>
        <s:property value="@cn.csdn.hr.domain.User@Name"/><Br/><!-- 以上两种方法都可以 -->
        <s:property value="%{@cn.csdn.hr.domain.User@study()}"/>
    以上可以访问某一个包的类的属性的集中方式,study()是访问方法的方法,并输出。
    以下用java代码代替的,访问某一个范围内的属性
    <%
    //采用pageContext对象往page范围内存入值来 验证#attr搜索顺序是从page开始的 ,搜索的顺序为:page,reques,session,application。
    set存值的时候存到的是request中,在jsp页面中访问的时候不用加任何的标识符,即可直接访问,如果不同的作用域不一样了,
    pageContext.setAttribute("name", "laoowang", PageContext.PAGE_SCOPE);
    %>
    <s:property value="#attr.name" /> 
    假设在action中设置了不同作用域的类
    不同的作用域的标签的访问:
     
      <h3>获取的是requet中的对象值</h3>
      第一种方式:<s:property value="#request.user1.realName"/>
      <br/>
      第二种方式:<s:property value="#request.user1['realName']"/>
       <br/>
      第三种方式:<s:property value="#user1.realName"/>
       <br/>
        第四种方式:<s:property value="#user1['realName']"/>
          <br/>
           第五种方式:${requestScope.user1.realName }  || ${requestScope.user1['realName'] }
           
       第六种:<s:property value="#attr.user1.realName"/>
      attr对象按page==>  request sessionapplictio找的
      
      
      <h3>获取session中的值</h3>
        第一种方式:<s:property value="#session.user1.realName"/>
      <br/>
      第二种方式:<s:property value="#session.user1['realName']"/>
      
      
        第五种方式:${sessionScope.user1.realName }  || ${sessionScope.user1['realName'] }
      
      <h3>获取application中的对象的值</h3>
        第一种方式:<s:property value="#application.user1.realName"/>
      <br/>
      第二种方式:<s:property value="#application.user1['realName']"/>
      
      
        第五种方式:${applicationScope.user1.realName }  || ${applicationScope.user1['realName'] }
    (2)iterator标签的使用
    第一种:list集合
    <!-- 设置set集合  value-->
    <!-- status 可选属性,该属性指定迭代时的IteratorStatus实例 -->
    <!-- value="#attr.list"   list存放到了request中  可以value="#request.list"
    statu.odd返回当前被迭代元素的索引是否是奇数
    -->
    <s:set name="list" value="{'a','b','c','d'}"></s:set>
    <s:iterator var="ent" value="#request.list" status="statu">
    <s:if test="%{#statu.odd}">
    <font color="red"><s:property value="#ent" />
    </font>
    </s:if>
    <s:else>
    <s:property value="#ent" />
    </s:else>
    </s:iterator>
    第二种:map集合中的使用
    <h3>Map集合</h3>
    <!-- map集合的特点: 
     语法格式:# {key:value,key1:value1,key2:value2,.....}   
     以上的语法中就直接生成了一个Map类型的集合,该Map对象中的每个key-value对象之间用英文的冒号隔开   
       ,多个元素之间用逗号分隔。   
    -->
    </div>
    <s:set var="map" value="#{'1':'laowang','2':'老王','3':'猩猩'}"></s:set>
    遍历Map:
    <br />
    <s:iterator value="#map">
    <s:property value="key" />:::<s:property value="value" />
    <Br />
    </s:iterator>\
    第三种:集合的变量
    <h3>遍历集合:::</h3>
    <div>
    <!-- 遍历出价格大于3000的 -->
    <s:iterator var="user" value="#session['users']">
    <s:if test="%{#user['price']>3000}">
    <s:property value="#user['price']"/>
    </s:if>
    </s:iterator>
    <hr color="blue"/><!-- $是取出价格 大于3000的最后一个值 -->
    <s:iterator var="u" value="#session.users.{$(#this['price']>3000)}">
    <s:property value="price"/>
    </s:iterator>
    </div>
    注:users是User的对象,price是User中的一个属性
    简述一下iterator的介绍:
    iterator标签用于对集合进行迭代,这里的集合包含List、Set和数组。
    <s:set name="list" value="{'zhangming','xiaoi','liming'}" />
    <s:iterator value="#list" status="st">
    <font color=<s:if test="#st.odd">red</s:if><s:else>blue</s:else>>
    <s:property /></font><br>
    </s:iterator> 
    value:可选属性,指定被迭代的集合,如果没有设置该属性,则使用ValueStack栈顶的集合。
    id:可选属性,指定集合里元素的id。
    status:可选属性,该属性指定迭代时的IteratorStatus实例。该实例包含如下几个方法:
    int getCount(),返回当前迭代了几个元素。
    int getIndex(),返回当前迭代元素的索引。
    boolean isEven(),返回当前被迭代元素的索引是否是偶数
    boolean isOdd(),返回当前被迭代元素的索引是否是奇数
    boolean isFirst(),返回当前被迭代元素是否是第一个元素。
    boolean isLast(),返回当前被迭代元素是否是最后一个元素。
    (3)if else语句的使用
    <s:set name="age" value="21" />
    <s:if test="#age==23">
    23
    </s:if>
    <s:elseif test="#age==21">
    21
    </s:elseif>
    <s:else>
    都不等
    </s:else> 
    (4)URL标签
    <!-- 声明一个URL地址 -->
        <s:url action="test" namespace="/tag" var="add">
        <s:param name="username">laowangang</s:param>
        <s:param name="id">12</s:param>
        </s:url>
        <s:a href="%{add}">测试URL</s:a>
        <s:a action="test" namespace="/tag"></s:a>
    以上的两个<s:a>标签的作用是一样的。
    (5)data标签
    <%
        pageContext.setAttribute("birth",new Date(200,03,10),PageContext.REQUEST_SCOPE);
        %>
        <s:date name="#request.birth" format="yyyy年MM月dd日"/>
        <s:date name="#request.birth" nice="true"/>
    这个标签是按照format的格式去输出的。
    (6)表单
       
        <h1>from表单</h1>
        <s:form action="test" namespace="/tag">
        <s:textfield label="用户名" name="uname" tooltip="你的名字" javascriptTooltip="false"></s:textfield>
        <s:textarea  name="rmake" cols="40" rows="20" tooltipDelay="300" tooltip="hi" label="备注" javascriptTooltip="true"></s:textarea>
        <s:password label="密码" name="upass"></s:password>
        <s:file name="file" label="上传文件"></s:file>
        <s:hidden name="id" value="1"></s:hidden>
       
        <!-- 
        <select name="edu">
        <option value="listKey">listValue</option>
        -->
        <s:select list="#{'1':'博士','2':'硕士'}" name="edu" label="学历" listKey="key" listValue="value"></s:select>
       
        <s:select list="{'java','.net'}" value="java"></s:select><!-- value是选中的 -->
       
        <!-- 必须有name -->
        <s:checkbox label="爱好 " fieldValue="true" name="checkboxFiled1"></s:checkbox>
       
        <!-- 多个checkbox -->
    <s:checkboxlist list="{'java','css','html','struts2'}" label="喜欢的编程语言" name="box" value="{'css','struts2'}"></s:checkboxlist>
    <!-- map集合前要加# -->
    <s:checkboxlist list="#{1:'java',2:'css',3:'html',4:'struts2',5:'spring'}" label="喜欢的编程语言" name="boxs" value="{1,2}"></s:checkboxlist>
    <!-- listKey 
    listValue
    <input type="text" name="boxs" value="listKey">显示值listValue
    -->
       
    <!-- radio -->
    <%
    //从服务器传过来值 
    pageContext.setAttribute("sex","男",PageContext.REQUEST_SCOPE);
    pageContext.setAttribute("sex1","男",PageContext.REQUEST_SCOPE);
    %>
    <s:radio list="{'男','女'}" name="sex" value="#request.sex"></s:radio>
    <s:radio list="#{1:'男',2:'女'}" name="sex1" listKey="key" listValue="value" value="#request.sex1"></s:radio>    
    <!-- 防止表单提交的方式 -->
    <s:token></s:token>
       
        <s:submit value="提交"></s:submit>
        </s:form>

    posted @ 2014-01-15 00:18 奋斗成就男人 阅读(177) | 评论 (0)编辑 收藏

    JAVA正则表达式语法大全

    [正则表达式]文本框输入内容控制
    整数或者小数:^[0-9]+\.{0,1}[0-9]{0,2}$
    只能输入数字:"^[0-9]*$"。
    只能输入n位的数字:"^\d{n}$"。
    只能输入至少n位的数字:"^\d{n,}$"。
    只能输入m~n位的数字:。"^\d{m,n}$"
    只能输入零和非零开头的数字:"^(0|[1-9][0-9]*)$"。
    只能输入有两位小数的正实数:"^[0-9]+(.[0-9]{2})?$"。
    只能输入有1~3位小数的正实数:"^[0-9]+(.[0-9]{1,3})?$"。
    只能输入非零的正整数:"^\+?[1-9][0-9]*$"。
    只能输入非零的负整数:"^\-[1-9][]0-9"*$。
    只能输入长度为3的字符:"^.{3}$"。
    只能输入由26个英文字母组成的字符串:"^[A-Za-z]+$"。
    只能输入由26个大写英文字母组成的字符串:"^[A-Z]+$"。
    只能输入由26个小写英文字母组成的字符串:"^[a-z]+$"。
    只能输入由数字和26个英文字母组成的字符串:"^[A-Za-z0-9]+$"。
    只能输入由数字、26个英文字母或者下划线组成的字符串:"^\w+$"。
    验证用户密码:"^[a-zA-Z]\w{5,17}$"正确格式为:以字母开头,长度在6~18之间,只能包含字符、数字和下划线。
    验证是否含有^%&',;=?$\"等字符:"[^%&',;=?$\x22]+"。
    只能输入汉字:"^[\u4e00-\u9fa5]{0,}$"
    验证Email地址:"^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$"。
    验证InternetURL:"^http://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$"。
    验证电话号码:"^(\(\d{3,4}-)|\d{3.4}-)?\d{7,8}$"正确格式为:"XXX-XXXXXXX"、"XXXX-XXXXXXXX"、"XXX-XXXXXXX"、"XXX-XXXXXXXX"、"XXXXXXX"和"XXXXXXXX"。
    验证身份证号(15位或18位数字):"^\d{15}|\d{18}$"。
    验证一年的12个月:"^(0?[1-9]|1[0-2])$"正确格式为:"01"~"09"和"1"~"12"。
    验证一个月的31天:"^((0?[1-9])|((1|2)[0-9])|30|31)$"正确格式为;"01"~"09"和"1"~"31"。
    匹配中文字符的正则表达式: [\u4e00-\u9fa5]
    匹配双字节字符(包括汉字在内):[^\x00-\xff]
    应用:计算字符串的长度(一个双字节字符长度计2,ASCII字符计1)
    String.prototype.len=function(){return this.replace(/[^\x00-\xff]/g,"aa").length;}
    匹配空行的正则表达式:\n[\s| ]*\r
    匹配html标签的正则表达式:<(.*)>(.*)<\/(.*)>|<(.*)\/>
    匹配首尾空格的正则表达式:(^\s*)|(\s*$)
    应用:javascript中没有像vbscript那样的trim函数,我们就可以利用这个表达式来实现,如下:
    String.prototype.trim = function()
    {
    return this.replace(/(^\s*)|(\s*$)/g, "");
    }
    利用正则表达式分解和转换IP地址:
    下面是利用正则表达式匹配IP地址,并将IP地址转换成对应数值的Javascript程序:
    function IP2V(ip)
    {
    re=/(\d+)\.(\d+)\.(\d+)\.(\d+)/g //匹配IP地址的正则表达式
    if(re.test(ip))
    {
    return RegExp.$1*Math.pow(255,3))+RegExp.$2*Math.pow(255,2))+RegExp.$3*255+RegExp.$4*1
    }
    else
    {
    throw new Error("Not a valid IP address!")
    }
    }
    不过上面的程序如果不用正则表达式,而直接用split函数来分解可能更简单,程序如下:
    var ip="10.100.20.168"
    ip=ip.split(".")
    alert("IP值是:"+(ip[0]*255*255*255+ip[1]*255*255+ip[2]*255+ip[3]*1))
    匹配Email地址的正则表达式:\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*
    匹配网址URL的正则表达式:http://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)?
    利用正则表达式限制网页表单里的文本框输入内容:
    用正则表达式限制只能输入中文:onkeyup="value=value.replace(/[^\u4E00-\u9FA5]/g,'')" onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\u4E00-\u9FA5]/g,''))"
    用正则表达式限制只能输入全角字符: onkeyup="value=value.replace(/[^\uFF00-\uFFFF]/g,'')" onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\uFF00-\uFFFF]/g,''))"
    用正则表达式限制只能输入数字:onkeyup="value=value.replace(/[^\d]/g,'') "onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\d]/g,''))"
    用正则表达式限制只能输入数字和英文:onkeyup="value=value.replace(/[\W]/g,'') "onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\d]/g,''))"
    <input onkeyup="value=value.replace(/[^\u4E00-\u9FA5\w]/g,'')" onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\u4E00-\u9FA5\w]/g,''))" value="允许下划线,数字字母和汉字">
    <script language="javascript">
    if (document.layers)//触发键盘事件
    document.captureEvents(Event.KEYPRESS)
    function xz(thsv,nob){
    if(nob=="2"){
    window.clipboardData.setData("text","")
    alert("避免非法字符输入,请勿复制字符");
    return false;
    }
    if (event.keyCode!=8 && event.keyCode!=16 && event.keyCode!=37 && event.keyCode!=38 && event.keyCode!=39 && event.keyCode!=40){
    thsvv=thsv.value;//输入的值
    thsvs=thsvv.substring(thsvv.length-1);//输入的最后一个字符
    //thsvss=thsvv.substring(0,thsvv.length-1);//去掉最后一个错误字符
    if (!thsvs.replace(/[^\u4E00-\u9FA5\w]/g,'') || event.keyCode==189){//正则除去符号和下划线 key
    thsv.value='请勿输入非法符号 ['+thsvs+']';
    alert('请勿输入非法符号 ['+thsvs+']');
    thsv.value="";
    return false;
    }
    }
    }
    </script>
    <input onkeyup="xz(this,1)" onPaste="xz(this,2)" value="">允许数字字母和汉字
    <script language="javascript">
    <!--
    function MaxLength(field,maxlimit){
    var j = field.value.replace(/[^\x00-\xff]/g,"**").length;
    //alert(j);
    var tempString=field.value;
    var tt="";
    if(j > maxlimit){
    for(var i=0;i<maxlimit;i++){
    if(tt.replace(/[^\x00-\xff]/g,"**").length < maxlimit)
    tt = tempString.substr(0,i+1);
    else
    break;
    }
    if(tt.replace(/[^\x00-\xff]/g,"**").length > maxlimit)
    tt=tt.substr(0,tt.length-1);
    field.value = tt;
    }else{
    ;
    }
    }
    </script>
    单行文本框控制<br />
    <INPUT type="text" id="Text1" name="Text1" onpropertychange="MaxLength(this, 5)"><br />
    多行文本框控制:<br />
    <TEXTAREA rows="14"
    cols="39" id="Textarea1" name="Textarea1" onpropertychange="MaxLength(this, 15)"></TEXTAREA><br />
    控制表单内容只能输入数字,中文....
    <script>
    function test()  
    {
    if(document.a.b.value.length>50)
    {
    alert("不能超过50个字符!");
    document.a.b.focus();
    return false;
    }
    }
    </script>
    <form name=a onsubmit="return test()">
    <textarea name="b" cols="40" wrap="VIRTUAL" rows="6"></textarea>
    <input type="submit" name="Submit" value="check">
    </form>
    只能是汉字
    <input onkeyup="value=value.replace(/[^\u4E00-\u9FA5]/g,'')">
    只能是英文字符
    <script language=javascript>
    function onlyEng()
    {
    if(!(event.keyCode>=65&&event.keyCode<=90))
        event.returnValue=false;
    }
    </script>
    <input onkeydown="onlyEng();">
    <input name="coname" type="text" size="50" maxlength="35" class="input2" onkeyup="value=value.replace(/[\W]/g,'') "onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\d]/g,''))">
    只能是数字
    <script language=javascript>
    function onlyNum()
    {
    if(!((event.keyCode>=48&&event.keyCode<=57)||(event.keyCode>=96&&event.keyCode<=105)))
    //考虑小键盘上的数字键
        event.returnValue=false;
    }
    </script>
    <input onkeydown="onlyNum();">
    只能是英文字符和数字
    <input onkeyup="value=value.replace(/[\W]/g,'') "onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\d]/g,''))">
    验证为email格式
    <SCRIPT LANGUAGE=Javascript RUNAT=Server>
    function isEmail(strEmail) {
    if (strEmail.search(/^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/) != -1)
    return true;
    else
    alert("oh");
    }
    </SCRIPT>
    <input type=text onblur=isEmail(this.value)>
    屏蔽关键字(sex , fuck) - 已修改
    <script language="JavaScript1.2">
    function test() {
    if((a.b.value.indexOf ("sex") == 0)||(a.b.value.indexOf ("fuck") == 0)){
        alert("五讲四美三热爱");
        a.b.focus();
        return false;}
    }
    </script>
    <form name=a onsubmit="return test()">
    <input type=text name=b>
    <input type="submit" name="Submit" value="check">
    </form>
    限制文本框里只能输入数字
    <input onkeyup="if(event.keyCode !=37 && event.keyCode != 39) value=value.replace(/\D/g,'');"onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/\D/g,''))"> 
    <PIXTEL_MMI_EBOOK_2005>2                                                           </PIXTEL_MMI_EBOOK_2005>
    JAVA正则表达式语法(转)
    正则表达式语法
    正则表达式是一种文本模式,包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为“元字符”)。模式描述在搜索文本时要匹配的一个或多个字符串。
    正则表达式示例
    表达式 匹配 
    /^\s*$/
    匹配空行。
    /\d{2}-\d{5}/
    验证由两位数字、一个连字符再加 5 位数字组成的 ID 号。
    /<\s*(\S+)(\s[^>]*)?>[\s\S]*<\s*\/\1\s*>/
    匹配 HTML 标记。
    下表包含了元字符的完整列表以及它们在正则表达式上下文中的行为:
    字符 说明 
    \
    将下一字符标记为特殊字符、文本、反向引用或八进制转义符。例如,“n”匹配字符“n”。“\n”匹配换行符。序列“\\”匹配“\”,“\(”匹配“(”。
    ^
    匹配输入字符串开始的位置。如果设置了 RegExp 对象的 Multiline 属性,^ 还会与“\n”或“\r”之后的位置匹配。
    $
    匹配输入字符串结尾的位置。如果设置了 RegExp 对象的 Multiline 属性,$ 还会与“\n”或“\r”之前的位置匹配。
    *
    零次或多次匹配前面的字符或子表达式。例如,zo* 匹配“z”和“zoo”。* 等效于 {0,}。
    +
    一次或多次匹配前面的字符或子表达式。例如,“zo+”与“zo”和“zoo”匹配,但与“z”不匹配。+ 等效于 {1,}。
    ?
    零次或一次匹配前面的字符或子表达式。例如,“do(es)?”匹配“do”或“does”中的“do”。? 等效于 {0,1}。
    {n}
    n 是非负整数。正好匹配 n 次。例如,“o{2}”与“Bob”中的“o”不匹配,但与“food”中的两个“o”匹配。
    {n,}
    n 是非负整数。至少匹配 n 次。例如,“o{2,}”不匹配“Bob”中的“o”,而匹配“foooood”中的所有 o。“o{1,}”等效于“o+”。“o{0,}”等效于“o*”。
    {n,m}
    M 和 n 是非负整数,其中 n <= m。匹配至少 n 次,至多 m 次。例如,“o{1,3}”匹配“fooooood”中的头三个 o。'o{0,1}' 等效于 'o?'。注意:您不能将空格插入逗号和数字之间。
    ?
    当此字符紧随任何其他限定符(*、+、?、{n}、{n,}、{n,m})之后时,匹配模式是“非贪心的”。“非贪心的”模式匹配搜索到的、尽可能短的字符串,而默认的“贪心的”模式匹配搜索到的、尽可能长的字符串。例如,在字符串“oooo”中,“o+?”只匹配单个“o”,而“o+”匹配所有“o”。
    .
    匹配除“\n”之外的任何单个字符。若要匹配包括“\n”在内的任意字符,请使用诸如“[\s\S]”之类的模式。
    (pattern)
    匹配 pattern 并捕获该匹配的子表达式。可以使用 $0…$9 属性从结果“匹配”集合中检索捕获的匹配。若要匹配括号字符 ( ),请使用“\(”或者“\)”。
    (?:pattern)
    匹配 pattern 但不捕获该匹配的子表达式,即它是一个非捕获匹配,不存储供以后使用的匹配。这对于用“or”字符 (|) 组合模式部件的情况很有用。例如,'industr(?:y|ies) 是比 'industry|industries' 更经济的表达式。
    (?=pattern)
    执行正向预测先行搜索的子表达式,该表达式匹配处于匹配 pattern 的字符串的起始点的字符串。它是一个非捕获匹配,即不能捕获供以后使用的匹配。例如,'Windows (?=95|98|NT|2000)' 匹配“Windows 2000”中的“Windows”,但不匹配“Windows 3.1”中的“Windows”。预测先行不占用字符,即发生匹配后,下一匹配的搜索紧随上一匹配之后,而不是在组成预测先行的字符后。
    (?!pattern)
    执行反向预测先行搜索的子表达式,该表达式匹配不处于匹配 pattern 的字符串的起始点的搜索字符串。它是一个非捕获匹配,即不能捕获供以后使用的匹配。例如,'Windows (?!95|98|NT|2000)' 匹配“Windows 3.1”中的 “Windows”,但不匹配“Windows 2000”中的“Windows”。预测先行不占用字符,即发生匹配后,下一匹配的搜索紧随上一匹配之后,而不是在组成预测先行的字符后。
    x|y
    匹配 x 或 y。例如,'z|food' 匹配“z”或“food”。'(z|f)ood' 匹配“zood”或“food”。
    [xyz]
    字符集。匹配包含的任一字符。例如,“[abc]”匹配“plain”中的“a”。
    [^xyz]
    反向字符集。匹配未包含的任何字符。例如,“[^abc]”匹配“plain”中的“p”。
    [a-z]
    字符范围。匹配指定范围内的任何字符。例如,“[a-z]”匹配“a”到“z”范围内的任何小写字母。
    [^a-z]
    反向范围字符。匹配不在指定的范围内的任何字符。例如,“[^a-z]”匹配任何不在“a”到“z”范围内的任何字符。
    \b
    匹配一个字边界,即字与空格间的位置。例如,“er\b”匹配“never”中的“er”,但不匹配“verb”中的“er”。
    \B
    非字边界匹配。“er\B”匹配“verb”中的“er”,但不匹配“never”中的“er”。
    \cx
    匹配 x 指示的控制字符。例如,\cM 匹配 Control-M 或回车符。x 的值必须在 A-Z 或 a-z 之间。如果不是这样,则假定 c 就是“c”字符本身。
    \d
    数字字符匹配。等效于 [0-9]。
    \D
    非数字字符匹配。等效于 [^0-9]。
    \f
    换页符匹配。等效于 \x0c 和 \cL。
    \n
    换行符匹配。等效于 \x0a 和 \cJ。
    \r
    匹配一个回车符。等效于 \x0d 和 \cM。
    \s
    匹配任何空白字符,包括空格、制表符、换页符等。与 [ \f\n\r\t\v] 等效。
    \S
    匹配任何非空白字符。与 [^ \f\n\r\t\v] 等效。
    \t
    制表符匹配。与 \x09 和 \cI 等效。
    \v
    垂直制表符匹配。与 \x0b 和 \cK 等效。
    \w
    匹配任何字类字符,包括下划线。与“[A-Za-z0-9_]”等效。
    \W
    与任何非单词字符匹配。与“[^A-Za-z0-9_]”等效。
    \xn
    匹配 n,此处的 n 是一个十六进制转义码。十六进制转义码必须正好是两位数长。例如,“\x41”匹配“A”。“\x041”与“\x04”&“1”等效。允许在正则表达式中使用 ASCII 代码。
    \num
    匹配 num,此处的 num 是一个正整数。到捕获匹配的反向引用。例如,“(.)\1”匹配两个连续的相同字符。
    \n
    标识一个八进制转义码或反向引用。如果 \n 前面至少有 n 个捕获子表达式,那么 n 是反向引用。否则,如果 n 是八进制数 (0-7),那么 n 是八进制转义码。
    \nm
    标识一个八进制转义码或反向引用。如果 \nm 前面至少有 nm 个捕获子表达式,那么 nm 是反向引用。如果 \nm 前面至少有 n 个捕获,则 n 是反向引用,后面跟有字符 m。如果两种前面的情况都不存在,则 \nm 匹配八进制值 nm,其中 n 和 m 是八进制数字 (0-7)。
    \nml
    当 n 是八进制数 (0-3),m 和 l 是八进制数 (0-7) 时,匹配八进制转义码 nml。
    \un
    匹配 n,其中 n 是以四位十六进制数表示的 Unicode 字符。例如,\u00A9 匹配版权符号 (?)。

    posted @ 2014-01-15 00:16 奋斗成就男人 阅读(249) | 评论 (0)编辑 收藏

    MyEclipse设置编码方式

    MyEclipse设置编码方式
    1、windows->Preferences……打开"首选项"对话框,左侧导航树,导航到general->Workspace,
    右侧Text file encoding,选择Other,改变为UTF-8,以后新建立工程其属性对话框中的Text file encoding即为UTF-8.
     
    2、 windows->Preferences……打开"首选项"对话框,左侧导航树,导航到general->Content Types,右侧Context Types树,点开Text中每一颗子项,并在中输入"UTF-8",点update! 其他java应用开发相关的文件如:properties、XML等已经由Eclipse缺省指定,分别为ISO8859-1,UTF-8,如开发中确需 改变编码格式则可以在此指定。
     
    3、window——>preference——>MyEclipse——>Files and Editors,将每个子项的"Encoding"改为"ISO 10645/Unicode(UTF-8)",点Apply! 
     
    4、 选中工程---->右键--->properties---->Resource---->Text Fiel Encoding---->设置成UTF-8
    4、经过上述三步,新建java文件即为UTF-8编码,Eclipse编译、运行、调试都没问题。

    posted @ 2014-01-14 23:59 奋斗成就男人 阅读(229) | 评论 (0)编辑 收藏

    myeclipse中java文件头注释格式设置

    myeclipse中java文件头注释格式设置  

    windows->preferences->java->Code Templates->comments->Type->edit 
    Eclipse注释规范模版总结
    新建类文件
    /**
     * @ClassName:     ${file_name}
     * @Description:   ${todo}(用一句话描述该文件做什么) 
     * 
     * @author         ${user}
     * @version        V1.0  
     * @Date           ${date} ${time} 
     */
    方法
    /** 
     * @Title:        ${enclosing_method} 
     * @Description:  ${todo}(这里用一句话描述这个方法的作用) 
     * @param:        ${tags}    
     * @return:       ${return_type}    
     * @throws 
     * @author        ${user}
     * @Date          ${date} ${time} 
     */
    输入设置模板: 
    /**      
    * ${file_name} Create on ${date}     
    *      
    * Copyright (c) ${date} by taotaosoft      
    *      
    @author <a href="xiuzhong.li@gmail.com">Jerryli</a>     
    @version 1.0 
    *     
    */ 
    注意选择自动添加注释,养成一个规范的习惯是最好的。 
    选菜单 
    windows-->preference  --> Java-->Code Style-->Code Templates  --> code-->new Java files 
    选中点编辑 
    ${filecomment} 
    ${package_declaration} 
    /** 
    @author 作者姓名  E-mail: email地址 
    @version 创建时间:${date} ${time} 
    * 类说明 
    */ 
    ${typecomment} 
    ${type_declaration} 
      
     Eclipse注释规范模版总结
    1、  具体操作
    (1)在eclipse中,打开Window->Preference->Java->Code Style->Code Template
    (2)然后展开Comments节点就是所有需设置注释的元素,参照2注释规范对应设置即可
    2、  注释规范
    (1)文件(Files)注释标签
    /**
     * FileName:     ${file_name}
     * @Description: ${todo}(用一句话描述该文件做什么)
    * All rights Reserved, Designed By ZTE-ITS
     * Copyright:    Copyright(C) 2010-2011
     * Company       ZTE-ITS WuXi LTD.
     * @author:    名字
     * @version    V1.0 
     * Createdate:         ${date} ${time}
     *
     * Modification  History:
     * Date         Author        Version        Discription
     * -----------------------------------------------------------------------------------
     * ${date}       wu.zh          1.0             1.0
     * Why & What is modified: <修改原因描述>
     */
     
    (2)类型(Types)注释标签(类的注释):
     /**
     * @ClassName:     ${type_name}
     * @Description:${todo}(这里用一句话描述这个类的作用)
     * @author:    Android_Robot
     * @date:        ${date} ${time}
     *
     * ${tags}
     */
     
    (3)字段(Fields)注释标签:
     /**  
     * @Fields ${field} : ${todo}(用一句话描述这个变量表示什么)   
     */  
      
    (4)构造函数标签:
     /**
     * @Title:        ${enclosing_type}
     * @Description:    ${todo}(这里用一句话描述这个方法的作用)
     * @param:    ${tags}
     * @throws
     */
     
    (5)方法(Methods)标签:
    /**
     * @Title: ${enclosing_method}
     * @Description: ${todo}(这里用一句话描述这个方法的作用)
     * @param: ${tags}   
     * @return: ${return_type}   
     * @throws
     */
     
    (6)覆盖方法(Overriding Methods)标签:
     /**
     * <p>Title: ${enclosing_method}</p>
     * <p>Description: </p>
     * ${tags}
     * ${see_to_overridden}
     */
     
    (7)代表方法(Delegate Methods)标签:
    /**
     * ${tags}
     * ${see_to_target}
     */
     
    (8)getter方法标签:
    /**
     * @Title:        ${enclosing_method} <BR>
     * @Description: please write your description <BR>
     * @return:     ${field_type} <BR>
     */
     
    (9)setter方法标签:
    /** 
     * @Title:  ${enclosing_method} <BR> 
     * @Description: please write your description <BR> 
     * @return: ${field_type} <BR> 
     */ 

    posted @ 2014-01-14 23:23 奋斗成就男人 阅读(5365) | 评论 (0)编辑 收藏

    WebLogic设置session超时时间

    说明:本文转载自http://hi.baidu.com/%BF%AA%D0%C4%BE%CD%BA%C3_999/blog/item/cbc81c4a9666d32608f7efd7.html


    2008年06月05日 星期四 21:23

    WebLogic如何设置session超时时间
    1 web.xml

    设置WEB应用程序描述符web.xml里的<session-timeout>元素。这个值以分钟为
    单位,并覆盖weblogic.xml中的TimeoutSecs属性
    <session-config>
        <session-timeout>54</session-timeout>
    </session-config>
    此例表示Session将在54分钟后过期
    当<session-timeout>设置为-2,表示将使用在weblogic.xml中设置的
    TimeoutSecs这个属性值。
    当<session-timeout>设置为-1,表示Session将永不过期,而忽略在
    weblogic.xml中设置的TimeoutSecs属性值。
    该属性值可以通过console控制台来设置

    2 weblogic.xml

    设置WebLogic特有部署描述符weblogic.xml的<session-descriptor>元素的
    TimeoutSecs属性。这个值以秒为单位
    <session-descriptor>
       <session-param>
          <param-name>TimeoutSecs</param-name>
          <param-value>3600</param-value>
       </session-param>
    </session-descriptor>
    默认值是3600秒

    3,jsp中控制
    session.setmaxinactiveinterval(7200);
    session是默认对象,可以直接引用,单位秒s

    4,servlet中控制
    httpsession session = request.getsession();
    session.setmaxinactiveinterval(7200);
    单位秒s

    在weblgoic的console中:xxDomain->Servers->xxServer->Protocols->HTTP 中有一个关于Post Timeout的配置,但这个参数一般使用默认值即可

    一般是通过Services-->JDBC-->Connection Pools-->MyConnection(你所建立的连接池名)-->Configration-->Connections 里的Inactive Connection Timeout这个参数来设置的,默认的为0,表示连接时间无限长。你可以设一个时间值,连接超过这个时间值,它会把连接强制放回连接池

    <Server AcceptBacklog="62" CompleteHTTPMessageTimeout="480"
    CompleteMessageTimeout="480" IdleConnectionTimeout="600"
    ListenAddress="" ListenPort="7001" Name="myserver"
    NativeIOEnabled="true" ReliableDeliveryPolicy="RMDefaultPolicy"
    ServerVersion="8.1.4.0">
    是否IdleConnectionTimeout参数

    看连接池中高级选项内的Inactive Connection Timeout和Connection Reserve Timeout时多少, 把这两项设大些试试

    如果在两个文件中同时设置了超时时间,则会以web.xml中为准。
    所以在weblogic环境中,最好将web.xml中关于超时的设置删掉,保持唯一性。
    这也是一个客户发现了问题后,多次实验后发现的。

     

     

     

    如果使用WEBLOGIC作为应用服务器,设置SESSION超时时间会选择在WEBLOGIC的控制台设定。实际上,WEBLOGIC是将超时设定保存在WEB-INF下的weblogic.xml中,格式如下:
    <session-descriptor>
        <session-param>
          <param-name>TimeoutSecs</param-name>
          <param-value>7200</param-value>
        </session-param>
    </session-descriptor>
    param-value中的数值就是超时时间,单位为秒。在设置完这个参数后,会发现超时时间并一定起效。这是为什么呢?
    原来在WEB-INF下还有一个配置文件web.xml,里面同样会有一段设置session,格式如下:

    <session-config>

        <session-timeout>30</session-timeout>

    </session-config>
    session-timeout中的值也是超时时间,单位为分钟。
    如果在两个文件中同时设置了超时时间,则会以web.xml中为准。
    所以在weblogic环境中,最好将web.xml中关于超时的设置删掉,保持唯一性。

    这也是一个客户发现了问题后,多次实验后发现的。

     

     

    今天上午联创科技的一个朋友问题一个他们的问题.出现大量的:

    ueue: ‘billproxyqueue’ has been busy for “727″ seconds working on the request “Http Request: /bill/y
    nQueryPublic.go”, which is more than the configured time (StuckThreadMaxTime) of “600″ seconds.>

    一看明显是连接超时, 导致的错误.

    1. 程序问题,是不是程序中没有关闭连接
    2. 如果程序没问题,则是weblogic的StuckThreadMaxTime设置过小而引起的,一般weblogic server 的StuckThreadMaxTime默认参数是600s,即10分钟,如果并发量过大,而导致等待处理过多,导致系统不停的增加线程,造成线程阻塞,你可以把该参数设置大点这个是稍微调大StuckThreadMaxTime的参数即可.
    3. 看线程数设置,可适当增加线程数,这个在WLS控制台中可以调整

    posted @ 2013-12-06 12:27 奋斗成就男人 阅读(259) | 评论 (0)编辑 收藏

    cookie与session的关系

    为什么会有cookie呢,大家都知道,http是无状态的协议,客户每次读取web页面时,服务器都打开新的会话,而且服务器也不会自动维护客户的上下文信息,那么要怎么才能实现网上商店中的购物车呢,session就是一种保存上下文信息的机制,它是针对每一个用户的,变量的值保存在服务器端,通过 SessionID来区分不同的客户,session是以cookie或URL重写为基础的,默认使用cookie来实现,系统会创造一个名为 JSESSIONID的输出cookie,我们叫做session cookie,以区别persistent cookies,也就是我们通常所说的cookie,注意session cookie是存储于浏览器内存中的,并不是写到硬盘上的,这也就是我们刚才看到的JSESSIONID,我们通常情是看不到JSESSIONID的,但是当我们把浏览器的cookie禁止后,web服务器会采用URL重写的方式传递Sessionid,我们就可以在地址栏看到 sessionid=KWJHUG6JJM65HS2K6之类的字符串。 
            明白了原理,我们就可以很容易的分辨出persistent cookies和session cookie的区别了,网上那些关于两者安全性的讨论也就一目了然了,session cookie针对某一次会话而言,会话结束session cookie也就随着消失了,而persistent cookie只是存在于客户端硬盘上的一段文本(通常是加密的),而且可能会遭到cookie欺骗以及针对cookie的跨站脚本攻击,自然不如 session cookie安全了。 
            通常session cookie是不能跨窗口使用的,当你新开了一个浏览器窗口进入相同页面时,系统会赋予你一个新的sessionid,这样我们信息共享的目的就达不到了,此时我们可以先把sessionid保存在persistent cookie中,然后在新窗口中读出来,就可以得到上一个窗口SessionID了,这样通过session cookie和persistent cookie的结合我们就实现了跨窗口的session tracking(会话跟踪)。 
            在一些web开发的书中,往往只是简单的把Session和cookie作为两种并列的http传送信息的方式,session cookies位于服务器端,persistent cookie位于客户端,可是session又是以cookie为基础的,明白的两者之间的联系和 
    区别,我们就不难选择合适的技术来开发web service了 
    cookie 
    Session是由应用服务器维持的一个服务器端的存储空间,用户在连接服务器时,会由服务器生成一个唯一的SessionID,用该SessionID 为标识符来存取服务器端的Session存储空间。而SessionID这一数据则是保存到客户端,用Cookie保存的,用户提交页面时,会将这一 SessionID提交到服务器端,来存取Session数据。这一过程,是不用开发人员干预的。所以一旦客户端禁用Cookie,那么Session也会失效。 

    服务器也可以通过URL重写的方式来传递SessionID的值,因此不是完全依赖Cookie。如果客户端Cookie禁用,则服务器可以自动通过重写URL的方式来保存Session的值,并且这个过程对程序员透明。 

    可以试一下,即使不写Cookie,在使用request.getCookies();取出的Cookie数组的长度也是1,而这个Cookie的名字就是JSESSIONID,还有一个很长的二进制的字符串,是SessionID的值。 
    Cookie是客户端的存储空间,由浏览器来维持。
     
    总结:
    1:cookie是通过头部header返回到浏览器中并保存在磁盘中,下次再次访问该服务器中。浏览器会自动把该cookie传输到服务器中。
    2:Session与Cookie是一对的,Session使用的基础就是cookie。
    3:cookie分为两种,如果设置cookie时没有设置有效时间,就表示该cookie是临时性的,只保存在浏览器的内存中,即seesion-cookie,只要关闭浏览器,该cookie即将消失。
                              如果cookie设置了有效时间,就表示该cookie是持久化的,即persistent cookie。此外还可以为持久化cookie设置域名和路径。
    4:当禁止cookie后,就返回通过url地址返回cookie Id。
    5:如来是否自定义cookie值,服务器都会自动产生一个cookie值,名称为:
    JSESSIONID,而值就是服务器中的sessionid值。

    创建cookie的步骤: 以java为例:
     1: 创建cookie对象:Cookie cookie = new Cookie("cookiename","cookievalue"); 
     2:设置有效期:cookie.setMaxAge(3600); 
     3:设置路径:cookie.setPath("/"); //设置路径,这个路径即该工程下都可以访问该cookie 如果不设置路径,那么只有设置该cookie路径及其子路径可以访问 
     4:设置域名:cookie.setDomain(".zl.org") ;  //域名要以“.”开头 
     5:在返回对象中添加cookie对象:response.addCookie(cookie) ; 
     6:返回对象response其他的操作。

    以下为Java操作Cookie实例:
    java对cookie的操作比较简单,主要介绍下建立cookie和读取cookie,以及如何设定cookie的生命周期和cookie的路径问题。

    建立一个无生命周期的cookie,即随着浏览器的关闭即消失的cookie,代码如下

    HttpServletRequest request  
    HttpServletResponse response
    Cookie cookie = new Cookie("cookiename","cookievalue");
    response.addCookie(cookie);
     
    下面建立一个有生命周期的cookie,可以设置他的生命周期

    cookie = new Cookie("cookiename","cookievalue");
     
    cookie.setMaxAge(3600);
     
    //设置路径,这个路径即该工程下都可以访问该cookie 如果不设置路径,那么只有设置该cookie路径及其子路径可以访问
     
    cookie.setPath("/");
    response.addCookie(cookie);
     

    下面介绍如何读取cookie,读取cookie代码如下

    Cookie[] cookies = request.getCookies();//这样便可以获取一个cookie数组
    for(Cookie cookie : cookies){
        cookie.getName();// get the cookie name
        cookie.getValue(); // get the cookie value
    }
     

    上面就是基本的读写cookie的操作。我们在实际中最好进行一下封装,比如增加一个cookie,我们关注的是cookie的name,value,生命周期,所以进行封装一个函数,当然还要传入一个response对象,addCookie()代码如下

    /**
     * 设置cookie
     * 
    @param response
     * 
    @param name  cookie名字
     * 
    @param value cookie值
     * 
    @param maxAge cookie生命周期  以秒为单位
     
    */
    public static void addCookie(HttpServletResponse response,String name,String value,int maxAge){
        Cookie cookie = new Cookie(name,value);
        cookie.setPath("/");
        if(maxAge>0)  cookie.setMaxAge(maxAge);
        response.addCookie(cookie);
    }
     

    读取cookie的时候,为了方便我们的操作,我们希望封装一个函数,只要我们提供cookie的name,我们便可以获取cookie的value,带着这个想法,很容易想到将cookie封装到Map里面,于是进行下面的封装.
    /**
     * 根据名字获取cookie
     * 
    @param request
     * 
    @param name cookie名字
     * 
    @return
     
    */
    public static Cookie getCookieByName(HttpServletRequest request,String name){
        Map<String,Cookie> cookieMap = ReadCookieMap(request);
        if(cookieMap.containsKey(name)){
            Cookie cookie = (Cookie)cookieMap.get(name);
            return cookie;
        }else{
            return null;
        }   
    }
      
    /**
     * 将cookie封装到Map里面
     * 
    @param request
     * 
    @return
     
    */
    private static Map<String,Cookie> ReadCookieMap(HttpServletRequest request){  
        Map<String,Cookie> cookieMap = new HashMap<String,Cookie>();
        Cookie[] cookies = request.getCookies();
        if(null!=cookies){
            for(Cookie cookie : cookies){
                cookieMap.put(cookie.getName(), cookie);
            }
        }
        return cookieMap;
    }

    posted @ 2013-11-26 00:01 奋斗成就男人 阅读(165) | 评论 (0)编辑 收藏

    Java中Cookie的使用

    1、Cookie的来历与作用

    Cookie是WEB服务器通过浏览器保存在WWW用户端硬盘上的一个文本文件,这个文本文件中包含了文本信息。
    文本信息的内容以“名/值”对(key/value)的形式进行存储。
    可以让WEB开发者通过程序读写这个文本文件。
    XP中保存Cookie的目录是“C://Documents and Settings\用户名\Cookies”
    Cookie的作用
    解决浏览器用户与Web服务器之间无状态通信。
    2Cookie编程

    //创建对象
    Date date = new Date() ;
    Cookie c = new Cookie("lastVisited",date.toString()) ;
    //设定有效时间  以s为单位
    c.setMaxAge(60) ;
    //设置Cookie路径和域名
    c.setPath("/") ;
    c.setDomain(".zl.org") ;  //域名要以“.”开头
    //发送Cookie文件
    response.addCookie(c) ;
    //读取Cookie
    Cookie cookies[] = request.getCookies() ;
    Cookie c1 = null ;
    if(cookies != null){
        for(int i=0;i<cookies.length;i++){
           c1 = cookies[i] ;
           out.println("cookie name : " + c1.getName() + "   ") ;
           out.println("cookie value :" + c1.getValue() + "<br>");
        }
    }
    //修改Cookie
    Cookie cookies[] = request.getCookies() ;
    Cookie c = null ;
    for(int i=0;i<cookies.length;i++){
       c = cookies[i] ;
       if(c.getName().equals("lastVisited")){
          c.setValue("2010-04-3-28") ;
          c.setMaxAge(60*60*12) ;
          response.addCookie(c) ;     //修改后,要更新到浏览器中    
       }
    }

    //删除Cookie,(将Cookie的有效时间设为0)
    Cookie cookies[] = request.getCookies() ;
    Cookie c = null ;
    for(int i=0;i<cookies.length;i++){
       c = cookies[i] ;
       if(c.getName().equals("lastVisited")){
          c.setMaxAge(0);
          response.addCookie(c) ;
       }
    }
     
    4、使用Cookie的注意事项

    ·Cookie的大小和数量是有限制的。
    ·Cookie在个人硬盘上所保存的文本信息是以明文格式进行保存的,没有任何的加密措施。
    ·浏览器用户可以设定不使用Cookie。
    5、实例:Servlet中的Cookie编程

     cookieInput.html页面
     
    SetCookie.java
     
    GetCookie.java
     
     
    cookieInput.html页面中的参数提交到SetCookie.java中,由SetCookie.java保存在浏览器的Cookie中,在SerCookie.java中链接到GetCookie.java从而读取刚刚保存的Cookie。

    SetCookie.java :
    public void doPost(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
     
            response.setContentType("text/html;charset=utf-8");
            PrintWriter out = response.getWriter();
            String username = request.getParameter("username") ;
            //保存Cookie
            if(username !=""){
                Cookie c1 = new Cookie("username",username) ;
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd") ;
                Cookie c2 = new Cookie("lastVisited",sdf.format(new java.util.Date())) ;
                c1.setMaxAge(60*60*60*12*30) ;
                c2.setMaxAge(60*60*60*12*30) ;
                response.addCookie(c1) ;
                response.addCookie(c2) ;
                out.println("Cookie保存成功!");
                out.println("<br><br>") ;
                out.println("<a href=GetCookie02>读取Cookie</a>") ;
            }else{
                response.sendRedirect("../cookieInput.html") ;
            }
           
           
            out.flush();
            out.close();
        }
     
    GetCookie.java:
    public void doPost(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
     
            response.setContentType("text/html;charset=utf-8");
            PrintWriter out = response.getWriter();
            out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">");
            out.println("<HTML>");
            out.println("  <HEAD><TITLE>A Servlet</TITLE></HEAD>");
            out.println("  <BODY>");
           
            //读取Cookie
            Cookie cookies[] = request.getCookies() ;
            Cookie c = null ;
            if(cookies != null){
                for(int i=0;i<cookies.length;i++){
                    c = cookies[i] ;
                    if(c.getName().equals("username")){
                        out.println("用户名: "+c.getValue());
                        out.println("<br>");
                    }
                    if(c.getName().equals("lastVisited")){
                        out.println("上次登录的时间: "+c.getValue());
                    }
                }
            }else{
                out.println("No cookie !");
            }
           
            out.println("  </BODY>");
            out.println("</HTML>");
            out.flush();
            out.close();
        }

    posted @ 2013-11-25 22:15 奋斗成就男人 阅读(163) | 评论 (0)编辑 收藏

    Java读取目录下Txt文本

      /**
         * 功能:Java读取目录下txt文件的内容
         * 步骤:先获得目录句柄,如果是文件直接读取文件,如果是目录,继续迭代处理
         * 
    @param directoryPath
         
    */
        public static void readTxtDirectory(String directoryPath){
            File dir = new File(directoryPath);
            if(dir.isFile()) {           //读取文件
                readTxtFile(directoryPath);   
            } else if(dir.isDirectory()) {    //读取目录
                File[] files = dir.listFiles();
                for(int i=0;i<files.length;i++){
                    System.out.println((files[i].isDirectory()?"目录 :":"文件 :")+files[i].getName());
                    if(files[i].isFile()) {
                        readTxtFile(files[i].getAbsolutePath());
                    } else {
                        readTxtDirectory(files[i].getAbsolutePath());
                    }
                }
            } else { 
                 System.out.println("路径不存在!");
            }
        }
        
         /**
         * 功能:Java读取Txt文件的内容
         * 步骤:1:先获得文件句柄
         * 2:获得文件句柄当做是输入一个字节码流,需要对这个输入流进行读取
         * 3:读取到输入流后,需要读取生成字节流
         * 4:一行一行的输出。readline()。
         * 备注:需要考虑的是异常情况
         * 
    @param filePath
         
    */
        public static void readTxtFile(String filePath){
            try {
                    String encoding="GBK";
                    File file = new File(filePath);
                    if(file.isFile() && file.exists()){ //判断文件是否存在
                        InputStreamReader read = new InputStreamReader(
                        new FileInputStream(file),encoding);//考虑到编码格式
                        BufferedReader bufferedReader = new BufferedReader(read);
                        String lineTxt = null;
                        while((lineTxt = bufferedReader.readLine()) != null){
                            lineTxt = lineTxt.trim();
                            if(lineTxt.length() > 0) {
                                String regEx = "[' ']+"; // 一个或多个空格  
                                Pattern p = Pattern.compile(regEx);  
                                Matcher m = p.matcher(lineTxt);
                                String[] txtArray = m.replaceAll(";").trim().split(";");
                                if(txtArray.length == 6 && txtArray[0].length() == 15) {
                                    System.out.println(lineTxt);
                                }    
                            }
                        }
                        read.close();
                    } else {
                        System.out.println("文件不存在!");
                    }
            } catch (Exception e) {
                System.out.println("读取文件内容出错");
                e.printStackTrace();
            }
        }

    posted @ 2013-11-21 19:24 奋斗成就男人 阅读(255) | 评论 (0)编辑 收藏

    HttpClient 4 和 HttpClient 3 设置超时

    HttpClient 4:

    连接超时:
    httpclient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT,60000);
    // 或者
    HttpConnectionParams.setConnectionTimeout(params, 6000);

    读取超时:
    httpclient.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT,60000);
    // 或者
    HttpConnectionParams.setSoTimeout(params, 60000);


    HttpClient 3:

    连接超时:
    httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(60000);

    读取超时:
    httpClient.getHttpConnectionManager().getParams().setSoTimeout(60000);

    设置get方法请求超时为 5 秒
    GetMethod getMethod= new  GetMethod(url);    
    getMethod.getParams().setParameter(HttpMethodParams.SO_TIMEOUT,5000 ); 

    设置连接超时和请求超时,这两个超时的意义不同,需要分别设置

    posted @ 2013-11-13 20:54 奋斗成就男人 阅读(229) | 评论 (0)编辑 收藏

    同步静态方法

    问:当定义了方法A和方法B,当实例化类后,多线程如何保证调用方法A时方法B即使被调用也不会被执行?Java有保证这种机制的关键字吗?

    答:用 synchronized 搜索修饰方法   例如: 
    public class O
    {
    public synchronized void A(){}
    public synchronized void B(){}
    }
    同一个类中的所有synchronized修饰的方法是不能同时调用的,也就是说同时只能调用其中一个方法,比如线程1调用A方法,在A方法执行完之前,线程2调用B方法,这个时候线程2就会阻塞,直到线程1调用完A方法后,线程2才开始执行B方法!

    还有一个解决方法就是加一个同步对象锁

    public class O
    {
    Object lock;
    public void A()
    {
    synchronized(lock)
    {
    //这里写方法内容
    }
    }
    public void B()
    {
    synchronized(lock)
    {
    //这里写方法内容
    }
    }
    }


    注意:同一个类中所有的同步的静态方法,它们在类范围类是同步的,也就是同一时间只能有一个线程可以访问所有同步静态方法中的一个。

     

    不同类中的静态同步方法互不影响。前面所说,静态同步方法是类级别的,也就是以类为单位进行控制的。如果两个线程访问不同类中的同步方法,这两个线程是不需要等待的,即使是静态方法。





    posted @ 2013-11-06 19:29 奋斗成就男人 阅读(310) | 评论 (0)编辑 收藏

    如何在Oracle中复制表结构和表数据

    如何在Oracle中复制表结构和表数据 

    1. 复制表结构及其数据:

    create table table_name_new as select * from table_name_old

    2. 只复制表结构:

    create table table_name_new as select * from table_name_old where 1=2;

    或者:

    create table table_name_new like table_name_old

    3. 只复制表数据:

    如果两个表结构一样:

    insert into table_name_new select * from table_name_old

    如果两个表结构不一样:

    insert into table_name_new(column1,column2...) select column1,column2... from table_name_old

    posted @ 2013-11-05 21:29 奋斗成就男人 阅读(165) | 评论 (0)编辑 收藏

    基于注解的 Spring MVC 简单入门

    以下内容是经过自己整理资料、官方文档所得:


    web.xml 配置:

     

    <servlet> 	<servlet-name>dispatcher</servlet-name> 	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 	<init-param> 		<description>加载/WEB-INF/spring-mvc/目录下的所有XML作为Spring MVC的配置文件</description> 		<param-name>contextConfigLocation</param-name> 		<param-value>/WEB-INF/spring-mvc/*.xml</param-value> 	</init-param> 	<load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> 	<servlet-name>dispatcher</servlet-name> 	<url-pattern>*.htm</url-pattern> </servlet-mapping>

     

    这样,所有的.htm的请求,都会被DispatcherServlet处理;

    初始化 DispatcherServlet 时,该框架在 web 应用程序WEB-INF 目录中寻找一个名为[servlet-名称]-servlet.xml的文件,并在那里定义相关的Beans,重写在全局中定义的任何Beans,像上面的web.xml中的代码,对应的是dispatcher-servlet.xml;当然也可以使用<init-param>元素,手动指定配置文件的路径;

    dispatcher-servlet.xml 配置:

     

    <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"        xmlns:mvc="http://www.springframework.org/schema/mvc"        xmlns:p="http://www.springframework.org/schema/p"        xmlns:context="http://www.springframework.org/schema/context"        xmlns:aop="http://www.springframework.org/schema/aop"        xmlns:tx="http://www.springframework.org/schema/tx"        xsi:schemaLocation="http://www.springframework.org/schema/beans 			http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 			http://www.springframework.org/schema/context  			http://www.springframework.org/schema/context/spring-context-3.0.xsd 			http://www.springframework.org/schema/aop  			http://www.springframework.org/schema/aop/spring-aop-3.0.xsd 			http://www.springframework.org/schema/tx  			http://www.springframework.org/schema/tx/spring-tx-3.0.xsd 			http://www.springframework.org/schema/mvc  			http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd 			http://www.springframework.org/schema/context  			http://www.springframework.org/schema/context/spring-context-3.0.xsd">     <!--         使Spring支持自动检测组件,如注解的Controller     -->     <context:component-scan base-package="com.minx.crm.web.controller"/>         <bean id="viewResolver"           class="org.springframework.web.servlet.view.InternalResourceViewResolver"           p:prefix="/WEB-INF/jsp/"           p:suffix=".jsp" /> </beans>

     

    第一个Controller

    package com.minx.crm.web.controller;  import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class IndexController {     @RequestMapping("/index")     public String index() {         return "index";     } }

    @Controller注解标识一个控制器,@RequestMapping注解标记一个访问的路径(/index.htm),return "index"标记返回视图(index.jsp);

    注:如果@RequestMapping注解在类级别上,则表示一相对路径,在方法级别上,则标记访问的路径;

    @RequestMapping注解标记的访问路径中获取参数:

    Spring MVC 支持RESTful风格的URL参数,如:

    @Controller public class IndexController {      @RequestMapping("/index/{username}")     public String index(@PathVariable("username") String username) {         System.out.print(username);         return "index";     } }

    @RequestMapping中定义访问页面的URL模版,使用{}传入页面参数,使用@PathVariable 获取传入参数,即可通过地址:http://localhost:8080/crm/index/tanqimin.htm 访问;

    根据不同的Web请求方法,映射到不同的处理方法:

    使用登陆页面作示例,定义两个方法分辨对使用GET请求和使用POST请求访问login.htm时的响应。可以使用处理GET请求的方法显示视图,使用POST请求的方法处理业务逻辑

    @Controller public class LoginController {     @RequestMapping(value = "/login", method = RequestMethod.GET)     public String login() {         return "login";     }     @RequestMapping(value = "/login", method = RequestMethod.POST)     public String login2(HttpServletRequest request) {             String username = request.getParameter("username").trim();             System.out.println(username);         return "login2";     } }

    在视图页面,通过地址栏访问login.htm,是通过GET请求访问页面,因此,返回登陆表单视图login.jsp;当在登陆表单中使用POST请求提交数据时,则访问login2方法,处理登陆业务逻辑;

    防止重复提交数据,可以使用重定向视图:

    return "redirect:/login2"

    可以传入方法的参数类型:

    @RequestMapping(value = "login", method = RequestMethod.POST) public String testParam(HttpServletRequest request, HttpServletResponse response, HttpSession session) { 	String username = request.getParameter("username"); 	System.out.println(username); 	return null; }

     

    可以传入HttpServletRequestHttpServletResponseHttpSession,值得注意的是,如果第一次访问页面,HttpSession没被创建,可能会出错;

    其中,String username = request.getParameter("username");可以转换为传入的参数:

     

    @RequestMapping(value = "login", method = RequestMethod.POST) public String testParam(HttpServletRequest request, HttpServletResponse response, HttpSession session,@RequestParam("username") String username) { 	String username = request.getParameter("username"); 	System.out.println(username); 	return null; }

     

    使用@RequestParam 注解获取GET请求或POST请求提交的参数;

    获取Cookie的值:使用@CookieValue 

    获取PrintWriter

    可以直接在Controller的方法中传入PrintWriter对象,就可以在方法中使用:

    @RequestMapping(value = "login", method = RequestMethod.POST) public String testParam(PrintWriter out, @RequestParam("username") String username) { 	out.println(username); 	return null; }

     

     

    获取表单中提交的值,并封装到POJO中,传入Controller的方法里:

    POJO如下(User.java):

    public class User{ 	private long id; 	private String username; 	private String password;  	…此处省略getter,setter... }

     

     

    通过表单提交,直接可以把表单值封装到User对象中:

    @RequestMapping(value = "login", method = RequestMethod.POST) public String testParam(PrintWriter out, User user) { 	out.println(user.getUsername()); 	return null; }

     

     

    可以把对象,put 入获取的Map对象中,传到对应的视图:

    @RequestMapping(value = "login", method = RequestMethod.POST) public String testParam(User user, Map model) { 	model.put("user",user); 	return "view"; }

     

    在返回的view.jsp中,就可以根据key来获取user的值(通过EL表达式,${user }即可);

    Controller中方法的返回值:

    void:多数用于使用PrintWriter输出响应数据;

    String 类型:返回该String对应的View Name

    任意类型对象:

    返回ModelAndView

    自定义视图(JstlViewExcelView):

    拦截器(Inteceptors):

    public class MyInteceptor implements HandlerInterceptor { 	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o)  		throws Exception { 		return false; 	} 	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object o, ModelAndView mav)  		throws Exception { 	} 	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object o, Exception excptn)  		throws Exception { 	} }

     

    拦截器需要实现HandleInterceptor接口,并实现其三个方法:

    preHandle:拦截器的前端,执行控制器之前所要处理的方法,通常用于权限控制、日志,其中,Object o表示下一个拦截器;

    postHandle:控制器的方法已经执行完毕,转换成视图之前的处理;

    afterCompletion:视图已处理完后执行的方法,通常用于释放资源;

    MVC的配置文件中,配置拦截器与需要拦截的URL

    <mvc:interceptors> 	<mvc:interceptor> 		<mvc:mapping path="/index.htm" /> 		<bean class="com.minx.crm.web.interceptor.MyInterceptor" /> 	</mvc:interceptor> </mvc:interceptors>

     

    国际化:

    MVC配置文件中,配置国际化属性文件:

    <bean id="messageSource" 	class="org.springframework.context.support.ResourceBundleMessageSource" 	p:basename="message"> </bean>

     

    那么,Spring就会在项目中搜索相关的国际化属性文件,如:message.propertiesmessage_zh_CN.properties

    VIEW中,引入Spring标签:<%@taglib uri="http://www.springframework.org/tags" prefix="spring" %>,使用<spring:message code="key" />调用,即可;

    如果一种语言,有多个语言文件,可以更改MVC配置文件为:

    <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"> 	<property name="basenames"> 		<list> 			<value>message01</value> 			<value>message02</value> 			<value>message03</value> 		</list> 	</property> </bean>

    posted @ 2013-11-04 23:23 奋斗成就男人 阅读(276) | 评论 (0)编辑 收藏

    如何连接表更新数据

    sql server中如何连接表更新数据
    假设a,b两表有外键关联,想要从b表中取出相应字段的值更新a表字段,可以有如下几种写法:
    update a set a.name=b.name from a,b where a.id=b.id 
    update a inner join b on a.id=b.id set a.name=b.name where ... 
    update table1 set a.name = b.name from table1 a inner join table2 b on a.id =b


    二:

    表hotel中有id,hotel_city。

        表hotel_room中有id,hotel_id,其中hotel_id与表hotel中的id对应。

        表hotel_room_price中有room_id,price,price_year_month,其中room_id与hotel_room中的id对应。其余各项数据之间没有关联。

        现在要求更新表hotel_room_price中的price字段,符合的条件是room_id对应的hotel_city是744,且price_year_month是'20114'。

        SQL语句:

        update hotel_room_price set price = 0 from hotel_room_price a,hotel_room b,hotel c where a.room_id = b.id and b.hotel_id = c.id and c.hotel_city = 744 and a.price_year_month = '20114'

        重点看红色的部分。from后跟的是需要联立的三个表。用where a.room_id = b.id and b.hotel_id = c.id来将三个表当中需要对应的字段联立起来。and c.hotel_city = 744 and a.price_year_month = '20114'则是最后指定的两个条件。

        运行无错误。

    posted @ 2013-11-01 01:51 奋斗成就男人 阅读(171) | 评论 (0)编辑 收藏

    zencart 后台正常 前台空白的解决方法

    在调试zencart网店时,有时修改了某些文件,网店前台显示不完整了,或者出现了空白页面,可以通过以下方法打开错误提示:

    版本 v1.3.9 的排错方法
    错误记录在 /cache/ 目录下,前台的错误记录文件名为 "myDebug-xxxxxx.log" ,后台的错误记录文件名为 "myDebug-adm-xxxxxxx.log"

    如果需要在浏览器中显示出错误信息(注意,客户也会看到错误信息),执行下面的操作:

    如果是前台错误,打开文件 \includes\extra_configures\enable_error_logging.php
    如果是后台错误,打开文件 \admin\includes\extra_configures\enable_error_logging.php

    查找 @ini_set('display_errors', 0);
    修改为 @ini_set('display_errors', 1);


    版本 v1.3.8 的排错方法
    前台界面排错适用

    打开文件 \includes\application_top.php ,找到
    if (defined('STRICT_ERROR_REPORTING') && STRICT_ERROR_REPORTING == true) {

    在前面增加一行
    define('STRICT_ERROR_REPORTING', true);

    保存后重新刷新网页,就会有错误提示了。

    把上面的语句修改为
    define('STRICT_ERROR_REPORTING', false);
    就能关闭错误提示了。


    后台界面排错适用

    打开文件 \admin\includes\application_top.php,找到
    error_reporting(E_ALL & ~E_NOTICE);
    修改为
    @ini_set('display_errors', '1');
    error_reporting(E_ALL);

    找到错误后,再修改回去关闭错误提示

    posted @ 2013-10-15 01:18 奋斗成就男人 阅读(913) | 评论 (0)编辑 收藏

    本地环境访问zencart,前台正常,后台空白

    前两天在本地搭建一个网站,准备做下数据,安装好以后,发现登陆后台很慢,等了好久出现后台空白,开启错误提示也没用,根本就没错误,当时想,难道我这个站搭建的有问题。所以我又访问了以前搭建的站点,出现同样的错误。

    难道是我本地环境出现问题了?或许是吧,所以一气之下就把本地环境重新搭建了一下,发现还是不行;难道是集成环境版本太低了,我又从官网下载一个新的,最后发现还是不行,不是这个问题。无语了……

    然后我就再网上找啊找,最后根据一个的提示,我找到了一个解决办法,原来是线路的问题。前段时间我一直用的电信线路,最近换成了联通线路,就遇到这 样的问题,可能是最近联通线路有点问题。MD。折腾老子一下午才找到原因,为了避免和我一样的“程序猿”浪费时间,所以我就写下来,希望对你们有用。

    解决办法:

    把admin(网站后台目录)\includes\local\skip_version_check.ini文件里面的version_check=no修改成version_check=off 就可以了。

    因为安装zen-cart的时候,默认会选择那个版本更新选项,当进入后台的时候,一直更新不了,所以会出现那个问题了。

    posted @ 2013-10-15 01:18 奋斗成就男人 阅读(211) | 评论 (0)编辑 收藏

    再续火车头(免费版)采集数据

      自从上一篇zen-cart采集规则和数据库发布模块下载以后。很多人问我为什么他的不能采集,原来发现他们用的几乎都是免费版的,不能直接导入数据库中,可以做成CVS格式的,但是遗憾的是不能下载图片,所以这次我就做个简单的教程,大致说一下。
             quill.com 测试网站我用的是这个
            第一种方式不能直接下载图片,但是可以通过迅雷下载。
            第一种方式的 站点规则csv表
            第二种方式可以直接下载图片,但是批量中的那个图片字段有点乱,可以批量替换。
            第二种方式的站点规则CSV表

            这两种方式下载图片的区别在于如图对比

            第一种方式图1

            第二种方式图2

     

     

    版权申明:原创文章,转载时请务必复制以下链接。

    posted @ 2013-10-15 01:17 奋斗成就男人 阅读(174) | 评论 (0)编辑 收藏

    zen-cart采集细节图

    今天答应两位朋友的要求,说说如何采集细节图!首先说说我是如何学会采集的吧,当时接触火车头采集器的时候,发现这方面的资料很少(针对 zencart的),什么采集规则,数据库发布模块,第一次用这玩意,有太多不明白的地方。我每天就不断查资料,不断测试,还好我是计算机专业的,学过一 些编程知识,将近花了一个星期才学会采集,当你看到你这篇文章时,希望你们也好好不断测试,不断分析问题,只有这样,以后遇到跟复杂的问题,才能会解决, 或许有些问题,只有少量的人遇到,只能靠自己了。好像很多人认为这个简单,也没有这方面的教程,可是对于我们这样的菜鸟来说,入门是必要的。也有一些收费 的,给别人采集一个站,做个批量表收多少钱等等。互联网提倡的就是资源共享,授人之鱼不如授人之渔。其实我对火车头采集器更多的功能没有深入了解,我只是 把我工作中学会的东西分享出来,再某些人看来,可能没有什么意义。我不会给别人采集一个网站收多少钱,说实话我现在还没那个能力,也没有太多的时间。废话 不多说了,开始今天的教程。

    前面我的就不再介绍了,首先我找了一个有细节图的网站,例如www.jerseyscool.com。我们只看第二步:采集内容规则。我们添加一个标签名,就叫商品细节图,我的规则如下图(其实与商品图像差不多了)

    然后要注意左下角的标签循环匹配,选择“添加为新记录”。看我采集的效果,只是我的网速慢,还没下载完 ,看到那个第几条记录没,就说明我们规则写对了,可以进行采集了。

    最后一步要注意,搞zencart应该都知道,细节图是不写入数据库的,是根据图片名称匹配的,第三步设置如下图,不再在写入数据了,放到一个文件夹就行了。

    最后需要说明的,我们做这一步是纯粹为了得到细节图。所以我要首先按照上一次的教程,采集完数据,然后再采集细节图。采集细节图我们可以一下子采集完,具体怎么采集明天到公司再补充(家里的网络实在太慢了,没法搞了)。这一次我就不把采集规则发上来了,其实很简单。

    最近有人问我采集完了才做成批量表,其实很简单了,你在你的网站上安装一个批量表不就行了,可以把采集的数据放到另一个网站上,这一步我就操作了,不明白的可以给我留言或者加我q,最好是留言,我会认真回答你们的!

    你们的鼓励是我最大的动力,我也是菜鸟,我们一起共同进步,最近一直在学习magento,下一步可能要针对magento进行采集了,呵呵,欢迎朋友们批评和指正!

    posted @ 2013-10-15 01:17 奋斗成就男人 阅读(317) | 评论 (0)编辑 收藏

    zen-cart采集规则和数据库发布模块

    首先安装zen-cart,我用的是zen-cart1.9中文版的,安装步骤我就不写了,这个很简单了。安装以后根据你要采集的网站建立对应的目录就OK了。例如我要测试采集的网站www.yankeesjerseystore.com这 是我随便找的网站,我首先建立大分类Shop By Players 然后建立相应的小分类Alex Rodriguez Jersey(多页面,等会解释这个)和Folder Alfonso Soriano Jersey(单页面)。我只是测试采集就先建一个大分类两个小分类。如下图
    大分类
    小分类
           然后开始写采集规则了,每个网站的采集规则是不一样的,针对每个网站写不同的规则,不过zen-cart网站的规则差不多了,写多了就会发现很简单。
           第一步写采集网址规则,首先添加采集地址(我添加的是http://www.yankeesjerseystore.com/new-york- yankees-jersey-alex-rodriguez-jersey-c-6_16.html?page=(*)&sort=20a)如 下图
    然后为了采集自己想要的页面,就必须过滤一些网址了,就要写一些限制性的标志了,必须包含,不得包含,页面内选定区域采集网址从xx到xx等请看下图我是如何写的,这个不是唯一性的,每个人写的可能不一样。
    这一步算是完成了。
           第二步写采集内容规则,我把每个标签名对应规则放出来,如下图
    商品名称
    商品型号
    商品价格
    商品特价
    商品图像,注意哪个文件保存格式,我选择了[原文件名],根据自己的需要也可以改
    商品描述,注意用哪个html标签排除,我用了去首尾空白符
    OK,规则写完了,可以找个内容页测试一下,如下图
    看,已经测试成功了,注意图片一定要显示完整。
           第三步发布内容设置,有几种发布方式,我选择方式三,导入到自定义数据库,如下图
    然后点击数据库发布全局配置,选择编辑你要编辑数据库发布配置,如下图
    点击编辑以后,出现下图
    然后编辑数据库发布模块,如下图
    看到你刚才写的标签名没,注意这个地方的标签与刚才写的标签名要对应着,,不然就会失败的,看到最后那个“2”没,就是刚才我们建立栏目时的分 类ID,每采集一个栏目的时候变换不同的ID,上面我已经写了,不需要改动了,最后我会把发布模块分享给朋友们。修改完以后,要点击那个“修改配置”这样 才能保存着。
           第四步文件保存及部分高级设置,如下图,基本上不用改变。
           最后一步,点击更新,然后就可以点击开始采集了,采集效果如下图
          OK,采集成功了,可以发布到数据库了,然后我到网站后台看一下,是不是已经导入到数据库了,呵呵!如下图,成功了
    后台效果
    前台效果
           最后要说明一点,采集单网址也是一样,注意选择如下图
           好了,教程写完了,挺累的,写了两个小时,不知道你们看明白没,反正我是很明白(呵呵),根据不同的网站灵活运用就OK了,稍后我把采集规则放出来,供朋友下载,有不明白的地方可以给我留言或者加我qq          zen-cart.rar(点击下载哦)

    posted @ 2013-10-15 01:16 奋斗成就男人 阅读(206) | 评论 (0)编辑 收藏

    PreparedStatement 使用like 模糊查询

    PreparedStatement 使用like

    在使用PreparedStatement进行模糊查询的时候废了一番周折,以前一直都没有注意这个问题。一般情况下我们进行精确查询,sql语句类似:select * from table where name =?,然后调用 PreparedStatement的setString等方法给?指定值。那么模糊查询的时候应该怎么写呢?我首先尝试了:select * from customer where name like ‘%?%’。
    此时程序报错,因为?被包含在了单引号中,PreparedStatement并不视它为一个参数。后来上网查了相关的一些资料,发现可以这样写select * from table where name like ?;但是在指定参数的时候把?指定为”%”+name+”%”,name是指定的查询条件。这样就OK了。
    一般情况下,我总是潜意识的认定了?就是取代所指定的参数,但是实际上我们可以对指定的参数进行了一定的包装之后再传给?,比如这里我们在参数的前后都加了一个%,然后再传给?   

    String expr = "select * from  table where url like ?";
       pstmt = con.prepareStatement(expr);
       String a="a";
       pstmt.setString(1, "%"+a+"%");//自动添加单引号 (包装后的参数)
      pstmt.execute();
       System.out.println(pstmt.toString());//打印sql
       //会默认生成sql: select * from  table where url like '%http%' 

    posted @ 2013-10-08 10:33 奋斗成就男人 阅读(210) | 评论 (0)编辑 收藏

    $_GET,$_post与$_REQUEST

    PHP $_GET

    $_GET 变量是一个数组,内容是由 HTTP GET 方法发送的变量名称和值。

    PHP $_POST

    $_POST 变量用于收集来自 method="post" 的表单中的值。

    $_POST 变量

    $_POST 变量是一个数组,内容是由 HTTP POST 方法发送的变量名称和值。

    $_POST 变量用于收集来自 method="post" 的表单中的值。从带有 POST 方法的表单发送的信息,对任何人都是不可见的(会显示在浏览器的地址栏),并且对发送信息的量也没有限制。

    例子

    <form action="welcome.php" method="post"> Enter your name: <input type="text" name="name" /> Enter your age: <input type="text" name="age" /> <input type="submit" /> </form> 

    当用户点击提交按钮,URL 不会含有任何表单数据,看上去类似这样:

    http://www.w3school.com.cn/welcome.php 

    "welcome.php" 文件现在可以通过 $_POST 变量来获取表单数据了(请注意,表单域的名称会自动成为 $_POST 数组中的 ID 键):

    Welcome <?php echo $_POST["name"]; ?>.<br /> You are <?php echo $_POST["age"]; ?> years old! 

    为什么使用 $_POST?

    • 通过 HTTP POST 发送的变量不会显示在 URL 中。
    • 变量没有长度限制。

    不过,由于变量不显示在 URL 中,所有无法把页面加入书签。

    $_REQUEST 变量

    PHP 的 $_REQUEST 变量包含了 $_GET, $_POST 以及 $_COOKIE 的内容。

    PHP 的 $_REQUEST 变量可用来取得通过 GET 和 POST 方法发送的表单数据的结果。

    例子

    Welcome <?php echo $_REQUEST["name"]; ?>.<br /> You are <?php echo $_REQUEST["age"]; ?> years old! 

    ATTENTION:慎用$_REQUEST 
    如果get的一个变令名称和post的一个变量名称相同,则POST的值会覆盖GET的变量值 
    以为REQYEST先获取了get的值,然后获取了post的值,post的值会覆盖get值 
    我们可以来看php.ini中的配置 
    ; This directive describes the order in which PHP registers GET, POST, Cookie,
    ; Environment and Built-in variables (G, P, C, E & S respectively, often
    ; referred to as EGPCS or GPC). Registration is done from left to right, newer
    ; values override older values.
    variables_order = "EGPCS"

    这个EGPCS就是说明用$_REQUEST数组获取内容的优先级,其字母的含义分别代表为:E代表$_ENV,G代表$_GET,P代表$_POST,C代表$_COOKIE,S代表$_SESSION。后面出现的数据会覆盖前面写入的数据,其默认的数据写入方式就是EGPCS,所以POST包含的数据将覆盖GET中使用相同关键字的数据。
    通过这个我们也可以看出PHP获取参数的步骤 
    环境变量=》GET=》POST=》COOKIE=>SESSION 

    posted @ 2013-09-06 10:17 奋斗成就男人 阅读(195) | 评论 (0)编辑 收藏

    PHP中GET POST REQUEST区别

    PHP中有$_REQUEST$_POST$_GET用于接受表单数据。

    一、$_REQUEST$_POST$_GET的区别和特点

    $_REQUEST[]具用$_POST[] $_GET[]的功能,但是$_REQUEST[]比较慢。通过POSTGET方法提交的所有数据都可以通过$_REQUEST数组获得。

    二、$_POST$_GET的区别和特点

    1.         GET是从服务器上获取数据,POST是向服务器传送数据。

    2.         GET是把参数数据队列加到提交表单的ACTION属性所指的URL中,值和表单内各个字段一一对应,在URL中可以看到。POST是通过HTTP POST机制,将表单内各个字段与其内容放置在HTML HEADER内一起传送到ACTION属性所指的URL地址。用户看不到这个过程。

    3.         对于GET方式提交表单数据,服务器端用$_GET[‘name’]获取变量的值,对于POST方式提交表单数据,服务器端用$_POST[‘name’]获取提交的数据,当然,两者都可以通过$_REQUEST[‘name’]获得表单数据。对于REQUEST方式提交表单数据,服务器端用$_REQUEST[‘name’]获取变量的值,但这种方式很少用。

    4.         GET传送的数据量较小,不能大于2KBPOST传送的数据量较大,一般被默认为不受限制。但理论上,一般认为不能超过100KB

    5.         GET安全性非常低,POST安全性较高。

    6.         GET表单值可以通过_GET获取;但通过actionurl设置的参数总是获取不到的,<form method="get" action="a.asp?b=b"><form method="get"action="a.asp">是一样的,也就是说,在这种情况下,GET方式会忽略action页面后边带的参数列表。POST表单值可以通过_POST获取;但通过actionurl参数设置的参数则可以不能通过_POST获取到。action=test.php?id=1这种就是GET方式传值,可以用$_REQUEST$_GET接受传值,但不能用POST方式获取到值,即使表单是POST方式提交。所在,在提交表单时,如果action中同时有参数,最好只能通过POST表单方式,对于表单内数据,直接通过POST获取,对于action中参数,童工GET获取。

    在做数据查询时,建议用GET方式,而在做数据添加、修改或删除时,建议用POST方式。

    request是先读取 get再读post 的, 同时存在, 即覆盖掉前面的变量。

    经典实例:

    <?php
    echo "get\n";
    print_r($_GET);
    echo "post\n";
    print_r($_POST);
    echo "request\n";
    print_r($_REQUEST);
    ?>
    <form method=post action='?a=1&b=2'>
    <input type=text name=a value='a'>
    <input type=text name=b value='b'>
    <input type=submit value=test>
    </form>

     

    输出结果:

    get
    Array
    (
      [a] => 1
      [b] => 2
    )
    post

    Array
    (
      [a] => a
      [b] => b
    )
    request

    Array
    (
      [a] => a
      [b] => b
    )

     

    其实,在php配置文件php.ini中有一个设置项:variables_order = "GPCS" GPCS分别是GETPOSTCookieServer的首字母缩写,variables_order = "GPCS"含义是php文件中变量的解析顺序是GETPOSTCookieServer

    posted @ 2013-09-06 10:15 奋斗成就男人 阅读(228) | 评论 (0)编辑 收藏

    POS响应代码解析

    代码 POS显示的内容原因/操作员应采取的措施
    00   交易成功       承兑或交易成功
    01   交易失败       请联系发卡行 查发卡行
    02   交易失败       请联系发卡行向发卡行查询
    03   商户未登记     联系银行卡服务中心处理
    04   没收卡         请联系收单行 操作员没收卡
    05   交易失败       请联系发卡行 发卡不予承兑,与发银行联系查询
    06   交易失败       请联系发卡行发卡行故障
    07   没收卡         请联系收单行 特殊条件下没收卡
    09   交易失败       请重试 重做该交易
    12   交易失败       请重试 发卡行不支持的交易
    13   交易金额超限   请重试交易金额无效,采用小金额交易或与发卡行联系
    14   无效卡号       请联系发卡行无效卡号,与银行卡服务中心或发卡行联系
    15   此卡不能受理   请与银行卡服务中心联系处理
    19   交易失败       请联系发卡行 刷卡读取数据有误,重新刷卡
    20   交易失败       请联系发卡行 与银行卡服务中心或发卡行联系
    21   交易失败       请联系发卡行 与银行卡服务中心或发卡行联系
    22   操作有误       请重试 POS状态与中心不符,重新签到
    23   交易失败       请联系发卡行 不可接受的交易费
    25   交易失败     请联系发卡行发卡行未能找到有关记录,核对有关资料重做该交易或与发卡行联系
    30   交易失败       请重试 检查卡磁条是否完好或反方向刷卡
    31   此卡不能受理   此发卡方未与中心开通业务
    33   过期卡         请联系发卡行 过期的卡或与发卡行联系
    34   没收卡         请联系收单行 有作弊嫌疑的卡,操作员可以没收
    35   没收卡         请联系收单行 有作弊嫌疑的卡,操作员可以没收
    36   此卡有误       请换卡重试 有作弊嫌疑的卡,操作员可以没收
    37   没收卡         请联系收单行 有作弊嫌疑的卡,操作员可以没收
    38   密码错误次数超限   密码输错的次数超限
    39   交易失败       请联系发卡行 可能刷卡操作有误
    40   交易失败       请联系发卡行 发卡行不支持的交易类型
    41   没收卡         请联系收单行 挂失的卡,与发卡行联系处理
    42   交易失败       请联系发卡方 发卡行找不到此帐户
    43   没收卡         请联系收单行 被窃卡, 操作员可以没收
    44   交易失败       请联系发卡行 可能刷卡操作有误
    51   余额不足       请查询 帐户内余额不足
    52   交易失败       请联系发卡行 无此支票账户
    53   交易失败       请联系发卡行 无此储蓄卡账户
    54   过期卡         请联系发卡行 过期的卡
    55   密码错         请重试 密码输错,可重新输入
    56   交易失败       请联系发卡行 发卡行找不到此帐户,与发卡行联系
    57   交易失败       请联系发卡行不允许持卡人进行的交易,与发卡行联系
    58   终端无效       请联系收单行或银联重新签到再试或与银行卡服务中心联系
    59   交易失败       请联系发卡行 与发卡行联系
    60   交易失败       请联系发卡行 与发卡行联系
    61   金额太大       超出去款金额限制
    62   交易失败       请联系发卡行 受限制的卡
    63   交易失败       请联系发卡行 违反安全保密规定
    64   交易失败       请联系发卡行原始金额不正确,核对原始资料或与发卡行联系
    65   超出取款次数限制   超出取款次数限制
    66   交易失败       请联系收单行或银联 与发卡放联系处理
    67   没收卡         没收卡
    68   交易超时       请重试发卡行规定时间内没有应答,与银行卡服务中心或发卡行联系
    75   密码错误次数超限允许的输入PIN次数超限   该卡要重置密码方能使用
    77   请向网络中心签到   重做签到
    79   POS终端重传脱机数据 POS终端上传的脱机数据对帐不平
    90   交易失败       请稍后重试日期切换正在处理,与银行卡服务中心或发卡行联系
    91   交易失败       请稍后重试 电话查询发卡方或银联,可重作
    92   交易失败       请稍后重试银行通讯故障,电话查询发卡方或网络中心
    93   交易失败       请联系发卡行 交易违法、不能完成。重新签到后再试
    94   交易失败       请稍后重试重新签到后再交易或与银行卡服务中心联系
    95   交易失败       请稍后重试发卡行调节控制错,与发卡行联系
    96   交易失败       请稍后重试 与发卡行或银行卡服务中心联系
    97   终端未登记     请联系收单行或银联与银行卡服务中心联系
    98   交易超时       请重试银联收不到发卡行应答,与银行卡服务中心或发
    卡行联系
    99   校验错         请重新签到 重新签到再作交易
    A0   校验错         请重新签到 重新签到作交易

    posted @ 2013-08-09 21:47 奋斗成就男人 阅读(496) | 评论 (0)编辑 收藏

    POS机的报文格式

         摘要: POS机的主要功能点: 1. 签到 2. 输入密码 3. 消费 4. 余额查询 5. 撤销 6. 系统设置 我公司建议: 1:为统一格式及今后扩展,近可能按照银联标准开发: 2:增加“批结算”功能; 3:建议把卡号信息写在磁条卡“2磁道”; 4:报文格式: TPDU(10字节) + 报文头(12字节)+ 消息类型(4字节)+ 位图(8字节)+位图保护...  阅读全文

    posted @ 2013-08-09 21:45 奋斗成就男人 阅读(1710) | 评论 (0)编辑 收藏

    MyEclipse快捷键大全

    -------------------------------------
    MyEclipse 快捷键1(CTRL)
    -------------------------------------
    Ctrl+1 快速修复
    Ctrl+D: 删除当前行 
    Ctrl+Q  定位到最后编辑的地方 
    Ctrl+L  定位在某行  
    Ctrl+O  快速显示 OutLine 
    Ctrl+T  快速显示当前类的继承结构 
    Ctrl+W  关闭当前Editer 
    Ctrl+K  快速定位到下一个 
    Ctrl+E 快速显示当前Editer的下拉列表
    Ctrl+J  正向增量查找(按下Ctrl+J后,你所输入的每个字母编辑器都提供快速匹配定位到某个单词,如果没有,则在stutes line中显示没有找到了,)    
    Ctrl+Z 返回到修改前的状态 
    Ctrl+Y 与上面的操作相反
    Ctrl+/  注释当前行,再按则取消注释 
    Ctrl+D删除当前行。
    Ctrl+Q跳到最后一次的编辑处
    Ctrl+M切换窗口的大小 
    Ctrl+I格式化激活的元素Format Active Elements。
    Ctrl+F6切换到下一个Editor
    Ctrl+F7切换到下一个Perspective
    Ctrl+F8切换到下一个View
    ------------------------------------------
    MyEclipse 快捷键2(CTRL+SHIFT)
    ------------------------------------------
    Ctrl+Shift+E 显示管理当前打开的所有的View的管理器(可以选择关闭,激活等操作) 
    Ctrl+Shift+/ 自动注释代码 
    Ctrl+Shift+\自动取消已经注释的代码 
    Ctrl+Shift+O 自动引导类包 
    Ctrl+Shift+J 反向增量查找(和上条相同,只不过是从后往前查) 
    Ctrl+Shift+F4 关闭所有打开的Editer 
    Ctrl+Shift+X  把当前选中的文本全部变为小写 
    Ctrl+Shift+Y  把当前选中的文本全部变为小写 
    Ctrl+Shift+F  格式化当前代码
    Ctrl+Shift+M(先把光标放在需导入包的类名上) 作用是加Import语句 
    Ctrl+Shift+P 定位到对于的匹配符(譬如{}) (从前面定位后面时,光标要在匹配符里面,后面到前面,则反之) 
    Ctrl+Shift+F格式化文件Format Document。
    Ctrl+Shift+O作用是缺少的Import语句被加入,多余的Import语句被删除。 
    Ctrl+Shift+S保存所有未保存的文件。
    Ctrl+Shift+/ 在代码窗口中是这种/*~*/注释,在JSP文件窗口中是 <!--~-->。 
    Shift+Ctrl+Enter 在当前行插入空行(原理同上条)
    -----------------------------------------
    MyEclipse 快捷键3(ALT)
    -----------------------------------------
    Alt+/ 代码助手完成一些代码的插入 ,自动显示提示信息
    Alt+↓  当前行和下面一行交互位置(特别实用,可以省去先剪切,再粘贴了) 
    Alt+↑  当前行和上面一行交互位置(同上) 
    Alt+←  前一个编辑的页面 
    Alt+→  下一个编辑的页面(当然是针对上面那条来说了) 
    Alt+Enter 显示当前选择资源(工程,or 文件 or文件)的属性

    MyEclipse 快捷键4(ALT+CTRL)

    Alt+CTRL+↓ 复制当前行到下一行(复制增加) 
    Alt+CTRL+↑ 复制当前行到上一行(复制增加)
    -------------------------------------------
    MyEclipse 快捷键5(ALT+SHIFT)
    -------------------------------------------
    Alt+Shift+R 重命名 
    Alt+Shift+M 抽取方法
    Alt+Shift+C 修改函数结构(比较实用,有N个函数调用了这个方法,修改一次搞定) 
    Alt+Shift+L 抽取本地变量
    Alt+Shift+F 把Class中的local变量变为field变量
    Alt+Shift+I 合并变量
    Alt+Shift+V 移动函数和变量
    Alt+Shift+Z 重构的后悔药(Undo) Shift+Enter 在当前行的下一行插入空行(这时鼠标可以在当前行的任一位置,不一定是最后) 
    Alt+Shift+O(或点击工具栏中的Toggle Mark Occurrences按钮) 当点击某个标记时可使本页面中其他地方的此标记黄色凸显,并且窗口的右边框会出现白色的方块,点击此方块会跳到此标记处。 
    下面的快捷键是重构里面常用的,本人就自己喜欢且常用的整理一下(注:一般重构的快捷键都是Alt+Shift开头的了)

    --------------------------------------------
    MyEclipse 快捷键(6) 
    --------------------------------------------
    F2当鼠标放在一个标记处出现Tooltip时候按F2则把鼠标移开时Tooltip还会显示即Show Tooltip Description。 
    F3跳到声明或定义的地方。 
    F5单步调试进入函数内部。 
    F6单步调试不进入函数内部,如果装了金山词霸2006则要把“取词开关”的快捷键改成其他的。 
    F7由函数内部返回到调用处。 
    F8一直执行到下一个断点。

    posted @ 2013-08-09 01:56 奋斗成就男人 阅读(178) | 评论 (0)编辑 收藏

    Java对象的持久化

    Java对象的持久化主要使用ObjectInputStream与ObjectOutputStream类 来实现!


    public class Student implements Serializable {
     
            String name;
            int id ;
         int age;
            String department;
      public Student(String name, int id, int age, String department) {
       this.age = age;
       this.department = department;
       this.id = id;
       this.name = name;
      }

    public static void saveObjects(Student student, String fileName) { 
    FileOutputStream os = new FileOutputStream("fileName.dat"); 
    ObjectOutputStream oos = new ObjectOutputStream(os); 
    oos.writeObject(student); 
    }

    public static Student readObjects(String fileName) { 
    Student student; 
    Object obj; 
    try
    FileInputStream is = new FileInputStream("fileName.dat"); 
    ObjectInputStream ois = new ObjectInputStream(is); 
    obj = ois.readObject(); 
    }catch (Exception e) { 
    e.printStackTrace(); 

    if(obj instanceof Student){ 
    Student stu= (Student)obj; 
    return stu; 

    return null
    }

    posted @ 2013-08-09 01:30 奋斗成就男人 阅读(245) | 评论 (0)编辑 收藏

    JAVA读取Properties配置文件


    JAVA获取文件绝对路径Thread.currentThread().getContextClassLoader().getResource("abc.properties");                                   


     配置文件:XXX.properties 常用操作


     1:加载properties配置文件
      /**
         * 根据key从Properties对象中得到相应的值
         * 
    @param key
         * 
    @return 对应的值
         
    */
        public static String getValue(String key) {
            if (p !=  null) {
                return p.getProperty(key);
            }
            String property = null
            InputStream in = null;
            
            try {
                System.out.println("gleepay.properties is path : " + gleepayURL.getFile());
                File file = new File(gleepayURL.getFile());
                in = new FileInputStream(file);
                p = new Properties();
                p.load(in);
                property = p.getProperty(key);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }  finally {
                if (in != null) {
                    try {
                            in.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            return property;
        }

    2:写入propertis配置信息
    /**
         * 写入properties信息
         * 
    @param parameterKey
         * 
    @param parameterValue
         * 
         * 
    @return
         
    */
        public static void writeProperties_MACkey(String parameterKey, String parameterValue) {
            String filePath = MACkeyURL.getFile();
            Properties prop = new Properties();
            try {
                InputStream fis = new FileInputStream(filePath);
                // 从输入流中读取属性列表(键和元素对)
                prop.load(fis);
                // 调用 Hashtable 的方法 put。使用 getProperty 方法提供并行性。
                
    // 强制要求为属性的键和值使用字符串。返回值是 Hashtable 调用 put 的结果。
                OutputStream fos = new FileOutputStream(filePath);
                prop.setProperty(parameterKey, parameterValue);
                // 以适合使用 load 方法加载到 Properties 表中的格式,
                
    // 将此 Properties 表中的属性列表(键和元素对)写入输出流
                prop.store(fos, "Update '" + parameterKey + "' value");
            } catch (IOException e) {
                System.err.println("Visit " + filePath + " for updating "
                        + parameterKey + " value error");
                e.printStackTrace();
            }
        }
        

    3:根据key读取propertis文件value值
        /**
         * 根据key读取value
         * 
    @param filePath
         * 
    @param key
         * 
    @return 对应的值
         
    */
        public static String readValueByKey(String filePath, String key) {
            System.out.println("properties file is path : " + filePath);
            Properties props = new Properties();
            try {
                InputStream in = new BufferedInputStream(new FileInputStream(filePath));
                props.load(in);
                String value = props.getProperty(key);
                System.out.println(" --> " + key + "=" + value);
                return value;
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
        
    4:读取properties配置文件所有信息
        /**
         *  读取properties的全部信息
         * 
    @param filePath
         * 
    @return
         
    */
        @SuppressWarnings("unchecked")
        public static void readPropertiesAll(String filePath) {
            System.out.println("properties file is path : " + filePath);
            Properties props = new Properties();
            try {
                InputStream in = new BufferedInputStream(new FileInputStream(filePath));
                props.load(in);
                Enumeration en = props.propertyNames();
                while (en.hasMoreElements()) {
                    String key = (String) en.nextElement();
                    String Property = props.getProperty(key);
                    System.out.println(" --> " + key + "=" + Property);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    posted @ 2013-08-08 23:43 奋斗成就男人 阅读(155) | 评论 (0)编辑 收藏

    JAVA 对象拷贝

         摘要: JAVA 对象拷贝 为什么需要有对象拷贝? 对象拷贝相对的自然是引用拷贝。java初学者经常会问,我这个方法要改变一个对象的属性,可以把参数传进去了,为什么没有改变了? ——基本数据类型传值,而对象传引用或引用的拷贝。 而有时候我们要获取到一个当前状态的对象复制品,他们是两个独立对象。不再是引用或者引用拷贝(实质都是指向对象本身)。就是说a是b的拷贝,b发生变化的时候,不要...  阅读全文

    posted @ 2013-08-08 23:26 奋斗成就男人 阅读(159) | 评论 (0)编辑 收藏

    用JAVA轻松操作properties文件

    import java.io.BufferedInputStream;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.util.Enumeration;
    import java.util.Properties;
    public class TestMain {
     
     //根据key读取value
     public static String readValue(String filePath,String key) {
      Properties props = new Properties();
            try {
             InputStream in = new BufferedInputStream (new FileInputStream(filePath));
             props.load(in);
             String value = props.getProperty (key);
                System.out.println(key+value);
                return value;
            } catch (Exception e) {
             e.printStackTrace();
             return null;
            }
     }
     
     //读取properties的全部信息
        public static void readProperties(String filePath) {
         Properties props = new Properties();
            try {
             InputStream in = new BufferedInputStream (new FileInputStream(filePath));
             props.load(in);
                Enumeration en = props.propertyNames();
                 while (en.hasMoreElements()) {
                  String key = (String) en.nextElement();
                        String Property = props.getProperty (key);
                        System.out.println(key+Property);
                    }
            } catch (Exception e) {
             e.printStackTrace();
            }
        }

        //写入properties信息
        public static void writeProperties(String filePath,String parameterName,String parameterValue) {
         Properties prop = new Properties();
         try {
          InputStream fis = new FileInputStream(filePath);
                //从输入流中读取属性列表(键和元素对)
                prop.load(fis);
                //调用 Hashtable 的方法 put。使用 getProperty 方法提供并行性。
                
    //强制要求为属性的键和值使用字符串。返回值是 Hashtable 调用 put 的结果。
                OutputStream fos = new FileOutputStream(filePath);
                prop.setProperty(parameterName, parameterValue);
                //以适合使用 load 方法加载到 Properties 表中的格式,
                
    //将此 Properties 表中的属性列表(键和元素对)写入输出流
                prop.store(fos, "Update '" + parameterName + "' value");
            } catch (IOException e) {
             System.err.println("Visit "+filePath+" for updating "+parameterName+" value error");
            }
        }
        public static void main(String[] args) {
         readValue("info.properties","url");
            writeProperties("info.properties","age","21");
            readProperties("info.properties" );
            System.out.println("OK");
        }
    }

    posted @ 2013-08-08 22:12 奋斗成就男人 阅读(161) | 评论 (0)编辑 收藏

    Scanner----java控制台和文件读取的利器

    今天介绍的Scanner这个类是java 5新增加的类,不仅使用方便,功能更是强大。先来看一个简单的例子:
    import java.util.*;
    public class ScannerTest {
     
       public static void main(String[] args){
            Scanner scanner=new Scanner(System.in);
            double a=scanner.nextDouble();
            System.out.println(a);
        }
    }
    运行
    输入 一个任意数然后输出这个数
     
    注意粗体字的地方,这一行就实现了从控制台输入数字的功能,如果要输入字符串
    可以用
    String a=scanner.next();//注意不是nextString()
     
    Scanner还可以直接扫描文件。比如(有点长,耐心一点):
    import java.util.*;
    import java.io.*;
    public class ScannerTest {
        public static void main(String[] args) throws IOException{//这里涉及到文件io操作
            double sum=0.0;
            int count=0;
            FileWriter fout=new FileWriter("text.txt");
            fout.write("2 2.2 3 3.3 4 4.5 done");//往文件里写入这一字符串
            fout.close();
            FileReader fin=new FileReader("text.txt");
            Scanner scanner=new Scanner(fin);//注意这里的参数是FileReader类型的fin
            while(scanner.hasNext()){//如果有内容
                if(scanner.hasNextDouble()){//如果是数字
                    sum=sum+scanner.nextDouble();
                    count++;
                }else{
                    String str=scanner.next();
                    if(str.equals("done")){
                        break;  
                    }else{
                        System.out.println("文件格式错误!");
                        return;
                    }
                }
            }
            fin.close();
            System.out.println("文件中数据的平均数是:"+sum/count);
        }
    }
    结果输出文件中数据的平均数是:3.1666666666666665
    这段程序的功能是将"2 2.2 3 3.3 4 4.5 done"写入文件scanner读取文件中的数直到done结束。并求出数字的平均值,比较有意思的是scanner会自动一空格作为分割符区分不同数字。当然也可以通过scanner.useDelimiter(Pattern pattern)来设置不同的分割符,比如 scanner.useDelimiter(",*");

    posted @ 2013-08-08 22:11 奋斗成就男人 阅读(178) | 评论 (0)编辑 收藏

    字节流与字符流转换

         摘要: 字节流与字符流之间的区别却可以联系起来,这就是表中的两个类InputStreamReader和OutputStreamWriter。InputStreamReader负责把字节输入流转换为字符输入流,OutputStreamWriter负责把输出字节流转换为输出字符流。下面来看看如何进行转换。1.字节输入流转换为字符输入流InputStreamReader是字节流通向字符流的桥梁,它使用指定的ch...  阅读全文

    posted @ 2013-08-08 22:08 奋斗成就男人 阅读(5218) | 评论 (0)编辑 收藏

    面理解Java中的String数据类型

    1.首先String不属于8种基本数据类型,String是一个对象。

      因为对象的默认值是null,所以String的默认值也是null;但它又是一种特殊的对象,有其它对象没有的一些特性。

      2. new String()和new String(“”)都是申明一个新的空字符串,是空串不是null;

      3. String str=”kvill”;
    String str=new String (“kvill”);的区别:

      在这里,我们不谈堆,也不谈栈,只先简单引入常量池这个简单的概念。

      常量池(constant pool)指的是在编译期被确定,并被保存在已编译的.class文件中的一些数据。它包括了关于类、方法、接口等中的常量,也包括字符串常量。

      看例1:

    String s0=”kvill”;
    String s1=”kvill”;
    String s2=”kv” + “ill”;
    System.out.println( s0==s1 );
    System.out.println( s0==s2 );
      结果为:

    true
    true
      首先,我们要知道Java会确保一个字符串常量只有一个拷贝。

      因为例子中的s0和s1中的”kvill”都是字符串常量,它们在编译期就被确定了,所以s0==s1为true;而”kv”和”ill”也都是字符串常量,当一个字符串由多个字符串常量连接而成时,它自己肯定也是字符串常量,所以s2也同样在编译期就被解析为一个字符串常量,所以s2也是常量池中”kvill”的一个引用。

      所以我们得出s0==s1==s2;

      用new String() 创建的字符串不是常量,不能在编译期就确定,所以new String() 创建的字符串不放入常量池中,它们有自己的地址空间。

      看例2:

    String s0=”kvill”;
    String s1=new String(”kvill”);
    String s2=”kv” + new String(“ill”);
    System.out.println( s0==s1 );
    System.out.println( s0==s2 );
    System.out.println( s1==s2 );
      结果为:

    false
    false
    false
      例2中s0还是常量池中”kvill”的应用,s1因为无法在编译期确定,所以是运行时创建的新对象”kvill”的引用,s2因为有后半部分new String(“ill”)所以也无法在编译期确定,所以也是一个新创建对象”kvill”的应用;明白了这些也就知道为何得出此结果了。

      4. String.intern():

      再补充介绍一点:存在于.class文件中的常量池,在运行期被JVM装载,并且可以扩充。String的intern()方法就是扩充常量池的一个方法;当一个String实例str调用intern()方法时,Java查找常量池中是否有相同Unicode的字符串常量,如果有,则返回其的引用,如果没有,则在常量池中增加一个Unicode等于str的字符串并返回它的引用;看例3就清楚了

      例3:

    String s0= “kvill”;
    String s1=new String(”kvill”);
    String s2=new String(“kvill”);
    System.out.println( s0==s1 );
    System.out.println( “**********” );
    s1.intern();
    s2=s2.intern(); //把常量池中“kvill”的引用赋给s2
    System.out.println( s0==s1);
    System.out.println( s0==s1.intern() );
    System.out.println( s0==s2 );
      结果为:

    false
    **********
    false //虽然执行了s1.intern(),但它的返回值没有赋给s1
    true //说明s1.intern()返回的是常量池中”kvill”的引用
    true
      最后我再破除一个错误的理解:

      有人说,“使用String.intern()方法则可以将一个String类的保存到一个全局String表中,如果具有相同值的Unicode字符串已经在这个表中,那么该方法返回表中已有字符串的地址,如果在表中没有相同值的字符串,则将自己的地址注册到表中“如果我把他说的这个全局的String表理解为常量池的话,他的最后一句话,“如果在表中没有相同值的字符串,则将自己的地址注册到表中”是错的:

      看例4:

    String s1=new String("kvill");
    String s2=s1.intern();
    System.out.println( s1==s1.intern() );
    System.out.println( s1+" "+s2 );
    System.out.println( s2==s1.intern() );
      结果:

    false
    kvill kvill
    true
      在这个类中我们没有声名一个”kvill”常量,所以常量池中一开始是没有”kvill”的,当我们调用s1.intern()后就在常量池中新添加了一个”kvill”常量,原来的不在常量池中的”kvill”仍然存在,也就不是“将自己的地址注册到常量池中”了。

      s1==s1.intern()为false说明原来的“kvill”仍然存在;

      s2现在为常量池中“kvill”的地址,所以有s2==s1.intern()为true。

      5. 关于equals()和==:

      这个对于String简单来说就是比较两字符串的Unicode序列是否相当,如果相等返回true;而==是比较两字符串的地址是否相同,也就是是否是同一个字符串的引用。

      6. 关于String是不可变的

      这一说又要说很多,大家只要知道String的实例一旦生成就不会再改变了,比如说:String str=”kv”+”ill”+” “+”ans”;
    就是有4个字符串常量,首先”kv”和”ill”生成了”kvill”存在内存中,然后”kvill”又和” “ 生成 ”kvill “存在内存中,最后又和生成了”kvill ans”;并把这个字符串的地址赋给了str,就是因为String的“不可变”产生了很多临时变量,这也就是为什么建议用StringBuffer的原因了,因为StringBuffer是可改变的.

    posted @ 2013-08-08 21:57 奋斗成就男人 阅读(126) | 评论 (0)编辑 收藏

    java中的参数传递

    这到底是怎样一个问题呢?还是用例子说明吧:
    public class Parameter{
        static void aMethod(){
            int a=1;                         //定义一个int a
            change(a);
            System.out.println(a);
        }
        static void change(int a){           //将传入的a加1
            a++;
        }
        public static void main(String[] args){
            aMethod();                        //执行并输出
        }
    }
    猜猜程序的输出会是什么呢?1还是2?结果是1。为什么呢?
        因为a是int 数据,所以作为参数传递的时候,a并没真正传入change(a).传入的是a的一个副本。所以change不管怎么对a进行处理都不会改变aMethod中a的值。
    那么有没有办法通过外部的一个方法改变另一个方法里的值呢?当然有,只要使用对象的引用也叫句柄。说起来文绉绉的倒不如举个例子:
    import java.util.*;                      //LinkedList要用到这个包
    public class Parameter{
        static void aMethod(){
            LinkedList a = new LinkedList();  //生成一个LinkedList a对象
            a.add("a");
            change(a);
            for(int i=0;i<a.size();i++){      //将链表中所有数据输出
                System.out.println(a.get(i).toString());
            }
        }
        static void change(LinkedList a){     //将传入的a加1
            a.add("b");                       //为a中再添加一个b
        }
        public static void main(String[] args){
            aMethod();                        //执行并输出
        }
    }
    输出的结果是:
    a
    b
        这说明了什么?说明change(LinkedList a)方法已经改变了a中的值。那么为什么a是对象就可以改变呢?我们将a传入change方法的时候传入的不是某个对象,而是这个对象的引用(或者叫做句柄)插入一句,什么是句柄?比如你,作为一个人,是一个对象,引用(句柄)就是你的身份证号码。当我们把引用作为参数传入方法的时候,引用同样也进行了复制,但复制后的引用指向同一个对象,所以change()里对a 的改变其实也就是对aMethod()里a的改变,因为他们是同一个对象!
        是不是说只要是对象就可以了呢?不一定!
        比如String类型的数据,即使你这样生成一个String a对象
                       String a = new String("go to hell");
    a的确是一个对象,但是在a的引用复制的时候,原来的对象也会丢失。其实String 类型的数据在每次改变应用的时候都会清楚原来的对象。
    比如在你这么使用的时候:
                       String a="you";//第一行
                     a=a+"are fool";//第二行
    第一行的a和第二行的a所代表的是完全不同的对象。所以说如果程序里要对String进行大量改变的时候建议不要使用String,如果不小心使用了,你的程序将莫名其妙地占用大量的内存。不用String用什么?用StringBuffer!

    posted @ 2013-08-08 21:39 奋斗成就男人 阅读(148) | 评论 (0)编辑 收藏

    java对象序列化(Serializtion)

    不想说得太过于文绉绉,其实序列化,说白了就是将对象以文件的形式保存起来,反序列化,顾名思义,就是将对象文件转化为程序中的对象。一个对象如果要被序列化则必须实现Serializable接口(implements Serializable)。
    序列化:
    在这一过程中需要用到java.io包中的地两个类:FileOutputSteam 和ObjectOutputSteam
    下面是一个将LinkedList对象序列化的简单例子,LinkedList已经实现了Serializable接口(implements Serializable),方法(Method)如下:
    import java.io.*;
    ...//外部代码
    public static void OutputObject() throws
            FileNotFoundException,IOException{
        LinkedList ll=new LinkedList();
        FileOutputStream fos=new FileOutputStream("object");
        ObjectOutputStream oos=new ObjectOutputStream(fos);
        oos.writeObject(ll);

    }
    ...//外部代码
    关键代码就是三行,相当容易。
    反序列化:
    这一过程要用到FileInputStream和ObjectInputSteam,都在java.io包里
    ...//外部代码
    public static Object InputObject() throws FileNotFoundException,
                IOException, ClassNotFoundException{
        FileInputStream fis=new FileInputStream("object");
        ObjectInputStream ois=new ObjectInputStream(fis);

        return ois.readObject();//返回对象
    }
    ...//外部代码
    关键代码就是两行。
     
    当然这只是一个简单的入门,如果你被老外的书整晕了的话,上面这两段代码是很好的参考。

    posted @ 2013-08-08 21:34 奋斗成就男人 阅读(167) | 评论 (0)编辑 收藏

    java 产生随机数的两种方式

    在java中,我们可以通过两种方式来获取随机数(generating a random number)一种是大家熟悉的java.lang.Math.Random()静态方法,另一种是创建java.util.Random对象。下面是两种方法的使用过程:
     
    一.java.lang.Math.random()
        在使用这一静态方法的时候,我们不需要import任何包,因为java.lang.*包是默认载入的,下面举例说面使用方法:
    public class RandomTest{
        public static void main(String[] args){
            int i=Math.random();//random()会自动产生一个0.0-1.0的双精度随机数
            System.out.println(i);//输出
            i=Math.random()*1000;//产生0-1000的双精度随机数   
            System.out.println(i); 
            int b=(int)(Math.random()*1000);//产生0-1000的整数随机数   
            System.out.println(b);
        }
    }
     
    二.创建java.util.Random对象
    import java.util.random
    public class RandomTest{
        public static void main(String[] args){
            Random random=new Random();//创建random对象
            int intNumber=random.nextInt();//获取一个整型数
            float floatNumber=random.nextFloat();//获取一个浮点数(0-1)
            double doubleNumber=random.nextDouble();//获取双精度数(0-1)
            boolean booleanNumber=random.nextBoolean();//获取boolean数
            System.out.println("intNumber:"+intNumber);
            System.out.println("floatNumber:"+floatNumber);
            System.out.println("doubleNumber:"+doubleNumber);
            System.out.println("booleanNumber:"+booleanNumber);
        }
    }
    random在产生随机数的时候使用当前的时间作为基数,我们可以同过System.currentTimeMillis()来获取这个基数。当然我们也可以指定基数:
                      Random random=new Random(100);
    同一基数所产生的随机数序列是一样的,可以用下面这一段程序进行印证:
    import java.util.random
    public class RandomTest{
        public static void main(String[] args){
            Random random1=new Random(100);
            Random random2=new Random(100);
            for(int i=0;i<5;i++){
                System.out.print(random1.nextInt()+"\t");
                System.out.println(random2.nextInt()+"\t");
                System.out.println("---------------------------------");
            }
        }
    }
    我们可以发现random1和random2所产生的随机数是相同的。

    posted @ 2013-08-08 21:27 奋斗成就男人 阅读(130) | 评论 (0)编辑 收藏

    java 集合框架(Collection)和数组的排序

      根据约定,在使用java编程的时候应尽可能的使用现有的类库,当然你也可以自己编写一个排序的方法,或者框架,但是有几个人能写得比JDK里的还要好呢?使用现有的类的另一个好处是代码易于阅读和维护,这篇文章主要讲的是如何使用现有的类库对数组和各种Collection容器进行排序,(文章中的一部分例子来自《Java Developers Almanac 1.4》)
        首先要知道两个类:java.util.Arrays和java.util.Collections(注意和Collection的区别)Collection是集合框架的顶层接口,而Collections是包含了许多静态方法。我们使用Arrays对数组进行排序,使用 Collections对结合框架容器进行排序,如ArraysList,LinkedList等。
        例子中都要加上import java.util.*和其他外壳代码,如类和静态main方法,我会在第一个例子里写出全部代码,接下来会无一例外的省略。
     
    对数组进行排序
     
    比如有一个整型数组:
        int[] intArray = new int[] {4, 1, 3, -23};
    我们如何进行排序呢?你这个时候是否在想快速排序的算法?看看下面的实现方法:
        import java.util.*;
        public class Sort{
            public static void main(String[] args){
                int[] intArray = new int[] {4, 1, 3, -23};
                Arrays.sort(intArray);
            }
        }
    这样我们就用Arrays的静态方法sort()对intArray进行了升序排序,现在数组已经变成了{-23,1,3,4}.
     
    如果是字符数组:
        String[] strArray = new String[] {"z", "a", "C"};
    我们用:
        Arrays.sort(strArray);
    进行排序后的结果是{C,a,z},sort()会根据元素的自然顺序进行升序排序。如果希望对大小写不敏感的话可以这样写:
        Arrays.sort(strArray, String.CASE_INSENSITIVE_ORDER);
    当然我们也可以指定数组的某一段进行排序比如我们要对数组下表0-2的部分(假设数组长度大于3)进行排序,其他部分保持不变,我们可以使用:
        Arrays.sort(strArray,0,2);
    这样,我们只对前三个元素进行了排序,而不会影响到后面的部分。
     
    当然有人会想,我怎样进行降序排序?在众多的sort方法中有一个
        sort(T[] a, Comparator<? super T> c)
    我们使用Comparator获取一个反序的比较器即可,Comparator会在稍后讲解,以前面的intArray[]为例:
        Arrays.sort(intArray,Comparator.reverseOrder());
    这样,我们得到的结果就是{4,3,1,-23}。如果不想修改原有代码我们也可以使用:
        Collections.reverse(Arrays.asList(intArray));
    得到该数组的反序。结果同样为4,3,1,-23}。
    现在的情况变了,我们的数组里不再是基本数据类型(primtive type)或者String类型的数组,而是对象数组。这个数组的自然顺序是未知的,因此我们需要为该类实现Comparable接口,比如我们有一个Name类:
        class Name implements Comparable<Name>{
            public String firstName,lastName;
            public Name(String firstName,String lastName){
                this.firstName=firstName;
                this.lastName=lastName;
            }
            public int compareTo(Name o) {          //实现接口
                int lastCmp=lastName.compareTo(o.lastName);
                return (lastCmp!=0?lastCmp:firstName.compareTo(o.firstName));
               
            public String toString(){                //便于输出测试
                return firstName+" "+lastName;
            }
        }
    这样,当我们对这个对象数组进行排序时,就会先比较lastName,然后比较firstName 然后得出两个对象的先后顺序,就像compareTo(Name o)里实现的那样。不妨用程序试一试:
        import java.util.*;
        public class NameSort {
            public static void main(String[] args) {
                Name nameArray[] = {
                   new Name("John", "Lennon"),
                   new Name("Karl", "Marx"),
                   new Name("Groucho", "Marx"),
                   new Name("Oscar", "Grouch")
               };
               Arrays.sort(nameArray);
               for(int i=0;i<nameArray.length;i++){
                   System.out.println(nameArray[i].toString());
               }
           }
       }
    结果正如我们所愿:
        Oscar Grouch
        John Lennon
        Groucho Marx
        Karl Marx

     
    对集合框架进行排序
     
        如果已经理解了Arrays.sort()对数组进行排序的话,集合框架的使用也是大同小异。只是将Arrays替换成了Collections,注意Collections是一个类而Collection是一个接口,虽然只差一个"s"但是它们的含义却完全不同。
    假如有这样一个链表:
        LinkedList list=new LinkedList();
        list.add(4);
        list.add(34);
        list.add(22);
        list.add(2);
    我们只需要使用:
        Collections.sort(list);
    就可以将ll里的元素按从小到大的顺序进行排序,结果就成了:
        [2, 4, 22, 34]
    如果LinkedList里面的元素是String,同样会想基本数据类型一样从小到大排序。
    如果要实现反序排序也就是从达到小排序:
        Collections.sort(list,Collectons.reverseOrder());
    如果LinkedList里面的元素是自定义的对象,可以像上面的Name对象一样实现Comparable接口,就可以让Collection.sort()为您排序了。
     
    如果你想按照自己的想法对一个对象进行排序,你可以使用
        sort(List<T> list, Comparator<? super T> c)
    这个方法进行排序,在给出例子之前,先要说明一下Comparator的使用,
    Comparable接口的格式:
        public interface Comparator<T> {
            int compare(T o1, T o2);
        }
    其实Comparator里的int compare(T o1,T o2)的写法和Comparable里的compareTo()方法的写法差不多。在上面的Name类中我们的比较是从LastName开始的,这是西方人的习惯,到了中国,我们想从fristName开始比较,又不想修改原来的代码,这个时候,Comparator就可以派上用场了:
        final Comparator<Name> FIRST_NAME_ORDER=new Comparator<Name>() {
            public int compare(Name n1, Name n2) {
                 int firstCmp=n1.firstName.compareTo(n2.firstName);
                 return (firstCmp!=0?firstCmp:n1.lastName.compareTo 
                         (n2.firstName));
            }
        };
    这样一个我们自定义的Comparator FIRST_NAME_ORDER就写好了。
    将上个例子里那个名字数组转化为List:
        List<Name> list=Arrays.asList(nameArray);
        Collections.sort(list,FIRST_NAME_ORDER);
    这样我们就成功的使用自己定义的比较器设定排序。

    posted @ 2013-08-08 21:25 奋斗成就男人 阅读(162) | 评论 (0)编辑 收藏

    对称块加密算法加密模式详解(转载)

    在openssl或其他密码相关的资料中,我们经常看到对称加密算法有ECB、CBC之类加密模式的简称,到底这些加密模式是什么呢?它们之间有什么不同呢,今天就是为大家解开这个迷。
    在现有的对称加密算法中,主要有4种加密处理模式,这4种加密处理模式一般是针对块加密算法而言的,如DES算法。这4种加密模式罗列如下:
    模式中文描述           英文名称(Openssl缩写)
    电子密码本模式         Electronic Code Book(ECB)
    加密块链模式           Cipher Block Chaining(CBC)
    加密反馈模式           Cipher Feedback Mode(CFB)
    输出反馈模式           Output Feedback Mode(OFB)
       
    下面我们分别介绍这4种加密模式。
    **********************************************************************
    【电子密码本模式】
    这种模式是最早采用和最简单的模式,它将加密的数据分成若干组,每组的大小跟加密密钥长度相同,然后每组都用相同的密钥进行加密。比如DES算法,一个64位的密钥,如果采用该模式加密,就是将要加密的数据分成每组64位的数据,如果最后一组不够64位,那么就补齐为64位,然后每组数据都采用DES算法的64位密钥进行加密。下图:
    _______________________
    My name |is Drago|nKing
    -----------------------
    上图“My name is DragonKing”这句话每8个字符(64位)作为一块,然后使用一个相同的64位的密钥对每个块进行加密,最后一块不足64位,就补齐后再进行加密。
    可以看到,因为ECB方式每64位使用的密钥都是相同的,所以非常容易获得密文进行密码破解,此外,因为每64位是相互独立的,有时候甚至不用破解密码,只要简单的将其中一块替换就可以达到黑客目的。
    【加密块链模式】
    从这两个图中大家可以看到,CBC模式的加密首先也是将明文分成固定长度(64位)的块(P0,P1...),然后将前面一个加密块输出的密文与下一个要加密的明文块进行XOR(异或)操作计算,将计算结果再用密钥进行加密得到密文。第一明文块加密的时候,因为前面没有加密的密文,所以需要一个初始化向量(IV)。跟ECB方式不一样,通过连接关系,使得密文跟明文不再是一一对应的关系,破解起来更困难,而且克服了只要简单调换密文块可能达到目的的攻击。
    但是该加密模式的缺点是不能实时解密,也就是说,必须等到每8个字节都接受到之后才能开始加密,否则就不能得到正确的结果。这在要求实时性比较高的时候就显得不合适了。所以才有了下面两种加密模式。
    【加密反馈模式】
    加密反馈模式为了克服必须等待8个字节全部得到才能进行解密的缺点,采用了一个64位(8个字节)的位移寄存器来获得密文,如下图所示:
    上面两个图中C2、C3以及P10等都是一个字节(8位)的数据,所以能够实现字符的实时加密和解密,不用再等到8个字节都接受到之后再进行解密。图示是在进行第10个字节数据的加密和解密过程,在该过程中,先从移位寄存器取8个字节的数据(C2到C9)用密钥进行加密,然后取加密数据最左边的一个字节跟输入的明文P10进行XOR(异或)操作,得到的值作为输出密文C10,同时将C10送入到移位寄存器中。
    需要注意的是,如果其中有一个字节的密文在传输的时候发生错误(即使是其中的一位),那么它出现在移位寄存器期间解密的8个字节的数据都会得不到正确的解密结果,当然,这8个字节过去之后,依然可以得到正确的解密结果。但是一个比特错误就影响到8个字节(64个比特)的正确结果,导致鲁棒性太差,所以就又提出了下面的加密模式OFB。
    【输出反馈模式】
    输出反馈模式OFB跟CFB几乎是一样的,除了其以为寄存器的输入数据稍微有一点不同之外,如下图:
    可以看到,这种方法因为没有采用密文作为加密的数据,所以克服了由于传输过程中由于单个比特导致64个相关比特解密失败的情况,在本模式下,如果一个比特发生错误了,那么只会影响其本身对应的一个比特,而不会影响别的。但是相对于其它模式,因为数据之间相关性小,这种加密模式是比较不安全的,所以在应用的时候除非特别需要,一般不提倡应用OFB模式。
    原文地址 http://hi.baidu.com/msingle/blog/item/e9d7cd455e02ed25cffca3a6.html 
    其他的一些补充:
    ■ 缩写说明 ■ 
          IN    - 输入向量
        OUT   - 输出向量(未用于和明文加密前)
        ENC   - 加密算法
        K     - 加密密钥
        P     - 明文
        C     - 密文
        XOR   - 异或
        <<    - 左移
        BSIZE - 算法的加密块尺寸
        COUNT - 计数器
    ------------------------------------------------------------------------------
      计数器(CTR)模式: IN(N) = ENC(K, COUNT++), C(N) = IN(N) XOR P(N);CTR 模式被广泛用于 ATM 网络安全和 IPSec应用中,相对于其它模式而言,CRT模式具有如下特点:
        ■ 硬件效率:允许同时处理多块明文 / 密文。
        ■ 软件效率:允许并行计算,可以很好地利用 CPU 流水等并行技术。
        ■ 预处理: 算法和加密盒的输出不依靠明文和密文的输入,因此如果有足够的保证安全的存储器,加密算法将仅仅是一系列异或运算,这将极大地提高吞吐量。
        ■ 随机访问:第 i 块密文的解密不依赖于第 i-1 块密文,提供很高的随机访问能力
        ■ 可证明的安全性:能够证明 CTR 至少和其他模式一样安全(CBC, CFB, OFB, ...)
        ■ 简单性:与其它模式不同,CTR模式仅要求实现加密算法,但不要求实现解密算法。对于 AES 等加/解密本质上不同的算法来说,这种简化是巨大的。
        ■ 无填充,可以高效地作为流式加密使用。
      ------------------------------------------------------------------------------
      密文块链接(CBC)模式:IN(N) = P(N) XOR C(N-1), C(N) = ENC(K, IN(N));在 CTR出现前广泛使用的块加密模式,用于安全的分组(迭代式)加密和认证。
      ------------------------------------------------------------------------------
      密文反馈 (CFB) 模式:  IN(N) = C(N-1) << (BSIZE-j),  C(N) = ENC(K, IN(N)) << (BSIZE-j) XOR P(N). 其中 j 为每次加密的位数。CFB 模式与 CBC 模式原理相似,但一次仅处理 j 位数据,其余 BLOCKSIZE - j 位丢弃。由于以上性质,CFB 模式可以在不损失安全性的前提下,将块加密变为流式加密。但是该模式也是比较浪费的,因为在每轮加解密中都丢弃了大部分结果(j 通常为一字节(8 位),块加密算法中每块的尺寸通常为64、128 或 256 位不等)。
      ------------------------------------------------------------------------------
      输出反馈 (OFB) 模式:IN(N) = OUT(N-1) << (BSIZE-j),  C(N) = ENC(K, IN(N)) << (BSIZE-j) XOR P(N), OUT(N) = ENC(K, IN(N)) << (BSIZE-j). 该模式与 CFB 模式基本相同,只不过本次输入是上次迭代中尚未与明文异或时的输出。 与 CFB 模式一样, OFB 模式也可以作为流加密模式使用,除此之外,由于每次迭代的输入不是上次迭代的密文,从而保证了较强的容错能力, 即: 对一块(一字节)密文的传输错误不会影响到后继密文。但是,由于输入没有经过密文叠加使得其抗篡改攻击的能力较差,通常需要与消息验
    证算法或数字签名算法配套使用。OFB 通常用于噪音水平较高的通信连接以及一般的流式应用中。
      ------------------------------------------------------------------------------
      电码本(ECB)模式: IN(N) = P(N), C(N) = ENC(K, IN(N)). 最简单但最不安全的加密方式。每次迭代的输入都使用相同密钥进行无变换的直接加密。对于同样的明文片断,总会产生相同的,与之对应的密文段。抗重复统计和结构化分析的能力较差。一次性加密的最坏情况 (即:每次输入的明文都小于等于 BSIZE 时) 就是电码本模式。 仅在一次一密,或传出极少数据时考虑使用 ECB 模式。 
    转自:IaWeN's Blog-iawen,原创,安全,破解视频,网页设计,影视后期,AE特效
    链接:http://www.iawen.com/read.php?296

    posted @ 2013-08-08 21:16 奋斗成就男人 阅读(196) | 评论 (0)编辑 收藏

    形参和实参的区别

    形参出现在函数定义中,在整个函数体内都可以使用, 离开该函数则不能使用。
    实参出现在主调函数中,进入被调函数后,实参变量也不能使用。 
    形参和实参的功能是作数据传送。发生函数调用时, 主调函数把实参的值传送给被调函数的形参从而实现主调函数向被调函数的数据传送
    1.形参变量只有在被调用时才分配内存单元,在调用结束时, 即刻释放所分配的内存单元。因此,形参只有在函数内部有效。 函数调用结束返回主调函数后则不能再使用该形参变量。 
    2.实参可以是常量、变量、表达式、函数等, 无论实参是何种类型的量,在进行函数调用时,它们都必须具有确定的值, 以便把这些值传送给形参。 因此应预先用赋值,输入等办法使实参获得确定值。 
    3.实参和形参在数量上,类型上,顺序上应严格一致, 否则会发生“类型不匹配”的错误。 
    4.函数调用中发生的数据传送是单向的。 即只能把实参的值传送给形参,而不能把形参的值反向地传送给实参。 因此在函数调用过程中,形参的值发生改变,而实参中的值不会变化。
    5.当形参和实参不是指针类型时,在该函数运行时,形参和实参是不同的变量,他们在内存中位于不同的位置,形参将实参的内容复制一份,在该函数运行结束的时候形参被释放,而实参内容不会改变。 而如果函数的参数是指针类型变量,在调用该函数的过程中,传给函数的是实参的地址,在函数体内部使用的也是实参的地址,即使用的就是实参本身。所以在函数体内部可以改变实参的值

    posted @ 2013-08-08 21:16 奋斗成就男人 阅读(181) | 评论 (0)编辑 收藏

    对称加密和非对称加密介绍和区别

    什么是对称加密技术?

      对称加密采用了对称密码编码技术,它的特点是文件加密和解密使用相同的密钥,即加密密钥也可以用作解密密钥,这种方法在密码学中叫做对称加密算法,对称加密算法使用起来简单快捷,密钥较短,且破译困难,除了数据加密标准(DES),另一个对称密钥加密系统是国际数据加密算法(IDEA),它比DES的加密性好,而且对计算机功能要求也没有那么高。IDEA加密标准由PGP(Pretty Good Privacy)系统使用。

      对称加密算法在电子商务交易过程中存在几个问题:

      1、要求提供一条安全的渠道使通讯双方在首次通讯时协商一个共同的密钥。直接的面对面协商可能是不现实而且难于实施的,所以双方可能需要借助于邮件和电话等其它相对不够安全的手段来进行协商;

      2、密钥的数目难于管理。因为对于每一个合作者都需要使用不同的密钥,很难适应开放社会中大量的信息交流;

      3、对称加密算法一般不能提供信息完整性的鉴别。它无法验证发送者和接受者的身份;

      4、对称密钥的管理和分发工作是一件具有潜在危险的和烦琐的过程。对称加密是基于共同保守秘密来实现的,采用对称加密技术的贸易双方必须保证采用的是相同的密钥,保证彼此密钥的交换是安全可靠的,同时还要设定防止密钥泄密和更改密钥的程序。

      假设两个用户需要使用对称加密方法加密然后交换数据,则用户最少需要2个密钥并交换使用,如果企业内用户有n个,则整个企业共需要n×(n-1) 个密钥,密钥的生成和分发将成为企业信息部门的恶梦。

      常见的对称加密算法有DES、3DES、Blowfish、IDEA、RC4、RC5、RC6和AES 

     

    什么是非对称加密技术

       1976年,美国学者Dime和Henman为解决信息公开传送和密钥管理问题,提出一种新的密钥交换协议,允许在不安全的媒体上的通讯双方交换信息,安全地达成一致的密钥,这就是“公开密钥系统”。相对于“对称加密算法”这种方法也叫做“非对称加密算法”。

       与对称加密算法不同,非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(privatekey)。公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。

       非对称加密算法实现机密信息交换的基本过程是:甲方生成一对密钥并将其中的一把作为公用密钥向其它方公开;得到该公用密钥的乙方使用该密钥对机密信息进行加密后再发送给甲方;甲方再用自己保存的另一把专用密钥对加密后的信息进行解密。甲方只能用其专用密钥解密由其公用密钥加密后的任何信息。

       非对称加密算法的保密性比较好,它消除了最终用户交换密钥的需要,但加密和解密花费时间长、速度慢,它不适合于对文件加密而只适用于对少量数据进行加密。

       如果企业中有n个用户,企业需要生成n对密钥,并分发n个公钥。由于公钥是可以公开的,用户只要保管好自己的私钥即可(企业分发后一般保存的是私钥,用户拿的是公钥),因此加密密钥的分发将变得十分简单。同时,由于每个用户的私钥是唯一的,其他用户除了可以可以通过信息发送者的公钥来验证信息的来源是否真实,还可以确保发送者无法否认曾发送过该信息。非对称加密的缺点是加解密速度要远远慢于对称加密,在某些极端情况下,甚至能比非对称加密慢上1000倍。
       非对称加密的典型应用是数字签名。

       常见的非对称加密算法有:RSA、ECC(移动设备用)、Diffie-Hellman、El Gamal、DSA(数字签名用)

    企业加密系统应用 常用加密算法介绍

      对称加密、非对称加密、hash加密(md5加密是典型应用)

     

    Hash算法

    Hash算法特别的地方在于它是一种单向算法,用户可以通过Hash算法对目标信息生成一段特定长度的唯一的Hash值,却不能通过这个Hash值重新获得目标信息。因此Hash算法常用在不可还原的密码存储、信息完整性校验等。

    常见的Hash算法有MD2、MD4、MD5、HAVAL、SHA

     

    加密算法的效能通常可以按照算法本身的复杂程度、密钥长度(密钥越长越安全)、加解密速度等来衡量。上述的算法中,除了DES密钥长度不够、MD2速度较慢已逐渐被淘汰外,其他算法仍在目前的加密系统产品中使用。

    posted @ 2013-08-08 21:09 奋斗成就男人 阅读(165) | 评论 (0)编辑 收藏

    各加密模式的演示(ECB,CBC) .

    对于较长的明文进行加密需要进行分块加密,但是直接加密(ecb)不容易隐藏模式,用OpenCV写了个程序论证了一下

    ECB

    优点就是简单,可以并行计算,不会迭代误差

    缺点就是隐藏不了模式

     

    Ecb encryption.png

    CBC

    需要初始化向量IV,来加密第一块C0.

    有点就是比ECB好

    缺点不利于并行计算、误差会迭代,还需要初始向量

     

    C_i = E_K(P_i \oplus C_{i-1}), C_0 = IV

     

     

    Cbc encryption.png




    加密算法为简单的位翻转

     

    1. #define bitrev(b) (((b)<<7)&0x80) |  \   
    2.       (((b)<<5)&0x40) |  \  
    3.       (((b)<<3)&0x20) |  \  
    4.       (((b)<<1)&0x10) |  \  
    5.       (((b)>>1)&0x08) |  \  
    6.       (((b)>>3)&0x04) |  \  
    7.       (((b)>>5)&0x02) |  \  
    8.       (((b)>>7)&0x01)       
    ECB加密,就是直接分块进行加密

     

     

    1. for(int i=0;i<grey->width;i++)  
    2.     for(int j=0;j<grey->height;j++)  
    3.         grey->imageData[j*grey->width+i]=bitrev(grey->imageData[j*grey->width+i]);  
    4. cvNamedWindow("ecb");  
    5. cvShowImage("ecb", grey);  


     

    CBC加密,与上一块密文异或后加密

     

    1. for(int i=0;i<grey->width;i++)  
    2.     for(int j=0;j<grey->height;j++)  
    3.         if(i!=0&&j!=0)            
    4.             grey->imageData[j*grey->width+i]=bitrev(grey->imageData[j*grey->width+i]^grey->imageData[j*grey->width+i-1]);  
    5.         else  
    6.             grey->imageData[0]=grey->imageData[0]^IV;  
    7. cvNamedWindow("cbc");  
    8. cvShowImage("cbc", grey);  

    posted @ 2013-08-08 20:52 奋斗成就男人 阅读(354) | 评论 (0)编辑 收藏

    对称加密和分组加密中的四种模式(ECB、CBC、CFB、OFB)

    . AES对称加密:


                                                          AES加密



                             分组



     

     

    . 分组密码的填充


                                                       分组密码的填充

     

    e.g.:


    . 流密码:



     

     

    . 分组密码加密中的四种模式:

    3.1 ECB模式

    优点:

    1.简单;

    2.有利于并行计算;

    3.误差不会被传送;

    缺点:

    1.不能隐藏明文的模式;

    2.可能对明文进行主动攻击;

     


    3.2 CBC
    模式:

    优点:

    1.不容易主动攻击,安全性好于ECB,适合传输长度长的报文,SSLIPSec的标准。

    缺点:

    1.不利于并行计算;

    2.误差传递;

    3.需要初始化向量IV

     

    3.3 CFB模式:


     优点:

    1.隐藏了明文模式;

    2.分组密码转化为流模式;

    3.可以及时加密传送小于分组的数据;

    缺点:

    1.不利于并行计算;

    2.误差传送:一个明文单元损坏影响多个单元;

    3.唯一的IV;

     

    3.4 OFB模式:


     优点
    :

    1.隐藏了明文模式;

    2.分组密码转化为流模式;

    3.可以及时加密传送小于分组的数据;

    缺点:

    1.不利于并行计算;

    2.对明文的主动攻击是可能的;

    3.误差传送:一个明文单元损坏影响多个单元;





                                                             PKCS#5填充方式

    posted @ 2013-08-08 20:45 奋斗成就男人 阅读(676) | 评论 (0)编辑 收藏

    深入理解按位异或运算符

    参与运算的两个值,如果两个相应bit位相同,则结果为0,否则为1。
    即:
       0^0 = 0, 
          1^0 = 1, 
          0^1 = 1, 
          1^1 = 0
    按位异或的3个特点:
    (1) 0^0=0,0^1=1  0异或任何数=任何数
    (2) 1^0=1,1^1=0  1异或任何数-任何数取反
    (3) 任何数异或自己=把自己置0
    按位异或的几个常见用途:
    (1) 使某些特定的位翻转
        例如对数10100001的第2位和第3位翻转,则可以将该数与00000110进行按位异或运算。
           10100001^00000110 = 10100111

    (2) 实现两个值的交换,而不必使用临时变量。
        例如交换两个整数a=10100001,b=00000110的值,可通过下列语句实现:
        a = a^b;   //a=10100111
        b = b^a;   //b=10100001
        a = a^b;   //a=00000110

    (3) 在汇编语言中经常用于将变量置零:
        xor   a,a

    (4) 快速判断两个值是否相等
        举例1: 判断两个整数a,b是否相等,则可通过下列语句实现:
            return ((a ^ b) == 0)
        
        举例2: Linux中最初的ipv6_addr_equal()函数的实现如下:
        static inline int ipv6_addr_equal(const struct in6_addr *a1, const struct in6_addr *a2)
        {
            return (a1->s6_addr32[0] == a2->s6_addr32[0] &&
                a1->s6_addr32[1] == a2->s6_addr32[1] &&
                a1->s6_addr32[2] == a2->s6_addr32[2] &&
                a1->s6_addr32[3] == a2->s6_addr32[3]);
        }
        
        可以利用按位异或实现快速比较, 最新的实现已经修改为:
        static inline int ipv6_addr_equal(const struct in6_addr *a1, const struct in6_addr *a2)
        {
        return (((a1->s6_addr32[0] ^ a2->s6_addr32[0]) |
            (a1->s6_addr32[1] ^ a2->s6_addr32[1]) |
            (a1->s6_addr32[2] ^ a2->s6_addr32[2]) |
            (a1->s6_addr32[3] ^ a2->s6_addr32[3])) == 0);
        }

    5  应用通式:

    对两个表达式执行按位异或。

    result = expression1 ^ expression2

    参数
    result

    任何变量。

    expression1

    任何表达式。

    expression2

    任何表达式。

    说明
    ^ 运算符查看两个表达式的二进制表示法的值,并执行按位异或。该操作的结果如下所示:

    0101     (expression1)1100     (expression2)----1001     (结果)当且仅当只有一个表达式的某位上为 1 时,结果的该位才为 1。否则结果的该位为 0。

    只能用于整数

     


    下面这个程序用到了“按位异或”运算符:

    class E 
    { public static void main(String args[ ]) 

      char  a1='十' ,  a2='点' ,  a3='进' ,  a4='攻' ; 
      char secret='8' ; 
      a1=(char) (a1^secret); 
      a2=(char) (a2^secret); 
      a3=(char) (a3^secret); 
      a4=(char) (a4^secret); 
      System.out.println("密文:"+a1+a2+a3+a4); 
      a1=(char) (a1^secret); 
      a2=(char) (a2^secret); 
      a3=(char) (a3^secret); 
      a4=(char) (a4^secret); 
      System.out.println("原文:"+a1+a2+a3+a4); 

    }

    就是加密啊解密啊

    char类型,也就是字符类型实际上就是整形,就是数字.

    计算机里面所有的信息都是整数,所有的整数都可以表示成二进制的,实际上计算机只认识二进制的. 
    位运算就是二进制整数运算啦. 
    两个数按位异或意思就是从个位开始,一位一位的比. 
    如果两个数相应的位上一样,结果就是0,不一样就是1 
    所以111^101=010 
    那加密的过程就是逐个字符跟那个secret字符异或运算. 
    解密的过程就是密文再跟同一个字符异或运算 
    010^101=111 
    至于为什么密文再次异或就变原文了,这个稍微想下就知道了..

    posted @ 2013-07-18 18:55 奋斗成就男人 阅读(218) | 评论 (0)编辑 收藏

    常见Map 及 ArrayList 是否有序总结

    说明:此处的排序 是指:

    1: 往集合中插入元素的顺序与遍历元素的顺序的关系;

    2: 往对象中插入元素否会根据元素的大小排序

     

    ?
    public class MapSortTest {
     
        public static void main(String[] args) {
             
            System.out.println("放入顺序为:a:aaa c:ccc b:bbb d:ddd ");
            System.out.println("HashMap 排序测试");
            Map map = new HashMap(); 
            map.put("a", "aaa");  
            map.put("c", "ccc");
            map.put("b", "bbb"); 
            map.put("d", "ddd"); 
            Iterator iterator = map.keySet().iterator(); 
            while (iterator.hasNext()) { 
                Object key = iterator.next(); 
                System.out.println("key:"+key+"         value:" + map.get(key)); 
            } 
            System.out.println("HashMap 进出无次序 ; key大小无次序 ");
            System.out.println("***********************************************************");
             
             
            System.out.println("Hashtable 排序测试");       
            Hashtable tab = new Hashtable(); 
            tab.put("a", "aaa"); 
            tab.put("c", "ccc");
            tab.put("b", "bbb");  
            tab.put("d", "ddd"); 
            Iterator iterator_1 = tab.keySet().iterator(); 
            while (iterator_1.hasNext()) { 
                Object key = iterator_1.next(); 
                System.out.println("key :"+key+"             value:"+ tab.get(key)); 
            } 
            System.out.println("Hashtable 进出无次序 ; key大小无次序 ");
            System.out.println("***********************************************************");
             
            System.out.println("TreeMap 排序测试");             
            TreeMap tmp = new TreeMap(); 
            tmp.put("a", "aaa"); 
            tmp.put("c", "ccc"); 
            tmp.put("b", "bbb"); 
            tmp.put("d", "ddd"); 
            Iterator iterator_2 = tmp.keySet().iterator(); 
            while (iterator_2.hasNext()) { 
                Object key = iterator_2.next(); 
                System.out.println("key:"+key+"          value:" + tmp.get(key)); 
            } 
            System.out.println("TreeMap 进出无次序 ; key大小从小到大 ");
            System.out.println("***********************************************************");
             
            System.out.println("LinkedHashMap 排序测试");               
            LinkedHashMap linkedHashMap = new LinkedHashMap(); 
            linkedHashMap.put("a", "aaa"); 
            linkedHashMap.put("c", "ccc"); 
            linkedHashMap.put("b", "bbb"); 
            linkedHashMap.put("d", "ddd"); 
            Iterator iterator2 = linkedHashMap.keySet().iterator(); 
            while (iterator2.hasNext()) { 
                Object key = iterator2.next(); 
                System.out.println("key:"+key+"          value:" + linkedHashMap.get(key)); 
            }       
            System.out.println("LinkedHashMap 先进先出; key大小无次序 ");
            System.out.println();
             
            System.out.println("ArrayList 排序测试");
            System.out.println("放入顺序为:aaa ccc bbb ddd");
            ArrayList arrayList=new ArrayList(); 
            arrayList.add("aaa"); 
            arrayList.add("ccc"); 
            arrayList.add("bbb"); 
            arrayList.add("ddd"); 
            System.out.println("ArrayList 先进先出;值大小无次序 ");
    //      Collections.sort(arrayList); 
            for(int i=0;i<arrayList.size();i++){ 
                System.out.println(arrayList.get(i)); 
            } 
            System.out.println("***********************************************************");
        }
     
    }

     

    运行结果:

    ?
    放入顺序为:a:aaa c:ccc b:bbb d:ddd 
    HashMap 排序测试
    key:d         value:ddd
    key:b         value:bbb
    key:c         value:ccc
    key:a         value:aaa
    HashMap 进出无次序 ; key大小无次序 
    ***********************************************************
    Hashtable 排序测试
    key :b             value:bbb
    key :a             value:aaa
    key :d             value:ddd
    key :c             value:ccc
    Hashtable 进出无次序 ; key大小无次序 
    ***********************************************************
    TreeMap 排序测试
    key:a          value:aaa
    key:b          value:bbb
    key:c          value:ccc
    key:d          value:ddd
    TreeMap 进出无次序 ; key大小从小到大 
    ***********************************************************
    LinkedHashMap 排序测试
    key:a          value:aaa
    key:c          value:ccc
    key:b          value:bbb
    key:d          value:ddd
    LinkedHashMap 先进先出; key大小无次序 
     
    ArrayList 排序测试
    放入顺序为:aaa ccc bbb ddd
    LinkedHashMap 先进先出;值大小无次序 
    aaa
    ccc
    bbb
    ddd
    ***********************************************************

    posted @ 2013-06-09 21:20 奋斗成就男人 阅读(2454) | 评论 (0)编辑 收藏

    Apache Java项目全介绍

    Apache Java项目全介绍最近接触Jakarta-Common-BeanUtils这个东东比较 多,于是对Apache Jakarta Project产生了兴趣,上他们的官方网站上看了下感觉有用的东西好多,眼花缭乱的,又没有中文网站,又上各大论坛搜了下,也没有发现一个集中该项目的资料,于是决定自己整理翻译一下,有助于各位网友更好的了解该项目。如果有什么描述不对不全面的地方,希望各位提出来给大家分享。

    Jakarta项目是ASF(The Apache Software Foundation)的一部分。ASF是一个非赢利组织,她鼓励基于开放的软件许可下进行合作、注重实效的开发,并提供各个领域的高质量软件,她涉及到 Http服务器,编译工具,类库,开发架构,服务器端Java技术,J2EE容器,数据库工具,日志工具,XML解析等等诸多领域。ASF提供的java 项目有一部分在Jakarta中,还有一些成为独立的诸如Tomcat的项目,Jakarta项目则提供了多种多样开源的java解决通用方案。

    先介绍一下ASF中和Jakarta项目并列的java项目: 
    Ant ——java构建工具,使用一个配置文件就可以完成java的项目的,编译、打包、测试、运行、部署、生成文档等诸多工作。 
    Avalon ——是一个包括核心框架、工具、组件和容器的面向组件编程(AOP)的完整开发平台。使用关键设计模式,如反向控制模式(IoC)和分离考虑模(SoC)。 Avalon提供各种基本组件和缺省的应用程序模块,帮助你快速的建立你自己的应用程序解决方案。 
    Excalibur ——集多个开源项目(Avalon Framework、LogKit和Cornerstone)于一身的轻量级可嵌入式反向控制容器。 
    Gump ——是Apache组织自己也使用的一个持续集成工具,全面支持Ant和Maven,当有新的改动提交到版本控制系统,它可以检查出潜在的冲突,并及时通知项目组的所有成员并自动生成改动的详细报告。 
    James ——是一套用java开发的邮件、新闻组、消息服务器,提供了比较完善的配置方案,尤其是关于邮件内容存储和用户信息存储。 支持 SMTP, POP3 , NNTP , IMAP 。 
    Logging ——可靠,快速的日志工具。 
    Lucene ——Java开发的高性能,全方位的文本搜索引擎。替文件的每一个字作索引,索引让搜寻的效率比传统的逐字比较大大提高, Lucen提供一组解读,过 滤,分析文件,编排和使用索引的API,它的强大之处除了高效和简单外,是最重要的是使使用者可以随时应自已需要自订其功能。 
    Maven ——是一个潜在的基于java的apache ant的构建工具的替代者。提供了更强大的功能和易用性。 
    Portals ——提供了功能全面的、具有商业价值的企业门户。门户概念:门户对企业内的各种资源如信息管理系统进行整合并通过单一接口对外提供服务,雇员、合伙人及 顾客可以通过任何装置在任何地点通过门户入口享受到企业提供的服务,分析家们预计,门户将成为下一代的桌面环境。 
    Struts ——一个实现MVC model2的web应用程序开发框架。通过一个配置文件可以很好的对各种组件进行装配,结构清晰,应用的最广泛的额web开发框架。
    Tapestry——类似 Struts,也是一个基于servlet的应用程序框架,支持MVC,出现的较晚,不如Struts普及,主要利用javabean和xml技术进行开发, 
    Tomcat ——Serlvet容器,同时具有传统的Web服务器的功能,如:处理Html页面。能够处理动静态网页。 
    Watchdog ——用来检查一个servlet或jsp容器在相应规范上的执行情况的兼容性。但是该项目已经静止了,只支持Servlet2.3、JSP1.2,相应的Serlvet容器如Tomcat也只支持Tomcat4.x。  
    下面介绍下Jakarta的各个子项目:

    Alexandria——已经不再开发 
    BCEL ——The Byte Code Engineering Library (formerly known as JavaClass) 字节码引擎类库,它让用户方便的分析,创建,操作java的class文件成为可能。 它可以让您深入 JVM 汇编语言进行类操作的细节。 
    BSF ——bean脚本框架 在java应用内对脚本语言提供了支持,通过脚本语言可以访问java的对象和方法。 
    Cactus ——一个基于JUnit框架的简单测试框架,用来单元测试服务端Java代码。 Cactus单元测试服务端内容包括servlet,EJB, tag librarie, filter等 
    Commons ——提供很多日常开发中使用率很高的功能解决方案,已被很多著名的开源项目采用。具体的项目列表后面会有。 
    ECS ——使用Java语言和面向对象方法创建标记语言文档(HTML,XML)的开源项目。 
    HiveMind ——是一个服务和配置的微型内核, 一套通过简单的java对象和接口创建复杂应用的框架。 
    HttpComponents ——提供了java.net包所不能提供的更多强大的、方便的http协议处理功能。 
    JCS ——一个分布式的缓存系统,用来提高应用程序的性能,并且提供很多强大的额外功能。 
    JMeter ——纯java开发的一套桌面应用程序。用来进行功能测试和性能测试。它可以用来测试静止资料库或者活动资料库中的服务器的运行情况,可以用来模拟对服 务器或者网络系统加以重负荷以测试它的抵抗,或者用来分析不同负荷类型下的所有运行情况。它也提供了一个可替换的界面用来定制数据显示,测试同步及测试 的创建和执行。 
    ORO ——一套文本处理工具,能提供perl5.0兼容的正则表达式、 AWK-like正则表达式, glob 表达式。还提供替换,分割,文件名过虑等功能。 
    POI ——一套用来创建,读写基于OLE 2组件文档格式的文件。使用Java来读写MS Excel ,Word文件。 
    Regexp ——一套纯java的正则表达式相关的包。 
    Slide ——主要模块是一个可以做为内容管理框架底层的内容仓库.它可以把内容信息存取到专门的,异质的,分布式的数据库中.Slide还增加了security, locking, versioning等特性. 
    Taglibs ——一套在开发web应用时十分有用的,jsp 通用 tag包。 
    Turbine ——类似 Struts,也是一个基于servlet的应用程序框架,支持MVC。提供了大量可重用的组件。此框架包中包含了大量组件,但是这些组件是离散的。 
    Velocity ——是一个基于java的模板引擎(template engine)。它允许任何人仅仅简单的使用模板语言(template language)来引用由java代码定义的对象。 当Velocity应用于web开发时,界面设计人员可以和java程序开发人员同步开发一个遵 循MVC架构的web站点,也就是说,页面设计人员可以只关注页面的显示效果,而由java程序开发人员关注业务逻辑编码。 Velocity将 java代码从web页面中分离出来,这样为web站点的长期维护提供了便利, 同时也为我们在JSP和PHP之外又提供了一种可选的方案。 Velocity的能力远不止web站点开发这个领域,例如,它可以从模板(template)产生SQL和PostScript、XML,它也可以被 当作一个独立工具来产生源代码和报告,或者作为其他系统的集成组件使用。Velocity也可以为Turbine web开发架构提供模板服务(template service)。 Velocity+Turbine提供一个模板服务的方式允许一个web应用以一个真正的MVC模型进行开发。 
    Apache java项目全介绍2

    下面介绍一下Jakarta下的Commons:一个csdn网友描述得很贴切,Commons就好比一个java百宝箱。
    commons分为3部分Commons Proper、Commons Sandbox和Commons Dormant。
    Commons Proper:提供了设计良好可重用的java组件,并都经过了广泛、严格的测试。
    Commons Sandbox:处于实验、测试阶段的组件。
    Commons Dormant:处于停滞状态,从Sandbox退出的,不活跃的组件,谨慎使用。

    Commons Proper组件:

    Attributes—— 支持源代码级的元数据。 
    BeanUtils——提供对 Java 反射和自省API的包装,处理javabean的工具。 
    Betwixt——将JavaBeans与XML相互转换。 
    Chain——对Chain of Responsibility(责任链)设计模式的实现。使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。 
    CLI——处理命令行的命令的解析。 
    Codec——包含一些通用的编码解码算法。包括一些语音编码器, Hex, Base64, 以及URL encoder。 
    Collections——扩展和增加标准的 Java Collection框架。 
    Configuration——操作各种格式的配置文件。Properties文件 /XML文件 /JNDI /JDBC 数据源 /System properties /Applet parameters / Servlet parameters 
    Daemon——创建类似unix守护线程的java代码,可以安全地执行一些后台操作,线程不被某个应用程序控制,而是由操作系统控制类似windows的service,可以设置一个服务依赖于另一个服务,一个服务关闭前必须先执行另一个服务。 
    DBCP——一个数据库连接池 
    DbUtils——一个JDBC的工具类,比如可以将ResultSets生成javabean。 
    Digester——基于规则的XML文档解析,主要用于XML到Java对象的映射. 
    Discovery——提供工具来定位资源 (包括类) ,通过使用各种模式来映射服务/引用名称和资源名称。 
    EL——JSP 2.0引入的表达式 
    Email——处理e-mail 
    FileUpload——web应用中的文件上传组件 
    HttpClient——使用HTTP协议的客户端开发框架 
    IO——帮助进行IO功能开发 
    Jelly ——Jelly能够把XML转换成可执行代码,所以Jelly是一个基于XML与Java的脚本和处理引擎。 Jelly借鉴了JSP定指标签,Velocity, Cocoon和Xdoclet中的脚本引擎的许多优点。Jelly可以用在命令行,Ant或者Servlet之中。 
    Jexl——Jexl是一个表达式语言,通过借鉴来自于Velocity的经验扩展了JSTL定义的表达式语言。 
    JXPath——使用XPath语法操作javabean的工具。 
    Lang——提供对java.lang包的扩展。 
    Launcher——跨平台的java程序的启动 
    Logging ——提供的是一个日志(Log)接口(interface),同时兼顾轻量级和不依赖于具体的日志实现工具。它提供给中间件/日志工具开发者一个简单的日志操作抽象,允许程序开发人员使用不同的具体日志实现工具。用户被假定已熟悉某种日志实现工具的更高级别的细节。JCL提供的接口,对其它一些日志工具,包括Log4J, Avalon LogKit, and JDK 1.4等,进行了简单的包装,此接口更接近于Log4J和LogKit的实现. 
    Math——Math 是一个轻量的,自包含的数学和统计组件,解决了许多非常通用但没有及时出现在Java标准语言中的实践问题. 
    Modeler—— 支持兼容JMX规范的MBeans开发。 
    Net——集合了网络工具和协议工具的实现 
    Pool——Commons-Pool 提供了通用对象池接口,一个用于创建模块化对象池的工具包,以及通常的对象池实现。 
    Primitives——对java原始类型的支持。 
    SCXML——处理SCXML 
    Transaction——事务处理,实现了多层次锁、事务集合、事务文件的访问。 
    Validator——提供了一个简单的,可扩展的框架来在一个XML文件中定义校验器 (校验方法)和校验规则。支持校验规则的和错误消息的国际化。 
    VFS——访问各种文件系统,可以是本地文件、HTTP服务器上的文件、zip中的文件。 
    Commons Sandbox组件:

    Compress——处理压缩文件如tar, zip 和 bzip2 格式。 
    CSV——处理CSV文件 
    Exec——安全地处理外部进程 
    Finder——实现类似UNIX find命令的功能 
    I18n——处理软件的I18n功能 
    Id——生成id号功能 
    Javaflow——捕捉程序运行状态 
    JCI——java编译接口 
    OpenPGP——处理加密方法OpenPGP. 
    Pipeline——处理类似工作队列的管道工具 
    Proxy——生成动态代理 

    posted @ 2013-05-29 23:16 奋斗成就男人 阅读(198) | 评论 (0)编辑 收藏

    让HTML中的文本框中的文字垂直居中 .

    当你自己定义了 Text 的 height 属性时,在 Text 中输入的文字都不是垂直居中的,不过你可以添加CSS来控制它,让输入的文字垂直居中,使网页更完美。

    <html>
    <head>
    <style type="text/css">
        #text {
            height:20px;
            vertical-align:middle;
            line-height:20px;  /*line-height must be equal to height*/    
        }
    </style>
    </head>
    <body>
        <table>
            <input type="text" id="text">
        </table>
    </body>
    </html>

    加入 verticla-align、line-height 两个属性后,文本框中的文字就在文本框中垂直居中了,要注意的是 line-height 必须要等于 height 。


    posted @ 2013-05-14 19:25 奋斗成就男人 阅读(6895) | 评论 (3)编辑 收藏

    利用BeanUtils在对象间复制属性

    commons-beanutils是jakarta commons子项目中的一个软件包,其主要目的是利用反射机制对JavaBean的属性进行处理。我们知道,一个JavaBean通常包含了大量的属性,很多情况下,对JavaBean的处理导致大量get/set代码堆积,增加了代码长度和阅读代码的难度(什么,你的薪水按代码行数计算?那千万别让老板看到此帖哦)

    BeanUtils是这个包里比较常用的一个工具类,这里只介绍它的copyProperties()方法。该方法定义如下:

    public static void copyProperties(java.lang.Object dest,java.lang.Object orig)
      
    throws java.lang.IllegalAccessException,
             java.lang.reflect.InvocationTargetException

    如果你有两个具有很多相同属性的JavaBean,一个很常见的情况就是Struts里的PO对象(持久对象)和对应的ActionForm,例如Teacher和TeacherForm。我们一般会在Action里从ActionForm构造一个PO对象,传统的方式是使用类似下面的语句对属性逐个赋值: 
    //得到TeacherForm
    TeacherForm teacherForm=(TeacherForm)form;
    //构造Teacher对象
    Teacher teacher=new Teacher();
    //赋值
    teacher.setName(teacherForm.getName());
    teacher.setAge(teacherForm.getAge());
    teacher.setGender(teacherForm.getGender());
    teacher.setMajor(teacherForm.getMajor());
    teacher.setDepartment(teacherForm.getDepartment());

    //持久化Teacher对象到数据库
    HibernateDAO=;
    HibernateDAO.save(teacher);
    而使用BeanUtils后,代码就大大改观了,如下所示: 
    //得到TeacherForm
    TeacherForm teacherForm=(TeacherForm)form;
    //构造Teacher对象
    Teacher teacher=new Teacher();
    //赋值
    BeanUtils.copyProperties(teacher,teacherForm);
    //持久化Teacher对象到数据库
    HibernateDAO=;
    HibernateDAO.save(teacher);
    如果Teacher和TeacherForm间存在名称不相同的属性,则BeanUtils不对这些属性进行处理,需要程序员手动处理。例如Teacher包含modifyDate(该属性记录最后修改日期,不需要用户在界面中输入)属性而TeacherForm无此属性,那么在上面代码的copyProperties()后还要加上一句: 
    teacher.setModifyDate(new Date());
    怎么样,很方便吧!除BeanUtils外还有一个名为PropertyUtils的工具类,它也提供copyProperties()方法,作用与BeanUtils的同名方法十分相似,主要的区别在于后者提供类型转换功能,即发现两个JavaBean的同名属性为不同类型时,在支持的数据类型范围内进行转换,而前者不支持这个功能,但是速度会更快一些。BeanUtils支持的转换类型如下:
    • java.lang.BigDecimal
    • java.lang.BigInteger
    • boolean and java.lang.Boolean
    • byte and java.lang.Byte
    • char and java.lang.Character
    • java.lang.Class
    • double and java.lang.Double
    • float and java.lang.Float
    • int and java.lang.Integer
    • long and java.lang.Long
    • short and java.lang.Short
    • java.lang.String
    • java.sql.Date
    • java.sql.Time
    • java.sql.Timestamp

    这里要注意一点,java.util.Date是不被支持的,而它的子类java.sql.Date是被支持的。因此如果对象包含时间类型的属性,且希望被转换的时候,一定要使用java.sql.Date类型。否则在转换时会提示argument mistype异常。

    本文地址:http://www.cnblogs.com/bjzhanghao/archive/2004/07/30/28607.html

     

    posted @ 2013-05-07 01:19 奋斗成就男人 阅读(148) | 评论 (0)编辑 收藏

    Java 12小时和24小时制时间format

    12小时制: dff = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
    24小时制: dff = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    posted @ 2013-04-15 14:56 奋斗成就男人 阅读(530) | 评论 (0)编辑 收藏

    String、data、Calendar、Timestamp 之间的转换


    String、data、Calendar、Timestamp 之间的转换 

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    1.Calendar 转化 String 
    //获取当前时间的具体情况,如年,月,日,week,date,分,秒等 
            Calendar calendat = Calendar.getInstance();
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    String dateStr = sdf.format(calendar.getTime());

    2.String 转化Calendar
    String str="2010-5-27";
    SimpleDateFormat sdf= new SimpleDateFormat("yyyy-MM-dd");
    Date date =sdf.parse(str);
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(date);

    3.Date 转化String
    SimpleDateFormat sdf= new SimpleDateFormat("yyyy-MM-dd");
    String dateStr=sdf.format(new Date());

    4.String 转化Date
    String str="2010-5-27";
    SimpleDateFormat sdf= new SimpleDateFormat("yyyy-MM-dd");
    Date birthday = sdf.parse(str);

    5.Date 转化Calendar
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(new java.util.Date());

    6.Calendar转化Date
    Calendar calendar = Calendar.getInstance();
    java.util.Date date =calendar.getTime();

    7.Date 转成 String
    System.out.println(sdf.format(new Date())); 
    8.String 转成 Timestamp
    Timestamp ts = Timestamp.valueOf("2011-1-14 08:11:00");

    9.Timestamp 转成 String
    sdf.format(ts);

    Timestamp和Date多数用法是一样的。
    10.Date 转 TimeStamp
    SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    String time = df.format(new Date());
    Timestamp ts = Timestamp.valueOf(time);

    11.日期比较大小
    String ti="2010-11-25 20:11:00";
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 
    Date time=sdf.parse(ti);
    String ti2="2011-11-26 20:11:00";
    Date time2=sdf.parse(ti2);
    int c=ti2.compareTo(ti);
    if(c>0){
        System.out.println(ti+"大");
    }else if(c==0){
        System.out.println("一样大");
    }else{
        System.out.println(ti2+"大");
    }

    12.Date/ Timestamp 转成 Calendar 
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(startDate);
    calendar.add(Calendar.YEAR, 2);   //日期加2年
    System.out.println(calendar.getTime());
    calendar.add(Calendar.DATE, -30);     //日期加30天
    System.out.println(calendar.getTime());
    calendar.add(Calendar.MONTH, 3);  //日期加3个月
    System.out.println(calendar.getTime());
    Date date=new Date();
    DateFormat df=DateFormat.getDayeInstance();
    ps.setString(4,df.format(date))
    Date date = new Date(); 
    SimpleDateFormat from = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
    String times = from.format(date);
    public class Test1 {
    public static void main(String[] args) {
      long   m=System.currentTimeMillis();
      System.out.println(new Date(m) );
    }

    posted @ 2013-04-15 14:38 奋斗成就男人 阅读(264) | 评论 (0)编辑 收藏

    Linux面试题大全

         摘要: 一.填空题: 1. 在Linux系统中,以 文件 方式访问设备 。 2. Linux内核引导时,从文件 /etc/fstab 中读取要加载的文件系统。 3. Linux文件系统中每个文件用 i节点 来标识。 4. 全部磁盘块由四个部分组成,分别为引导块 、专用块 、 i节点表块 和数据存储块。 5. 链接分为: 硬链接 和 符号链接 。 ...  阅读全文

    posted @ 2013-04-01 00:57 奋斗成就男人 阅读(509) | 评论 (0)编辑 收藏

    从1.5k到18k, 一个程序员的5年成长之路 .

    昨天收到了心仪企业的口头offer, 回首当初什么都不会开始学编程, 到现在恰好五年. 整天在社区晃悠, 看了不少的总结, 在这个时间点, 我也写一份自己的总结吧.

    我一直在社区分享, 所以, 这篇总结也是本着一种分享的态度, 希望相比我还年轻的同学们, 可以从中找到一些让自己成长更快的文字.


    先介绍下背景:
    1. 2008年3月开始学习编程, 目前2013年3月;
    2. 2009年6月计算机专业本科毕业;
    3. 大学期间, 基本稳拿班级倒数第一, 高考英语49分, 大学英语除了补考没及格过.


    接着, 是一份总结:
    1. 5年间60%以上的时间, 每天凌晨2-4点睡觉;
    2. 为学习编程花费的总时间超过6000小时;
    3. 手写了超过50万行代码;
    4. 记录了超过100万字学习笔记;
    5. 录制了两份视频教程;
    6. 翻译了小型技术文档5份以上, 5个php扩展的官方文档, jqueryui官方文档一份, 书籍<php扩展和嵌入式>
    7. 供职过4家公司;
    8. 获得两次优秀员工;


    下面是这几年的流水, 本人没有过硬的文采, 只是以流水的方式记录, 希望可以激励到别人, 仅此而已:

    2008年03月 -- 2008年10月, 一个偶然的机会, 看到了北京尚学堂的java视频教程, 以此为起点, 我开始了自己的编程学习之路. 5月份汶川地震, 我在甘肃, 学校给通宵电, 在这段时间, 我就基本很少去学校上课了, 每天晚上学习到凌晨5-6点, 接着睡到10-11点, 每天两袋1.3元的方便面, 其余所有的时间都用来学习. 这段时间, 我学会了基本的程序设计, 更重要的是, 视频中, 马士兵老是给我灌输了影响我后来最重要的两个观念: 1) 不要怕英文, 出错信息, 文档, 都是学习英文的机会; 2) 不要怕出错, 出错就是学习的机会. 在后来的5年中, 我一直坚持, 我是从基本每个英文单词都要查翻译软件, 到现在能翻译一些东西的. 同样, 我在碰到问题的时候, 都是自己跟踪源代码去解决. 这两个观念直接决定了我今天可以进入自己心仪的企业.


    2008年10月 -- 2009年1月, 这段时间, 宿舍搬到了校本部, 没有通宵电了. 学校一位老师找我们帮他做项目, 他为我们提供了他的宿舍, 很烂, 但我依然搬进去了, 就为了通宵电, 我住进了这个阴森森的宿舍, 恐惧缠绕着我, 但我依旧坚持. 白天帮老师做项目, 晚上继续自己的学习. 同样, 我也很感谢这位老师, 虽然他只给了我们很少的报酬, 但是, 我知道, 我得到的远远不是这些报酬可以比拟的. 这里这种很容易满足的心里也是很重要的, 我奉劝各位职场新人, 刚开始不要期望什么, 放低身段, 去做自己的积累就好了. (想起从社区里看到的一句话: 现在的你, 凭什么翘着二郎腿, 你应该放下你的腿, 身体前倾, 时刻保持战斗姿态)


    2009年02月, 一个小插曲, 我独自一人来到北京, 开始了第一次真正意义的独立, 我来找工作. 我开始在网上投了10多份简历, 没有回信. 接着我就急了, 直接从网上找招聘的公司, 查地图, 直接去公司面试, 一般都还是会给面试机会的. 最好的成绩是一家表示能给到3000左右, 但后来也没信了. 这段时间, 我有两个收获: 1) 我打印了一整本的<Java数据结构与算法>, 20天的时间, 把基础的数据结构与算法读了一遍; 2) 在一个完全陌生的城市, 我独自一人, 查招聘信息, 查地图, 找公司, 厚颜无耻的霸王面, 这一切都是对我处世能力的极大提升.


    2009年03月 -- 2009年06月, 回到学校, 仍然没有工作. 我继续在老师的小黑屋, 实现了所有我找工作时学习的数据结构与算法. 接着, 就进入了毕业季, 每天都泡在酒精中, 浑浑噩噩. 这段时间, 老婆把工作签到了山东淄博, 我也联系了一家淄博的公司, 准备毕业后去面试. 这段时间, 和高中的毕业季一样, 是值得怀念的, 放松, 惬意.


    2009年06月 -- 2010年03月, 我来到了淄博, 找到了之前联系的公司, 面试没有通过. 淄博是一个小城市, 做软件开发的没有几家, 还好, 山东人好, 虽然没有面试通过, 但我依然可以借宿在公司宿舍找工作, 就这样, 我放下了所有的尊严, 在别人的宿舍借住, 15天后, 我找到了我的第一家公司. 公司有30人左右, 做国家电网的项目, 老板人很好, 我还得到了一台笔记本电脑, 并且可以带回家. 我每天加班到9点, 然后回家继续学习大凌晨2点左右. 公司的工作相对轻松, 当然, 工资也很少, 只有1.5k. 老婆每周末都过来, 我们虽然没有钱, 经常要靠吃方便面度日, 但我们很幸福. 这段时间, 我学习了python, javascript, 翻译了jqueryui的文档, 录制了一套python的视频教程, 录制了一份fullcalendar的视频教程, 我的生活非常的充实, 当然, 我还有另一个收获: 我学会了吃苦. 冬天, 我住的小屋窗户基本起不到保暖作用, 买个小电暖也起不了多少作用, 屋里水龙头都已经结冰, 我很长时间每天需要吃两包方便面, 但我依然坚持学习, 因为我知道有一天我将不再这样.


    2010年03月 -- 2011年03月, 从后来很多次建议来看, 不得不说老婆很有眼光. 她建议我去北京找工作, 我请了3天假, 再一次来到了北京, 不同于上一次, 我现在有大半年经验, 我翻译过文档, 录制过视频教程, 有一定资本了. 然而, 事情并不是那么顺利, 当时期望的用友并没有通过, 在用友面试完后, 我就觉得自己一无是处. 无奈, 只能退而求其次, 来到一家刚创业的游戏公司. 跟这家公司谈完薪水后, 我先给妈妈打了电话, 5.5k, 已经到了妈妈不能相信的地步. 就这样, 我正式的踏入了北京的土地. 一年中, 我更多的是为公司付出, 自己以javascript研发进入, 后来页面制作也的我搞, php后来我也要做, 服务器我还要搞, 不得不说, 非常锻炼人. 还是前面的态度, 我觉得这种锻炼就是我最大的收获, 从这里开始, 我正式的转向php开发.到2011年3月的时候, 已经觉得公司很不行了, 又碰巧老婆怀孕, 不得不考虑结婚的事情, 因此, 我就辞职, 回家结婚.


    2011年04月 -- 2012年03月, 婚后的生活很好, 我又找到了一份工作, 这家公司相对比较大, 2000+的规模. 不过有一些体制内的特质, 我进入的薪资是6k, 全年能拿到18薪以上, 公司的福利待遇都很完善, 工作也相对轻松, 我的领导人也很好, 技术也很好, 就这样, 在这家公司, 我又开始了自己的学习之路. 我继续每天凌晨2-3点睡觉, 完成了这几年最重要的积累: unix环境高级编程, unix网络编程, php内核和扩展, shell/awk/sed等等最基础的东西. 同样, 在大公司中, 我也学会了更多的团队协作, 同事关系方面的东西. 2012年03月, 公司一位副总跳槽, 就这样, 我们小组集体来到了下一家公司.


    2012年03月 -- 2013年03月, 新的公司, 项目还没有上线, 已有的东西问题诸多, 我们被委以重任, 6.1日上线. 旧的团队存在诸多问题, 士气不振, 技术水平不足. 我们在6.1之前完成了很重要的几件事: 1) 提升团队士气; 2) 整理旧的框架不好的东西; 3) 修改大量的bug; 4) 规范工作流程; 5) 规划未来的技术框架. 虽然后来看做的东西一般, 但在这么短的时间完成这一切, 我觉得实在难得. 虽然我一直自我感觉对自己更多的提升是自己业余时间的学习, 但不可否认, 在这家公司的一年中, 我在团队建设, 团队管理, 团队协作方面也有了质的变化. 在这家公司, 我的薪资得到了很大的提升, 达到了18K, 这是我从来都没有想过的事情. 所以, 我想给诸位职场新人说, 你不要一开始就想要这要那, 只要你做的够好, 终有一天, 你会发现你得到的远比失去的要多.
    后面这两家公司中, 我觉得更重要的是我学会了一种处世方式, 首先学会听别人说话, 然后自己做感悟, 做提升.


    流水的结束, 就是在昨天, 我收到了自己心仪公司的口头offer, 并且也已经给现在的公司提出了离职. 和leader聊了一会儿, 大家都还挺开心.


    在前5年中, 我用的网名是selfimpr, 是self-improvement简写而来, 含义是: 自强不息. 5年中, 我从所有可能激励我的地方去激励自己, 让自己可以一直坚持走到今天. 这几天, 我在考虑, 用一个词总结我的前5年. 我想, 这个词就是"积累".
    这也正是我想给这个行业的后来者说的, "积累", 并且要是不计回报的积累, 因为你一旦太过计较回报, 你的心就很难平静, 往往就会半途而废.
    此外, 还有一点要说的是, 比我基础更差的同学估计也很难找了, 所以, 能不能学有所成, 关键不在你是否有基础, 而在于你付出了多少.


    接下来, 我已经更换了自己的网名goosman, 是从swan goose演化而来, 我不知道"鸿鹄"用英语怎么说, 就用了这个单词, 希望我可以像书中所说, 利用自己前5年的积累, 一展鸿鹄之志.  

    posted @ 2013-03-09 01:28 奋斗成就男人 阅读(185) | 评论 (0)编辑 收藏

    javamail发送邮件

    今天学习了一下JavaMail,javamail发送邮件确实是一个比较麻烦的问题。为了以后使用方便,自己写了段代码,打成jar包,以方便以后使用。呵呵 

    以下三段代码是我的全部代码,朋友们如果想用,直接复制即可。jar包因为我不知道怎么传到javaeye上,所以朋友们回去自己打吧。 
    我的代码有三个类: 
    第一个类:MailSenderInfo.java  
    package com.util.mail;
    /** 
    * 发送邮件需要使用的基本信息 
    */ 
    import java.util.Properties; 
    public class MailSenderInfo { 
    // 发送邮件的服务器的IP和端口 
    private String mailServerHost; 
    private String mailServerPort = "25"; 
    // 邮件发送者的地址 
    private String fromAddress; 
    // 邮件接收者的地址 
    private String toAddress; 
    // 登陆邮件发送服务器的用户名和密码 
    private String userName; 
    private String password; 
    // 是否需要身份验证 
    private boolean validate = false; 
    // 邮件主题 
    private String subject; 
    // 邮件的文本内容 
    private String content; 
    // 邮件附件的文件名 
    private String[] attachFileNames;
    /** 
     * 获得邮件会话属性 
     */ 
    public Properties getProperties(){ 
     Properties p = new Properties(); 
     p.put("mail.smtp.host", this.mailServerHost); 
     p.put("mail.smtp.port", this.mailServerPort); 
     p.put("mail.smtp.auth", validate ? "true" : "false"); 
     return p; 
    public String getMailServerHost() { 
     return mailServerHost; 
    public void setMailServerHost(String mailServerHost) { 
     this.mailServerHost = mailServerHost; 
    }
    public String getMailServerPort() { 
     return mailServerPort; 
    }
    public void setMailServerPort(String mailServerPort) { 
     this.mailServerPort = mailServerPort; 
    }
    public boolean isValidate() { 
     return validate; 
    }
    public void setValidate(boolean validate) { 
     this.validate = validate; 
    }
    public String[] getAttachFileNames() { 
     return attachFileNames; 
    }
    public void setAttachFileNames(String[] fileNames) { 
     this.attachFileNames = fileNames; 
    }
    public String getFromAddress() { 
     return fromAddress; 
    public void setFromAddress(String fromAddress) { 
     this.fromAddress = fromAddress; 
    }
    public String getPassword() { 
     return password; 
    }
    public void setPassword(String password) { 
     this.password = password; 
    }
    public String getToAddress() { 
     return toAddress; 
    public void setToAddress(String toAddress) { 
     this.toAddress = toAddress; 
    public String getUserName() { 
     return userName; 
    }
    public void setUserName(String userName) { 
     this.userName = userName; 
    }
    public String getSubject() { 
     return subject; 
    }
    public void setSubject(String subject) { 
     this.subject = subject; 
    }
    public String getContent() { 
     return content; 
    }
    public void setContent(String textContent) { 
     this.content = textContent; 

    第二个类:SimpleMailSender.java  
    package com.util.mail;

    import java.util.Date; 
    import java.util.Properties;
    import javax.mail.Address; 
    import javax.mail.BodyPart; 
    import javax.mail.Message; 
    import javax.mail.MessagingException; 
    import javax.mail.Multipart; 
    import javax.mail.Session; 
    import javax.mail.Transport; 
    import javax.mail.internet.InternetAddress; 
    import javax.mail.internet.MimeBodyPart; 
    import javax.mail.internet.MimeMessage; 
    import javax.mail.internet.MimeMultipart; 

    /** 
    * 简单邮件(不带附件的邮件)发送器 
    */ 
    public class SimpleMailSender  { 
    /** 
      * 以文本格式发送邮件 
      * 
    @param mailInfo 待发送的邮件的信息 
      
    */ 
        public boolean sendTextMail(MailSenderInfo mailInfo) { 
          // 判断是否需要身份认证 
          MyAuthenticator authenticator = null
          Properties pro = mailInfo.getProperties();
          if (mailInfo.isValidate()) { 
          // 如果需要身份认证,则创建一个密码验证器 
            authenticator = new MyAuthenticator(mailInfo.getUserName(), mailInfo.getPassword()); 
          }
          // 根据邮件会话属性和密码验证器构造一个发送邮件的session 
          Session sendMailSession = Session.getDefaultInstance(pro,authenticator); 
          try { 
          // 根据session创建一个邮件消息 
          Message mailMessage = new MimeMessage(sendMailSession); 
          // 创建邮件发送者地址 
          Address from = new InternetAddress(mailInfo.getFromAddress()); 
          // 设置邮件消息的发送者 
          mailMessage.setFrom(from); 
          // 创建邮件的接收者地址,并设置到邮件消息中 
          Address to = new InternetAddress(mailInfo.getToAddress()); 
          mailMessage.setRecipient(Message.RecipientType.TO,to); 
          // 设置邮件消息的主题 
          mailMessage.setSubject(mailInfo.getSubject()); 
          // 设置邮件消息发送的时间 
          mailMessage.setSentDate(new Date()); 
          // 设置邮件消息的主要内容 
          String mailContent = mailInfo.getContent(); 
          mailMessage.setText(mailContent); 
          // 发送邮件 
          Transport.send(mailMessage);
          return true
          } catch (MessagingException ex) { 
              ex.printStackTrace(); 
          } 
          return false
        } 
        
        /** 
          * 以HTML格式发送邮件 
          * 
    @param mailInfo 待发送的邮件信息 
          
    */ 
        public static boolean sendHtmlMail(MailSenderInfo mailInfo){ 
          // 判断是否需要身份认证 
          MyAuthenticator authenticator = null;
          Properties pro = mailInfo.getProperties();
          //如果需要身份认证,则创建一个密码验证器  
          if (mailInfo.isValidate()) { 
            authenticator = new MyAuthenticator(mailInfo.getUserName(), mailInfo.getPassword());
          } 
          // 根据邮件会话属性和密码验证器构造一个发送邮件的session 
          Session sendMailSession = Session.getDefaultInstance(pro,authenticator); 
          try { 
          // 根据session创建一个邮件消息 
          Message mailMessage = new MimeMessage(sendMailSession); 
          // 创建邮件发送者地址 
          Address from = new InternetAddress(mailInfo.getFromAddress()); 
          // 设置邮件消息的发送者 
          mailMessage.setFrom(from); 
          // 创建邮件的接收者地址,并设置到邮件消息中 
          Address to = new InternetAddress(mailInfo.getToAddress()); 
          // Message.RecipientType.TO属性表示接收者的类型为TO 
          mailMessage.setRecipient(Message.RecipientType.TO,to); 
          // 设置邮件消息的主题 
          mailMessage.setSubject(mailInfo.getSubject()); 
          // 设置邮件消息发送的时间 
          mailMessage.setSentDate(new Date()); 
          // MiniMultipart类是一个容器类,包含MimeBodyPart类型的对象 
          Multipart mainPart = new MimeMultipart(); 
          // 创建一个包含HTML内容的MimeBodyPart 
          BodyPart html = new MimeBodyPart(); 
          // 设置HTML内容 
          html.setContent(mailInfo.getContent(), "text/html; charset=utf-8"); 
          mainPart.addBodyPart(html); 
          // 将MiniMultipart对象设置为邮件内容 
          mailMessage.setContent(mainPart); 
          // 发送邮件 
          Transport.send(mailMessage); 
          return true
          } catch (MessagingException ex) { 
              ex.printStackTrace(); 
          } 
          return false
        } 

    第三个类:MyAuthenticator.java  
    package com.util.mail;

    import javax.mail.*;
      
    public class MyAuthenticator extends Authenticator{
        String userName=null;
        String password=null;
         
        public MyAuthenticator(){
        }
        public MyAuthenticator(String username, String password) { 
            this.userName = username; 
            this.password = password; 
        } 
        protected PasswordAuthentication getPasswordAuthentication(){
            return new PasswordAuthentication(userName, password);
        }
    }

     下面给出使用上面三个类的代码: 
    public static void main(String[] args){
             //这个类主要是设置邮件
          MailSenderInfo mailInfo = new MailSenderInfo(); 
          mailInfo.setMailServerHost("smtp.163.com"); 
          mailInfo.setMailServerPort("25"); 
          mailInfo.setValidate(true); 
          mailInfo.setUserName("han2000lei@163.com"); 
          mailInfo.setPassword("**********");//您的邮箱密码 
          mailInfo.setFromAddress("han2000lei@163.com"); 
          mailInfo.setToAddress("han2000lei@163.com"); 
          mailInfo.setSubject("设置邮箱标题"); 
          mailInfo.setContent("设置邮箱内容"); 
             //这个类主要来发送邮件
          SimpleMailSender sms = new SimpleMailSender();
              sms.sendTextMail(mailInfo);//发送文体格式 
              sms.sendHtmlMail(mailInfo);//发送html格式
        }

    最后,给出朋友们几个注意的地方: 
    1、使用此代码你可以完成你的javamail的邮件发送功能。三个类缺一不可。 
    2、这三个类我打包是用的com.util.mail包,如果不喜欢,你可以自己改,但三个类文件必须在同一个包中 
    3、不要使用你刚刚注册过的邮箱在程序中发邮件,如果你的163邮箱是刚注册不久,那你就不要使用“smtp.163.com”。因为你发不出去。刚注册的邮箱是不会给你这种权限的,也就是你不能通过验证。要使用你经常用的邮箱,而且时间比较长的。 
    4、另一个问题就是mailInfo.setMailServerHost("smtp.163.com");mailInfo.setFromAddress("han2000lei@163.com");这两句话。即如果你使用163smtp服务器,那么发送邮件地址就必须用163的邮箱,如果不的话,是不会发送成功的。  

    posted @ 2013-03-09 01:00 奋斗成就男人 阅读(350) | 评论 (0)编辑 收藏

    JAVA邮件发送的简单实现

         摘要: JAVA MAIL是利用现有的邮件账户发送邮件的工具,比如说,我在网易注册一个邮箱账户,通过JAVA Mail的操控,我可以不亲自登录网易邮箱,让程序自动的使用网易邮箱发送邮件。这一机制被广泛的用在注册激活和垃圾邮件的发送等方面。JavaMail可以到http://www.oracle.com/technetwork/java/javamail/index-138643.html进行下载,并将ma...  阅读全文

    posted @ 2013-03-09 00:29 奋斗成就男人 阅读(312) | 评论 (0)编辑 收藏

    用gmail smtp发送邮件

    import java.util.Properties;
    import javax.mail.Message;
    import javax.mail.Session;
    import javax.mail.Transport;
    import javax.mail.internet.InternetAddress;
    import javax.mail.internet.MimeMessage;

    public class SendMail implements Runnable {
        private final String smtp_host = "smtp.gmail.com";                      
        private final String from_userName = "xx@gmail.com";        
        private final String from_passWord = "xx";                        
        private final String show_name = "xxx";
        
        public String email_address;
        public String email_subject;
        public String email_content;    
        
        public SendMail(String email_address, String email_subject, String email_content) {
            this.email_address = email_address;
            this.email_subject = email_subject;
            this.email_content = email_content;
        }

        public void run() {
            executeMailSend(email_address, email_subject, email_content);
        }
        
        /**
         * 
         * 
    @param recipients: the mail send to
         * 
    @param sendSubject: the mail subject
         * 
    @param sendText: the mail content
         
    */
        public void executeMailSend(String recipients, String sendSubject, String sendText) {
            
            try {            
                Properties props = System.getProperties();
                props.put("mail.smtp.starttls.enable", "true");
                props.put("mail.smtp.host", smtp_host);
                props.put("mail.smtp.user", from_userName);
                props.put("mail.smtp.password", from_passWord);
                props.put("mail.smtp.port", "587");  //gmail smtp port 587
                props.put("mail.smtp.auth", "true");
                

                
                Session session = Session.getDefaultInstance(props, null);
                session.setDebug(false);
                
                MimeMessage message = new MimeMessage(session);
                message.setFrom(new InternetAddress(from_userName));
                message.addRecipient(Message.RecipientType.TO, new InternetAddress(recipients));
                message.setFrom(new InternetAddress(show_name + "<" + from_userName + ">"));    
                message.setSubject(sendSubject);
                message.setContent(sendText, "text/html;charset=utf-8");            
                
                Transport transport = session.getTransport("smtp");
                transport.connect(smtp_host, from_userName, from_passWord);
                transport.sendMessage(message, message.getAllRecipients());
                transport.close();
                
                System.out.println("send an email to " + recipients + " success");
            } catch (Exception e) {
                e.printStackTrace();
                System.out.println("failure! ");

            }
        }
        public static void main (String args[]){
            new SendMail("yy@gmail.com","test","hehe").run();
        }
    }
    结果老是报如下的错误
    javax.mail.MessagingException: 530 5.7.0 Must issue a STARTTLS command first. 36sm443504yxh.67
    failure! 

        at com.sun.mail.smtp.SMTPTransport.issueCommand(SMTPTransport.java:1020)
        at com.sun.mail.smtp.SMTPTransport.mailFrom(SMTPTransport.java:716)
        at com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:388)
        at SendMail.executeMailSend(SendMail.java:59)
        at SendMail.run(SendMail.java:25)
        at SendMail.main(SendMail.java:70)
     折腾了个把小时,苦苦寻求后发现一个解决办法 
    props.put("mail.smtp.port""587");  
    替换成
    props.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); 
    props.setProperty("mail.smtp.socketFactory.fallback", "false"); 
    props.setProperty("mail.smtp.port", "465"); 
    props.setProperty("mail.smtp.socketFactory.port", "465"); 
    究其原因也不太清楚,网上有资料说port 587也可以,不知结果不行
    把上述代码中的 

    posted @ 2013-03-08 15:16 奋斗成就男人 阅读(1122) | 评论 (0)编辑 收藏

    Json-lib使用——JSONObject与JSONArray

    1.从Object到String
     要先用Object对象构造一个JSONObject或者JSONArray对象,然后调用它的toString()方法即可

    (1)示例一

    1 Book book=new Book();
    2 book.setName("Java");
    3 book.setPrice(52.3f);
    4 JSONObject object=JSONObject.fromObject(book);
    5 System.out.println(object.toString());

    (2)示例二

    复制代码
     1         Book book=new Book();
    2 book.setName("Java");
    3 book.setPrice(52.3f);
    4
    5 Book book2=new Book();
    6 book2.setName("C");
    7 book2.setPrice(42.3f);
    8 List list=new ArrayList();
    9 list.add(book);
    10 list.add(book2);
    11 JSONArray arry=JSONArray.fromObject(list);
    12 System.out.println(arry.toString());
    13 //结果如下:
    14 [{"name":"Java","price":52.3},{"name":"C","price":42.3}]
    复制代码

    2.从String到Object
     要先用String对象构造一个JSONObject或者JSONArray对象
    (1)示例一 

    1 String json="{name:'Java',price:52.3}";    
    2 JSONObject object=JSONObject.fromObject(json);
    3 System.out.println(object.get("name")+" "+object.get("price"));

    (2)示例二

    复制代码
    1 String json="[{name:'Java',price:52.3},{name:'C',price:42.3}]";
    2 JSONArray array=JSONArray.fromObject(json);
    3 for(int i=0;i<array.size();i++){
    4 Map o=(Map)array.get(i);
    5 System.out.println(o.get("name")+" "+o.get("price"));
    6 }
    复制代码

    3.从String到Bean

    (1)单个Bean对象

    1         String json="{name:'Java',price:52.3}";
    2 JSONObject object=JSONObject.fromObject(json);
    3 Product product=(Product)JSONObject.toBean(object,Product.class);
    4 System.out.println(product.getName()+" "+product.getPrice());

    (2).Bean的数组

    复制代码
    1         String json="[{name:'Java',price:52.3},{name:'C',price:42.3}]";
    2 JSONArray array=JSONArray.fromObject(json);
    3 Product[] products=(Product[]) JSONArray.toArray(array,Product.class);
    4 for(Product p:products){
    5 System.out.println(p.getName()+" "+p.getPrice());
    6 }
    复制代码

    自定义封装JSON操作的类

    复制代码
     1 package com.util;
    2
    3 import java.util.List;
    4 import java.util.Map;
    5
    6 import net.sf.json.JSONArray;
    7 import net.sf.json.JSONObject;
    8
    9 public class JsonHelper {
    10 //从普通的Bean转换为字符串
    11 public static String getJson(Object o){

    12 JSONObject jo=JSONObject.fromObject(o);
    13 return jo.toString();
    14 }
    15 //从Java的列表转换为字符串
    16 public static String getJson(List list){

    17 JSONArray ja=JSONArray.fromObject(list);
    18 return ja.toString();
    19 }
    20 //从Java对象数组转换为字符串
    21 public static String getJson(Object[] arry){

    22 JSONArray ja=JSONArray.fromObject(arry);
    23 return ja.toString();
    24 }
    25 //从json格式的字符串转换为Map对象
    26 public static Map getObject(String s){

    27 return JSONObject.fromObject(s);
    28 }
    29 //从json格式的字符串转换为List数组
    30 public static List getArray(String s){

    31 return JSONArray.fromObject(s);
    32 }
    33 //从json格式的字符串转换为某个Bean
    34 public static Object getObject(String s,Class cls){

    35 JSONObject jo=JSONObject.fromObject(s);
    36 return JSONObject.toBean(jo, cls);
    37 }
    38 //从json格式的字符串转换为某类对象的数组
    39 public static Object getArray(String s,Class cls){

    40 JSONArray ja=JSONArray.fromObject(s);
    41 return JSONArray.toArray(ja, cls);
    42 }
    43 }





    posted @ 2013-03-04 15:22 奋斗成就男人 阅读(781) | 评论 (0)编辑 收藏

    Java日志管理:Logger.getLogger()和LogFactory.getLog()的区别(详解Log4j)

         摘要: 第一、Logger.getLogger()和LogFactory.getLog()的区别    1.Logger.getLogger()是使用log4j的方式记录日志;    2.LogFactory.getLog()则来自apache的common-logging包。common-logging组件: &n...  阅读全文

    posted @ 2012-12-26 00:45 奋斗成就男人 阅读(6038) | 评论 (0)编辑 收藏

    log4j配置日志

    懂行的人都知道,log4j日志是个很基础的东东,与struts这种高层框架无关,只与web开发了的tomcat有关。这里之所以写出struts,是因为笔者一开始用struts的时候,以为是这样,也是这样google的。好了,言归正传,开工了
    给tomcat配置log4j有好几种方法,我知道的有:
    一、tomcat级别的统一日志管理(没有实际验证过,只是查了资料):
    在tomcat的common/lib下增加log4j的.jar包,以便程序使用的时候,能够加载到。
    在自己的webapps的WEB-INF/classes下添加log4j.properties配置,所有的东西都是自动的
     
    这种方式的缺点很明显,一个tomcat可能会多个子webapps,都统一到一个日志下,非常不便于管理。所以重点看下面
     
    二、每个webapp分别配置log4j(切实可行的实践经验)
    1、在自己youapp的WEB-INF/lib下增加log4j-xxx.jar文件
    2、自己写一个servlet,初始化log4j的相关配置信息:
    Java代码
    import javax.servlet.ServletException;  
    import javax.servlet.ServletRequest;  
    import javax.servlet.ServletResponse;  
    import javax.servlet.http.HttpServlet;  
    import org.apache.log4j.PropertyConfigurator;  
      
    public class Log4jInitServlet extends HttpServlet {  
        public void service(ServletRequest req, ServletResponse resp) throws ServletException, IOException {          
        }  
          
        public void init() throws ServletException {  
            System.setProperty("webappRoot", getServletContext().getRealPath("/"));       
            PropertyConfigurator.configure(getServletContext().getRealPath("/") + getInitParameter("configfile"));  
        }  
    }  
     3、修改web.xml文件,让tomcat启动你app的时候自动加载刚才这个servlet:
    Xml代码
    <!-- initialize log4j -->  
    <servlet>  
        <servlet-name>log4j config file</servlet-name>  
        <servlet-class>com.keepc.util.Log4jInitServlet</servlet-class>  
        <init-param>  
            <param-name>configfile</param-name>  
            <param-value>/WEB-INF/classes/log4j.properties</param-value>  
        </init-param>  
          
        <load-on-startup>1</load-on-startup>  
    </servlet>  
     4、在youapp/WEB-INF/classes先新建log4j.properties文件,内容如下:
    log4j.rootLogger=debug, A1

    log4j.appender.A1=org.apache.log4j.DailyRollingFileAppender
    log4j.appender.A1.file=${webappRoot}/logs/youapp_log-
    log4j.appender.A1.DatePattern=yyyy-MM-dd'.log'
    log4j.appender.A1.layout=org.apache.log4j.PatternLayout
    log4j.appender.A1.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss, SSS}[%c]-[%p] %m%n
    5、重新启动tomcat,即可在你的youapp应用目录下看到logs目录和对应的log文件
    #:这里说道的webapp目录是指:c:\program files\tomcat\webapps\youapp目录
    6、在你的app目录下创建一个jsp做下测试:
    Html代码
    <%@ page contentType="text/html; charset=GBK" language="java" import="org.apache.log4j.Logger,java.util.*"%>  
    <html>  
    <head>  
    <link href="style/reg.css" rel="stylesheet" type="text/css">  
    <title>测试页面</title>  
    </head>  
    <body>  
      
    <%  
    Logger log = Logger.getLogger("test.jsp");  
    log.debug("测试日志,哈哈");  
    %>  
      
    </body>  
      
    </html>  
    在你的浏览器调用下这个jsp,就可以看到日志内容了。
     
    本方法在windows和linux下都通用,完全一样。
    只与log4j.properties的详细配置方法,网上随便google下都有一箩筐,照抄就是了。

    posted @ 2012-12-25 00:52 奋斗成就男人 阅读(1052) | 评论 (0)编辑 收藏

    SVN的服务器的配置

        
        一: SVN包括:服务器端(Subversion)和客服端(TortoiseSVN),安装时,建议先安装服务器端,再安装客服端(因为安装完客服端后需要重启电脑)。

        二:安装完成后,创建服务器版本库:创建一个文件夹(比如:D:\\svnserver),然后右键:TortoiseSVN ----> create respository here,然后在该目录下生成六个文件(conf文件           夹、 db文件夹、hooks文件夹、locks文件夹、format文件和README.txt),其中配置文件在conf文件夹中。 其中conf文件夹下包含三个文件:authz(配置用户权限:读,写权限         等 等)、
        passwd(配置用户名和密码)和svnserve.conf(svn的核心配置)。
        其中:
        1: passwd配置:在该文件中,创建用户的方式为:  用户名 = 密码 ,例如:创建用户名为:admin,密码为abcd,即为:admin = abcd
        2: svnserve.conf配置:开启用户访问的功能:即只需开启: password-db = passwd 即可,具体操作:把password-db = passwd 前面的#去除即可。否则其他用户不能访问。
                                        开启用户权限的功能:即只需开启: authz-db = authz 即可,具体操作:把authz-db = authz  前面的#去除即可。否则配置的用户权限将不生效。 
          
        3:authz 配置:找到该文件的 [groups] :在下一行:有两种方式配置权限:
             (1): 权限名称  = 用户名  ,然后在相应的目录: 权限名称 = 权限(比如:rw)例如: 
                        [groups]                -- 给权限分组,有利于多个用户批量分配权限。
                        adm = admin         -- adm 为组权限名称,类似常说的“角色”,admin为用户名,= 前后最后加上一个空格。  
                        [/]                        -- / 表示svn服务器的跟目录下,当然也可以用其他的目录。比如:[/a/b/] 表示为/a/b/ 目录下分配目录权限
                        @adm = rw           -- @表示组, adm表示组名,r表示只读,即下载功能;r表示只写,即上传功能。
             (2):直接在相应的目录下:用户名 = 权限(比如:rw) 例如: 
                       admin = rw            -- admin 为用户名,rw表示读写权限。
       如果 svnserve.conf 的authz-db = authz 不开启。则权限分配则无效。当然这样用户也是可以上传和下载的。
       三:开启SVN服务:
       (1):临时开启,在dos界面中输入: svnserver  -d -r + svn服务器版本库目录  例如:svn版本库目录为:D:\\svnserver ,即为:
                   svnserver  -d -r D:\\svnserver           -- 注意:-d, -r ,svn服务器版本库目录中间需要用空格隔开。而一旦关闭dos界面是,svn服务器也随之关闭。
       (2):永久开启:即电脑启动时自动开启svn服务器。这样需要把svn创建一个服务,然后把该服务器设置为自动启动即可。具体操作:
                 (i) : 创建服务:在dos界面中输入:
                 sc create svnserver binpath= svnserve.exe目录 --service --root svn版本库目录                -- 注意:=与svnserve.exe之间必须要加一个空格
                 例如svn服务器安装在:D:\J2EE\SVN\Subversion目录下
                 则为: sc create svnserver binpath= "D:\J2EE\SVN\Subversion\bin\svnserve.exe --service --root  D:\\svnserver"     -- 双引号不可缺少
                然后:如果创建服务没有问题,则输入:services.msc 到电脑服务列表中会找到一个:svnserve服务。如果创建svn服务失败,则无法找到svnserve服务。 
                如果创建svn服务出现了问题,还可以删除svn服务。具体如: sc delete 服务名        例如: sc delete svnserver
               (ii)把svnserve服务设置为自动启动。以后电脑启动时即启动svn服务器。
      四: 这样svn服务器就配置好了。然后就可以在svn客服端进行各种操作了。

         顺便说一下: 创建服务:sc create 服务名 binpath=  程序启动的位置 --service --root      
                               
    -- 程序启动位置即:该软件启动的那个文件的位置(如:d:\xx\xxx\xxxx.exe)
                           删除服务:sc delete 服务名

    posted @ 2012-12-21 01:02 奋斗成就男人 阅读(1348) | 评论 (0)编辑 收藏

    用java实现验证码

    <%@ page contentType="image/jpeg" import="java.awt.*,java.awt.image.*,java.util.*,javax.imageio.*" %>
    <%!
    Color getRandColor(int fc,int bc){//给定范围获得随机颜色
      Random random = new Random();
      if(fc>255) fc=255;
      if(bc>255) bc=255;
      int r=fc+random.nextInt(bc-fc);
      int g=fc+random.nextInt(bc-fc);
      int b=fc+random.nextInt(bc-fc);
      return new Color(r,g,b);
      }
    %>
    <%
    //设置页面不缓存
    response.setHeader("Pragma","No-cache");
    response.setHeader("Cache-Control","no-cache");
    response.setDateHeader("Expires", 0);

    // 在内存中创建图象
    int width=60, height=20;
    BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

    // 获取图形上下文
    Graphics g = image.getGraphics();

    //生成随机类
    Random random = new Random();

    // 设定背景色
    g.setColor(getRandColor(200,250));
    g.fillRect(0, 0, width, height);

    //设定字体
    g.setFont(new Font("Times New Roman",Font.PLAIN,18));


    // 随机产生155条干扰线,使图象中的认证码不易被其它程序探测到
    g.setColor(getRandColor(160,200));
    for (int i=0;i<155;i++)
    {
      int x = random.nextInt(width);
      int y = random.nextInt(height);
      int xl = random.nextInt(12);
      int yl = random.nextInt(12);
      g.drawLine(x,y,x+xl,y+yl);
    }

    // 取随机产生的认证码(4位数字)

    String codeList = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890";

    String sRand="";


    for (int i=0;i<4;i++){
    int a=random.nextInt(codeList.length()-1);
      String rand=codeList.substring(a,a+1);
      sRand+=rand;
      // 将认证码显示到图象中
      g.setColor(new Color(20+random.nextInt(110),20+random.nextInt(110),20+random.nextInt(110)));//调用函数出来的颜色相同,可能是因为种子太接近,所以只能直接生成
      g.drawString(rand,13*i+6,16);
    }

    // 将认证码存入SESSION
    session.setAttribute("rand",sRand);

    // 图象生效
    g.dispose();

    // 输出图象到页面
    ImageIO.write(image, "JPEG", response.getOutputStream());
    out.clear();
    out = pageContext.pushBody();


    %> 

    posted @ 2012-11-14 23:34 奋斗成就男人 阅读(182) | 评论 (0)编辑 收藏

    HttpClient使用

    背景:因为想写一个测试tomcat连接的程序,就试试自已去构造Http请求。找了一下发现Apache下有一个比较成熟的轮子HttpComponets.

     

    使用库:Apache Http Client

    HttpClient是一个代码级的Http客户端工具,可以使用它模拟浏览器向Http服务器发送请求。

    其中HttpClient是HttpComponents项目其中的一部份,HttpComponents简称为hc.

    http://hc.apache.org/

    使用HttpClient还需要HttpCore.这里其中包括Http请求与Http响应的代码封装。

     

    现在导入两个jar包:

    httpclient-4.0.jar

    httpcore-4.0.jar

    httpmime-4.0.jar

     

    开始一个请求代码如下:

    Java代码 复制代码 收藏代码
    1. HttpClient httpClient = new DefaultHttpClient();   
    2. //构造请求,如果想使用POST则new一个HttpPost   
    3.         HttpGet get = new HttpGet("http://www.iteye.com");   
    4.         HttpResponse response = httpClient.execute(get);   
    5. //先从响应头得到实体   
    6.         HttpEntity entity = response.getEntity();      
    7. //得到实体输入流   
    8.         InputStream inSm = entity.getContent();   
    9.         Scanner inScn = new Scanner(inSm);   
    10.         while(inScn.hasNextLine()){   
    11.             System.out.println(inScn.nextLine());   
    12.         }   
    13.         entity.consumeContent();  
    HttpClient httpClient = new DefaultHttpClient(); //构造请求,如果想使用POST则new一个HttpPost 		HttpGet get = new HttpGet("http://www.iteye.com"); 		HttpResponse response = httpClient.execute(get); //先从响应头得到实体 		HttpEntity entity = response.getEntity();	 //得到实体输入流 		InputStream inSm = entity.getContent(); 		Scanner inScn = new Scanner(inSm); 		while(inScn.hasNextLine()){ 			System.out.println(inScn.nextLine()); 		} 		entity.consumeContent();

     

    这个是在HC例子中有代码作了少量的修改。

    输出:

    Java代码 复制代码 收藏代码
    1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">   
    2. <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="zh-CN" dir="ltr">   
    3.   <head>   
    4.     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>   
    5.     <title>JavaEye Java编程 Spring框架 AJAX技术 Agile敏捷软件开发 ruby on rails实践 - JavaEye做最棒的软件开发交流社区</title>   
    6.     <meta name="description" content="Java编程,Spring Struts Webwork框架深入,XMLHTTP AJAX开发,Java Web开发,Java企业应用,Java设计模式,Java开源框架,Java应用服务器,Rich Client讨论,Ruby编程,Ruby DSL开发,Ruby on rails实践,JavaScript编程,敏捷软件开发XP TDD,软件配置管理,软件测试,项目管理UML,数据库,C#/.net C/C++ Erlang/FP PHP/Linux平台,精通Hibernate" />   
    7.     <meta name="keywords"  content="Java编程 Spring框架 AJAX技术 Agile敏捷软件开发 ruby on rails实践 JavaEye深度技术社区" />   
    8.     <link rel="shortcut icon" href="/images/favicon.ico" type="image/x-icon" />   
    9.     <link href="/rss" rel="alternate" title="JavaEye技术网站RSS频道订阅" type="application/rss+xml" />   
    10.     <link href="http://www.iteye.com/stylesheets/homepage.css?1263389049" media="screen" rel="stylesheet" type="text/css" />   
    11.        
    12.   </head>   
    13.   
    14. ...省略,证明以上代码已经成功  
    <!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" xml:lang="zh-CN" dir="ltr">   <head>     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>     <title>JavaEye Java编程 Spring框架 AJAX技术 Agile敏捷软件开发 ruby on rails实践 - JavaEye做最棒的软件开发交流社区</title>     <meta name="description" content="Java编程,Spring Struts Webwork框架深入,XMLHTTP AJAX开发,Java Web开发,Java企业应用,Java设计模式,Java开源框架,Java应用服务器,Rich Client讨论,Ruby编程,Ruby DSL开发,Ruby on rails实践,JavaScript编程,敏捷软件开发XP TDD,软件配置管理,软件测试,项目管理UML,数据库,C#/.net C/C++ Erlang/FP PHP/Linux平台,精通Hibernate" />     <meta name="keywords"  content="Java编程 Spring框架 AJAX技术 Agile敏捷软件开发 ruby on rails实践 JavaEye深度技术社区" />     <link rel="shortcut icon" href="/images/favicon.ico" type="image/x-icon" />     <link href="/rss" rel="alternate" title="JavaEye技术网站RSS频道订阅" type="application/rss+xml" />     <link href="http://www.iteye.com/stylesheets/homepage.css?1263389049" media="screen" rel="stylesheet" type="text/css" />        </head>  ...省略,证明以上代码已经成功

     当然这个只是大刀一小试。现在还离我的目标差一点点:

    需要做个头,我还不太清楚有什么头可以使用,那样我又写了个程序看看IE的头到底是怎样子的,

    没有抓包程序,只好自已写个程序:

     

    Java代码 复制代码 收藏代码
    1. ServerSocket socketServer = new ServerSocket(10086);   
    2. Socket client = socketServer.accept();   
    3. InputStream inClient = client.getInputStream();   
    4. Scanner inScn = new Scanner(inClient);   
    5. while(inScn.hasNextLine()){   
    6.     System.out.println(inScn.nextLine());   
    7. }   
    8. inScn.close();   
    9. client.close();   
    10. socketServer.close();  
    		ServerSocket socketServer = new ServerSocket(10086); 		Socket client = socketServer.accept(); 		InputStream inClient = client.getInputStream(); 		Scanner inScn = new Scanner(inClient); 		while(inScn.hasNextLine()){ 			System.out.println(inScn.nextLine()); 		} 		inScn.close(); 		client.close(); 		socketServer.close();

     

    在IE地址栏上输入:

    http://locahost:10086/

    点确定后可以得到程序输出:

     

    Java代码 复制代码 收藏代码
    1. GET / HTTP/1.1  
    2. Accept: image/jpeg, application/x-ms-application, image/gif, application/xaml+xml, image/pjpeg, application/x-ms-xbap, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-shockwave-flash, */*   
    3. Accept-Language: zh-CN   
    4. User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; QQWubi 87; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0)   
    5. Accept-Encoding: gzip, deflate   
    6. Host: localhost:10086  
    7. Connection: Keep-Alive  
    GET / HTTP/1.1 Accept: image/jpeg, application/x-ms-application, image/gif, application/xaml+xml, image/pjpeg, application/x-ms-xbap, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-shockwave-flash, */* Accept-Language: zh-CN User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; QQWubi 87; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0) Accept-Encoding: gzip, deflate Host: localhost:10086 Connection: Keep-Alive

     

    分析请求包中这六个头信息。可以参考以下文章:

    http://zsxxsz.iteye.com/blog/568250

     

    现在我使用HC模拟IE的请求,修改后代码如下:

    Java代码 复制代码 收藏代码
    1. HttpClient httpClient = new DefaultHttpClient();   
    2.         HttpGet get = new HttpGet("http://www.iteye.com");   
    3.            
    4.         get.setHeader("Accept", "image/jpeg, application/x-ms-application, image/gif, application/xaml+xml, image/pjpeg, application/x-ms-xbap, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-shockwave-flash, */*");   
    5.         get.setHeader("Accept-Language","zh-CN");   
    6.         get.setHeader("User-Agent","Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; QQWubi 87; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0)");   
    7.         get.setHeader("Accept-Encoding","gzip, deflate");   
    8.         get.setHeader("Host","you never be know");   
    9.         get.setHeader("Connection","Keep-Alive");   
    10.            
    11.         HttpResponse response = httpClient.execute(get);  

    posted @ 2012-11-08 02:45 奋斗成就男人 阅读(609) | 评论 (0)编辑 收藏

    HTTP 协议简介

    一、TCP/IP 协议介绍

      在介绍 HTTP 协议之前,先简单说一下TCP/IP协议的相关内容。TCP/IP协议是分层的,从底层至应用层分别为:物理层、链路层、网络层、传输层和应用层,如下图所示:

     

     

    TCP/IP基础--层次图

     

      从应用层至物理层,数据是一层层封装,封装的方式一般都是在原有数据的前面加一个数据控制头,数据封装格式如下:

     

    TCP/IP基础--数据封装

     

      其中,对于TCP传输协议,客户端在于服务器建立连接前需要经过TCP三层握手,过程如下:

     

    TCP/IP基础--TCP三次握手

     

    二、HTTP协议

    2.1 简介

      超文本传输协议(Hypertext Transfer Protocol,简称HTTP)是应用层协议,自 1990 年起,HTTP 就已经被应用于 WWW 全球信息服务系统。
      HTTP 是一种请求/响应式的协议。一个客户机与服务器建立连接后,发送一个请求给服务器;服务器接到请求后,给予相应的响应信息。
      HTTP 的第一版本 HTTP/0.9是一种简单的用于网络间原始数据传输的协议;
      HTTP/1.0由 RFC 1945 定义 ,在原 HTTP/0.9 的基础上,有了进一步的改进,允许消息以类 MIME 信息格式存 在,包括请求/响应范式中的已传输数据和修饰符等方面的信息;
      HTTP/1.1(RFC2616) 的要求更加严格以确保服务的可靠性,增强了在HTTP/1.0 没有充分考虑到分层代理服务器、高速缓冲存储器、持久连接需求或虚拟主机等方面的效能;
      安全增强版的 HTTP (即S-HTTP或HTTPS),则是HTTP协议与安全套接口层(SSL)的结合,使HTTP的协议数据在传输过程中更加安全。

     

    2.2 协议结构

      HTTP协议格式也比较简单,格式如下:

     

     

    HTTP协议--协议结构

     

    2.3 HTTP 协议举例

      下面是一个HTTP请求及响应的例子:

     

    2.4 请求头格式

    a) 通用头(general-header):
    Cache-Control:客户端希望服务端如何缓存自己的请求数据,如"Cache-Control: no-cache","Cache-Control: max-age=0";
    Connection:客户端是否希望与服务端之间保持长连接,如"Connection: close", "Connection: keep-alive";
    Date:只有当请求方法为POST或PUT方法时客户端才可能会有些字段;
    Pragma:包含了客户端一些特殊请求信息,如 "Pragma: no-cache" 客户端希望代理或应用服务器不应缓存与该请求相关的结果数据;
    Via:一般用在代理网关向应用服务器发送的请求头中,表明该来自客户端的请求经过了网关代理,
         格式为:"Via: 请求协议版本 网关标识   [其它信息] ",
         如 :" Via: 1.1  webcache_250_199.hexun.com:80 (squid)"

     

    b) 请求头(request-header):
    Accept:表明客户同端可接受的请求回应的媒体类型范围列表。星号“*”用于按范围将类型分组,用“*/*”指示可接受全部类型;用“type/*”指示可接受 type类型的所有子类型,如“ Accept: image/gif, image/jpeg, */*”;
    Accept-Charset:客户端所能识别的字符集编码格式,格式:“Accept-Charset: 字符集1[:权重],字符集2[:权重]”,如:“ Accept-Charset: iso-8859-5, unicode-1-1;q=0.8”;
    Accept-Language:客户端所能识别的语言,格式:“Accept-Language: 语言1[:权重],语言2[:权重]”,如:” Accept-Language: zh, en;q=0.7”;
    Host:客户请求的主机域名或主机IP,格式:“Host: 域名或IP[:端口号]”,如:“Host: www.hexun.com:80“,请求行中若有HTTP/1.1则必须有该请求头;
    User-Agent:表明用户所使用的浏览器标识,主要用于统计的目的;
    Referer:指明该请求是从哪个关联连接而来;

    Accept-Encoding:客户端所能识别的编码压缩格式,如:“Accept-Encoding: gzip, deflate”;
    If- Modified-Since:该字段与客户端缓存相关,客户端所访问的URL自该指定日期以来在服务端是否被修改过,如果修改过则服务端返回新的修改后的信息,如果未修改过则服务器返回304表明此请求所指URL未曾修改过,如:“If-Modified-Since: Fri, 2 Sep 2006 19:37:36 GMT”;
    If-None-Match:该字段与客户端缓存相关,客户端发送URL请求的同时发送该字段及标识,如果服务端的标识与客户端的标识一致,则返回304表明此URL未修改过,如果不一致则服务端返回完整的数据信息,如:“If-None-Match: 0f0a893aad8c61:253, 0f0a893aad8c61:252, 0f0a893aad8c61:251”;
    Cookie:为扩展字段,存储于客户端,向同一域名的服务端发送属于该域的cookie,如:“Cookie: MailUserName=whouse”;

     

    c) 实体头(entity-header): (此类头存在时要求有数据体)
    Content-Encoding:客户端所能识别的编码压缩格式,如:“Content-Encoding: gzip, deflate”;
    Content-Length:客户端以POST方法上传数据时数据体部分的内容长度,如:“ Content-Length: 24”;
    Content- Type:客户端发送的数据体的内容类型,如:“Content-Type: application/x-www-form-urlencoded”为以普通的POST方法发送的数据;“Content-Type: multipart/form-data; boundary=---------------------------5169208281820”,则表明数据体由多部分组成,分隔符为 “-----------------------------5169208281820”;

     

    2.5)响应格式

    a) 通用头(general-header):
    Cache- Control:服务端要求中间代理及客户端如何缓存自己响应的数据,如“Cache-Control: no-cache”,如:“Cache-Control: private” 不希望被缓存,“Cache-Control: public” 可以被缓存;
    Connection:服务端是否希望与客户端之间保持长连接,如“Connection: close”, “Connection: keep-alive”;
    Date:只有当请求方法为POST或PUT方法时客户端才可能会有些字段;
    Pragma:包含了服务端一些特殊响应信息,如 “Pragma: no-cache” 服务端希望代理或客户端不应缓存结果数据;
    Transfer-Encoding:服务端向客户端传输数据所采用的传输模式(仅在HTTP1.1中出现),如:“Transfer-Encoding: chunked”,注:该字段的优先级要高于“Content-Length” 字段的优先级;

     

    b)响应头(response-header):
    Accept-Ranges:表明服务端接收的数据单位,如:“Accept-Ranges: bytes”, ;
    Location:服务端向客户端返回此信息以使客户端进行重定向,如:“Location: http://www.hexun.com”;
    Server:服务端返回的用于标识自己的一些信息,如:“ Server: Microsoft-IIS/6.0”;
    ETag:服务端返回的响应数据的标识字段,客户端可根据此字段的值向服务器发送某URL是否更新的信息;

     

    c)实体头(entity-header): (此类头存在时要求有数据体)
    Content-Encoding:服务端所响应数据的编码格式,如:“Content-Encoding: gzip”;
    Content-Length:服务端所返回数据的数据体部分的内容长度,如:“ Content-Length: 24”;
    Content-Type:服务端所返回的数据体的内容类型,如:“Content-Type: text/html; charset=gb2312” ;
    Set-Cookie:服务端返回给客户端的cookie数据,如:“ Set-Cookie: ASP.NET_SessionId=icnh2ku2dqlmkciyobgvzl55; path=/”

     

    2.6)服务器返回状态码

    1xx:表明服务端接收了客户端请求,客户端继续发送请求;
    2xx:客户端发送的请求被服务端成功接收并成功进行了处理;
    3xx:服务端给客户端返回用于重定向的信息;
    4xx:客户端的请求有非法内容;
    5xx:服务端未能正常处理客户端的请求而出现意外错误。

     

    举例:

    “100”  ; 服务端希望客户端继续;
    “200”  ; 服务端成功接收并处理了客户端的请求;
    “301”  ; 客户端所请求的URL已经移走,需要客户端重定向到其它的URL;
    “304”  ; 客户端所请求的URL未发生变化;
    “400”  ; 客户端请求错误;
    “403”  ; 客户端请求被服务端所禁止;
    “404”  ; 客户端所请求的URL在服务端不存在;
    “500”  ; 服务端在处理客户端请求时出现异常;
    “501”  ; 服务端未实现客户端请求的方法或内容;
    “502”  ; 此为中间代理返回给客户端的出错信息,表明服务端返回给代理时出错;
    “503”  ; 服务端由于负载过高或其它错误而无法正常响应客户端请求;
    “504”  ; 此为中间代理返回给客户端的出错信息,表明代理连接服务端出现超时。

     

    2.7)chunked 传输

      编码使用若干个Chunk组成,由一个标明长度为0的chunk结束,每个Chunk有两部分组成,第一部分是该Chunk的长度(以十六进制表示)和长度单位(一般不写),第二部分就是指定长度的内容,每个部分用CRLF隔开。在最后一个长度为0的Chunk中的内容是称为footer的内容,是一些没有写的头部内容。另外,在HTTP头里必须含有:” Transfer-Encoding: chunked” 通用头字段。格式如下:

    chunked 传输

     

    2.8)HTTP 请求方法

    GET、POST、HEAD、CONNECT、PUT、DELETE、TRACE

     

    2.9)举例

    a)GET请求

    Html代码 复制代码 收藏代码

    1. GET http://photo.test.com/inc/global.js HTTP/1.1   
    2. Host: photo.test.com   
    3. User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; zh-CN; rv:1.8.1) Gecko/20061010 Firefox/2.0   
    4. Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5   
    5. Accept-Language: en-us,zh-cn;q=0.7,zh;q=0.3   
    6. Accept-Encoding: gzip,deflate   
    7. Accept-Charset: gb2312,utf-8;q=0.7,*;q=0.7   
    8. Keep-Alive: 300   
    9. Proxy-Connection: keep-alive   
    10. Cookie: ASP.NET_SessionId=ey5drq45lsomio55hoydzc45  
    11. Cache-Control: max-age=0  

    GET http://photo.test.com/inc/global.js HTTP/1.1

    User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; zh-CN; rv:1.8.1) Gecko/20061010 Firefox/2.0

    Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5

    Accept-Language: en-us,zh-cn;q=0.7,zh;q=0.3

    Accept-Charset: gb2312,utf-8;q=0.7,*;q=0.7

    Cookie: ASP.NET_SessionId=ey5drq45lsomio55hoydzc45

     

    b)POST请求

    Html代码 复制代码 收藏代码

    1. POST / HTTP/1.1   
    2. Accept: image/gif, image/x-xbitmap, image/jpeg, application/vnd.ms-powerpoint, application/msword, */*   
    3. Accept-Language: zh-cn   
    4. Content-Type: application/x-www-form-urlencoded   
    5. Accept-Encoding: gzip, deflate   
    6. User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)   
    7. Host: www.test.com   
    8. Content-Length: 24   
    9. Connection: Keep-Alive   
    10. Cache-Control: no-cache   
    11.   
    12. name=value&submitsubmit=submit  

    Accept: image/gif, image/x-xbitmap, image/jpeg, application/vnd.ms-powerpoint, application/msword, */*

    Content-Type: application/x-www-form-urlencoded

    User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)

     

    c)通过HTTP代理发送GET请求

    Html代码 复制代码 收藏代码

    1. GET http://mail.test.com/ HTTP/1.1   
    2. Host: mail.test.com   
    3. User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; zh-CN; rv:1.8.1) Gecko/20061010 Firefox/2.0   
    4. Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5   
    5. Accept-Language: en-us,zh-cn;q=0.7,zh;q=0.3   
    6. Accept-Encoding: gzip,deflate   
    7. Accept-Charset: gb2312,utf-8;q=0.7,*;q=0.7   
    8. Keep-Alive: 300   
    9. Proxy-Connection: keep-alive  

    GET http://mail.test.com/ HTTP/1.1

    User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; zh-CN; rv:1.8.1) Gecko/20061010 Firefox/2.0

    Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5

    Accept-Language: en-us,zh-cn;q=0.7,zh;q=0.3

    Accept-Charset: gb2312,utf-8;q=0.7,*;q=0.7

     

    d)POST方式上传文件

    Html代码 复制代码 收藏代码

    1. POST http://www.test.comt/upload_attach?uidl=%3C HTTP/1.1   
    2. Host: www.test.com   
    3. User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; zh-CN; rv:1.8.1) Gecko/20061010 Firefox/2.0   
    4. Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5   
    5. Accept-Language: en-us,zh-cn;q=0.7,zh;q=0.3   
    6. Accept-Charset: gb2312,utf-8;q=0.7,*;q=0.7   
    7. Content-Type: multipart/form-data; boundary=---------------------------5169208281820   
    8. Content-Length: 449   
    9.   
    10. -----------------------------5169208281820   
    11. Content-Disposition: form-data; name="file_1"filename=""  
    12. Content-Type: application/octet-stream   
    13.   
    14.   
    15. -----------------------------5169208281820   
    16. Content-Disposition: form-data; name="file_0"filename="test.txt"  
    17. Content-Type: text/plain   
    18.   
    19. hello world!   
    20.   
    21. -----------------------------5169208281820   
    22. Content-Disposition: form-data; name="oper"  
    23.   
    24. upload   
    25. -----------------------------5169208281820--  

    POST http://www.test.comt/upload_attach?uidl=%3C HTTP/1.1

    User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; zh-CN; rv:1.8.1) Gecko/20061010 Firefox/2.0

    Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5

    Accept-Language: en-us,zh-cn;q=0.7,zh;q=0.3

    Accept-Charset: gb2312,utf-8;q=0.7,*;q=0.7

    Content-Type: multipart/form-data; boundary=---------------------------5169208281820

    Content-Disposition: form-data; name="file_1"; filename=""

    Content-Type: application/octet-stream

    Content-Disposition: form-data; name="file_0"; filename="test.txt"

    Content-Disposition: form-data; name="oper"

     

    e)CONNECT举例

    Html代码 复制代码 收藏代码

    1. CONNECT mail.test.com:80 HTTP/1.1   
    2. User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; zh-CN; rv:1.8.1) Gecko/20061010 Firefox/2.0   
    3. Proxy-Connection: keep-alive   
    4. Host: mail.test.com:80  

    CONNECT mail.test.com:80 HTTP/1.1

    User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; zh-CN; rv:1.8.1) Gecko/20061010 Firefox/2.0

     

    3.0)在终端以 telnet 方式测试

    a)打开回显功能(针对windows)
      Windows 2000:进入DOS模式->输入 telnet->set LOCAL_ECHO->退出:quit->telnet ip 80
      Windows xp:进入DOS模式->输入telnet->set local echo->open ip 80
    b) 按HTTP协议格式输入GET请求、HEAD请求、POST请求。

     

    posted @ 2012-11-08 02:44 奋斗成就男人 阅读(178) | 评论 (0)编辑 收藏

    按某一字段分组取最大(小)值所在行的数据

         摘要: /* 数据如下: name val memo a    2   a2(a的第二个值) a    1   a1--a的第一个值 a    3   a3:a的第三个值 b    1   b1-...  阅读全文

    posted @ 2012-11-02 19:21 奋斗成就男人 阅读(350) | 评论 (0)编辑 收藏

    公钥与私钥

    数字签名是什么?

    作者:David Youd

    翻译:阮一峰

    原文网址:http://www.youdzone.com/signature.html

    1.

    鲍勃有两把钥匙,一把是公钥,另一把是私钥。

    2.

    鲍勃把公钥送给他的朋友们----帕蒂、道格、苏珊----每人一把。

    3.

    苏珊要给鲍勃写一封保密的信。她写完后用鲍勃的公钥加密,就可以达到保密的效果。

    4.

    鲍勃收信后,用私钥解密,就看到了信件内容。这里要强调的是,只要鲍勃的私钥不泄露,这封信就是安全的,即使落在别人手里,也无法解密。

    5.

    鲍勃给苏珊回信,决定采用"数字签名"。他写完后先用Hash函数,生成信件的摘要(digest)。

    6.

    然后,鲍勃使用私钥,对这个摘要加密,生成"数字签名"(signature)。

    7.

    鲍勃将这个签名,附在信件下面,一起发给苏珊。

    8.

    苏珊收信后,取下数字签名,用鲍勃的公钥解密,得到信件的摘要。由此证明,这封信确实是鲍勃发出的。

    9.

    苏珊再对信件本身使用Hash函数,将得到的结果,与上一步得到的摘要进行对比。如果两者一致,就证明这封信未被修改过。

    10.

    复杂的情况出现了。道格想欺骗苏珊,他偷偷使用了苏珊的电脑,用自己的公钥换走了鲍勃的公钥。此时,苏珊实际拥有的是道格的公钥,但是还以为这是鲍勃的公钥。因此,道格就可以冒充鲍勃,用自己的私钥做成"数字签名",写信给苏珊,让苏珊用假的鲍勃公钥进行解密。

    11.

    后来,苏珊感觉不对劲,发现自己无法确定公钥是否真的属于鲍勃。她想到了一个办法,要求鲍勃去找"证书中心"(certificate authority,简称CA),为公钥做认证。证书中心用自己的私钥,对鲍勃的公钥和一些相关信息一起加密,生成"数字证书"(Digital Certificate)。

    12.

    鲍勃拿到数字证书以后,就可以放心了。以后再给苏珊写信,只要在签名的同时,再附上数字证书就行了。

    13.

    苏珊收信后,用CA的公钥解开数字证书,就可以拿到鲍勃真实的公钥了,然后就能证明"数字签名"是否真的是鲍勃签的。

    14.

    下面,我们看一个应用"数字证书"的实例:https协议。这个协议主要用于网页加密。

    15.

    首先,客户端向服务器发出加密请求。

    16.

    服务器用自己的私钥加密网页以后,连同本身的数字证书,一起发送给客户端。

    17.

    客户端(浏览器)的"证书管理器",有"受信任的根证书颁发机构"列表。客户端会根据这张列表,查看解开数字证书的公钥是否在列表之内。

    18.

    如果数字证书记载的网址,与你正在浏览的网址不一致,就说明这张证书可能被冒用,浏览器会发出警告。

    19.

    如果这张数字证书不是由受信任的机构颁发的,浏览器会发出另一种警告。

    20.

    posted @ 2012-10-15 02:37 奋斗成就男人 阅读(42167) | 评论 (31)编辑 收藏

    Struts2拦截器的使用

         摘要: 如何使用struts2拦截器,或者自定义拦截器。特别注意,在使用拦截器的时候,在Action里面必须最后一定要引用struts2自带的拦截器缺省堆栈defaultStack,如下(这里我是引用了struts2自带的checkbox拦截器): 源码复制打印?<interceptor-ref name="checkbox">    <...  阅读全文

    posted @ 2012-09-20 01:10 奋斗成就男人 阅读(275) | 评论 (0)编辑 收藏

    struts2原理(转)

    1.Struts 2的基本流程 
    Struts 2框架由3个部分组成:核心控制器FilterDispatcher、业务控制器和用户实现的业务逻辑组件。在这3个部分里,Struts 2框架提供了核心控制器FilterDispatcher,而用户需要实现业务控制器和业务逻辑组件。 
    2.核心控制器:FilterDispatcher 
    FilterDispatcher是Struts 2框架的核心控制器,该控制器作为一个Filter运行在Web应用中,它负责拦截所有的用户请求,当用户请求到达时,该Filter会过滤用户请求。如果用户请求以action结尾,该请求将被转入Struts 2框架处理。 

    Struts 2框架获得了*.action请求后,将根据*.action请求的前面部分决定调用哪个业务逻辑组件,例如,对于login.action请求,Struts 2调用名为login的Action来处理该请求。 

    Struts 2应用中的Action都被定义在struts.xml文件中,在该文件中定义Action时,定义了该Action的name属性和class属性,其中name属性决定了该Action处理哪个用户请求,而class属性决定了该Action的实现类。 

    Struts 2用于处理用户请求的Action实例,并不是用户实现的业务控制器,而是Action代理——因为用户实现的业务控制器并没有与Servlet API耦合,显然无法处理用户请求。而Struts 2框架提供了系列拦截器,该系列拦截器负责将HttpServletRequest请求中的请求参数解析出来,传入到Action中,并回调Action 的execute方法来处理用户请求。 

    显然,上面的处理过程是典型的AOP(面向切面编程)处理方式。图3.19显示了这种处理模型。 



    图3.19 Struts 2的拦截器和Action 

    从图3.19中可以看出,用户实现的Action类仅仅是Struts 2的Action代理的代理目标。用户实现的业务控制器(Action)则包含了对用户请求的处理。用户的请求数据包含在 HttpServletRequest对象里,而用户的Action类无需访问HttpServletRequest对象。拦截器负责将 HttpServletRequest里的请求数据解析出来,并传给业务逻辑组件Action实例。 
    3.业务控制器 
    正如从图3.19所看到的,业务控制器组件就是用户实现Action类的实例,Action类里通常包含了一个execute方法,该方法返回一个字符串——该字符串就是一个逻辑视图名,当业务控制器处理完用户请求后,根据处理结果不同,execute方法返回不同字符串 ——每个字符串对应一个视图名。 

    程序员开发出系统所需要的业务控制器后,还需要配置Struts 2的Action,即需要配置Action的如下三个部分定义: 

    — Action所处理的URL。 

    — Action组件所对应的实现类。 

    — Action里包含的逻辑视图和物理资源之间的对应关系。 

    每个Action都要处理一个用户请求,而用户请求总是包含了指定URL。当Filter Dispatcher拦截到用户请求后,根据请求的URL和Action处理URL之间的对应关系来处理转发。 
    4.Struts 2的模型组件 
    实际上,模型组件已经超出了MVC框架的覆盖范围。对于Struts 2框架而言,通常没有为模型组件的实现提供太多的帮助。 

    文本框: 图3.20 控制器调用模型组件Java EE应用里的模型组件,通常指系统的业务逻辑组件。而隐藏在系统的业务逻辑组件下面的,可能还包含了DAO、领域对象等组件。 

    通常,MVC框架里的业务控制器会调用模型组件的方法来处理用户请求。也就是说,业务逻辑控制器不会对用户请求进行任何实际处理,用户请求最终由模型组件负责处理。业务控制器只是中间负责调度的调度器,这也是称Action为控制器的原因。 


    图3.20显示了这种处理流程。 

    提示 在图3.20中看到Action调用业务逻辑组件的方法。当控制器需要获得业务逻辑组件实例时,通常并不会直接获取业务逻辑组件实例,而是通过工厂模式来获得业务逻辑组件的实例;或者利用其他IoC容器(如Spring容器)来管理业务逻辑组件的实例。 
    5.Struts 2的视图组件 
    Struts 2已经改变了Struts 1只能使用JSP作为视图技术的现状,Struts 2允许使用其他的模板技术,如FreeMarker、Velocity作为视图技术。 

    当Struts 2的控制器返回逻辑视图名时,逻辑视图并未与任何的视图技术关联,仅仅是返回一个字符串,该字符串作为逻辑视图名。 

    当我们在struts.xml文件中配置 Action时,不仅需要指定Action的name属性和class属性,还要为Action元素指定系列result子元素,每个result子元素定义一个逻辑视图和物理视图之间的映射。前面所介绍的应用都使用了JSP技术作为视图,故配置result子元素时没有指定type属性,默认使用JSP 作为视图资源。 

    如果需要在Struts 2中使用其他视图技术,则可以在配置result子元素时,指定相应的type属性即可。例如,如果需要使用FreeMarker,则为result指定值为freemarker的type属性;如果想使用Velocity模板技术作为视图资源,则为result指定值为velocity的type属性…… 
    6.Struts 2的运行流程 
    经过上面介绍,我们发现Struts 2框架的运行流程非常类似于WebWork框架的流程。 

    提示 在Struts 2的官方站点,我们可以找到如下说法:Essentially,Struts 2.0 is the technical equivalent of WebWork 2.3。Aside from the package and property renaming,it isn't much different than,say,migrating from WebWork 2.1 to 2.2——意思是说:Struts 2.0技术等同于WebWork 2.3框架,除了包和属性被改名外。从WebWork 2.2迁移到Struts 2不会比从WebWork 2.1迁移到WebWork 2.2更复杂。 

    这里我们可以看到,Struts 2其实就是WebWork 2.2的升级版,这也就不难理解:为什么WebWork和Struts 2如此相似! 

    因此,Struts 2的运行流程与WebWork的运行流程完全相同,读者可以参看图1.8来了解Struts 2的运行流程。 

    posted @ 2012-09-20 01:10 奋斗成就男人 阅读(240) | 评论 (0)编辑 收藏

    struts2 的基石--拦截器

         摘要: struts2 的基石--拦截器(Interceptor)(转载自http://www.blogjava.net/max/archive/2006/12/06/85925.html) 许多朋友可能对于Struts 2.0与WebWork关系还搞不清楚。下面是Apache的Struts官网中的一段话: Apache Struts 2 was originally known as...  阅读全文

    posted @ 2012-09-20 01:09 奋斗成就男人 阅读(289) | 评论 (0)编辑 收藏

    Struts2的注解功能

    我们知道通常情况下,Struts2是通过struts.xml配置的。但是随着系统规模的加大我们需要配置的文件会比较大,虽然我们可以根据不同的系统功能将不同模块的配置文件单独书写,然后通过<include>节点将不同的配置文件引入到最终的struts.xml文件中,但是毕竟还是要维护和管理这些文件,因此也会给维护工作带来很大的困扰。为了解决这个问题,可以考虑使用struts2的注解。实际上struts2中最主要的概念就是packageaction以及Interceptor等等概念,所以只要明白这些注解就可以了。

    如果希望使用struts2的注解功能,必须使用一个包struts2-convention-plugin-2.1.8.1.jar,我使用的环境是struts2.1.8.1。如果你使用了不同的版本,找名字就行。

    在以上所述的jar文件中定义了一系列的注解,其中比较主要的是:

    • @ParentPackage,这个注解对应了xml文件中的package节点,它只有一个属性叫value,其实就是packagename属性;
    • @Namespace,命名空间,也就是xml文件中<package>namespace属性;
    • @Action,这个注解对应<action>节点。这个注解可以应用于action类上,也可以应用于方法上。这个注解中有几个属性:
      • value(),表示actionURL,也就是<action>节点中的name属性;
      • results(),表示action的多个result;这个属性是一个数组属性,因此可以定义多个Result
      • interceptorRefs(),表示action的多个拦截器。这个属性也是一个数组属性,因此可以定义多个拦截器;
      • params(),这是一个String类型的数组,它按照name/value的形式组织,是传给action的参数;
      • exceptionMappings(),这是异常属性,它是一个ExceptionMapping的数组属性,表示action的异常,在使用时必须引用相应的拦截器;
    • @Result,这个注解对应了<result>节点。这个注解只能应用于action类上。这个注解中也有几个属性:
      • name(),表示action方法的返回值,也就是<result>节点的name属性,默认情况下是【success】;
      • location(),表示view层文件的位置,可以是相对路径,也可以是绝对路径;
      • type(),是action的类型,比如redirect
      • params(),是一个String数组。也是以name/value形式传送给result的参数;

    实际上,struts2中的主要注解就是这些,当然了,还有上面提到的@interceptorRef@exceptionMapping;基本上,掌握了这些注解就可以了。

    但是如果想让这些注解真正工作,必须在配置文件增加几个常量的定义:

    • struts.convention.default.parent.package:这个常量表示缺省的包名是什么,因为在实际应用中,我们常常定义一个缺省的包,这个包中定义了一大堆的拦截器等等,然后其他的包继承自这个包。这个常量可以配也可以不配;
    • struts.convention.package.locators:这个常量表示你的action类的java包的包名的后缀是啥:比如action。这个常量也可以不配;
    • struts.convention.package.locators.basePackage:这个常量表示你的action类的javapackage的名字是啥;这个常量也可以不配;

    以上三个常量都是辅助作用的,为了让注解真正的工作,必须在配置文件中增加<package>节点的配置,至少是<package name="myPackage" extends="struts-default" />,这样注解就可以使用了。

    posted @ 2012-09-20 01:08 奋斗成就男人 阅读(310) | 评论 (0)编辑 收藏

    Java编码易疏忽的十个问题

         摘要: 在Java编码中,我们容易犯一些错误,也容易疏忽一些问题,因此笔者对日常编码中曾遇到的一些经典情形归纳整理成文,以共同探讨。 0. 纠结的同名 现象 很多类的命名相同(例如:常见于异常、常量、日志等类),导致在import时,有时候张冠李戴,这种错误有时候很隐蔽。因为往往同名的类功能也类似,所以IDE不会提示warn。 解决 写完代码时,扫视下im...  阅读全文

    posted @ 2012-09-20 00:57 奋斗成就男人 阅读(131) | 评论 (0)编辑 收藏

    Java程序员应该知道的10个调试技巧

    摘要:调试不仅可以查找到应用程序缺陷所在,还可以解决缺陷。对于Java程序员来说,他们不仅要学会如何在Eclipse里面开发像样的程序,更需要学会如何调试程序。本文介绍了Java程序员必知的10个调试技巧,保证让你受益匪浅! 

    调试可以帮助识别和解决应用程序缺陷,在本文中,作者将使用大家常用的的开发工具Eclipse来调试Java应用程序。但这里介绍的调试方法基本都是通用的,也适用于NetBeans IDE,我们会把重点放在运行时上面。 

    在开始之前,推荐大家去看看Eclipse shortcuts这篇文章,它将会给你带来很多方便。在本文中使用的是Eclipse Juno版(Eclipse 4.2),在开始前给大家提3点建议! 

    1.不要使用System.out.println作为调试工具 

    2.把所有涉及到的组件日志级别激活并使用 

    3.使用日志分析器来读取日志 

    0.条件断点 

    如果你不知道如何添加断点,只需点击左边面板(行号前面)断点即被创建。在调试界面中,“断点”视图会把所有被创建的断点列出来。我们可以给它加一个布尔条件,也就是说,该断点会被激活并且如果布尔条件为真,就会执行该断点,否则将会跳过往下执行。 
     

    1.异常断点 

    在断点视图中,有一个J!标记按钮!我们可以使用该按钮来添加一个Java异常断点。例如,我们想让程序在遇到空指针异常(NullPointerException)时,仍然能继续调试,那么我们可以使用该按钮来添加一个异常断点! 
     

    2.监视点 

    这是一个非常好的功能,当选定的属性访问或修改程序时,程序会停止执行并允许进行调试。在Outline视图中选择一个类变量并从上下文菜单中选择切换监视点,属性监视点将会被创建,在断点(Breakpoints)视图中会把所有监视点用列表的形式显示出来。 

     

    3.评估/检查 

    按Ctrl+Shift+D或者Ctrl+Shift+I来显示选定变量或者表达式的值。我们也可以给一个变量或表达式添加永久观察点,当程序在调试时,这些观察点就会在表达式视图(Expression view)中显示出来。 

     

    4.修改变量值 

    在调试过程中,我们可以修改变量值。先选好一个变量然后进入变量视图(Variables view),根据变量类型在其对应的Value列里输入值即可。 

     

    5.在Main函数里面停止执行 

    在运行/调试设置中,编辑配置对话框中有“Main”这个选项卡,我们可以勾选“Stop in main”这个复选框。如果选中,那么在调试一个基于main方法的Java程序时,程序会在main方法第一行位置便停止执行。 

     

    6.环境变量 

    并不是在系统属性中添加环境变量,我们可以在编辑配置对话框中很方便地进行添加。 

     

    7.Drop to Frame 

    这也是我最喜欢的一个功能。调试期间,可以重新跳到调用堆栈框架的开始处执行,并且变量值也会回到最初。根据回档调整堆栈的深度,这个功能的主要用途是所有变量状态可以快速回到方法开始执行时候的样子,然后你可以重新进行一遍一遍执行,这样就可以在你关注的地方进行多次调试,但是在执行过程中也会产生一些副作用,比如插入到数据库里面的数据是无法删除的! 

     

    8.分布过滤 

    当我们进入(F5)方法的时候,我们还可以访问其外部库(比如java.*),我们可能不需要这个库,就可以在Perference选项卡页面添加一个过滤器来排除这个包。 

     

    9.进入、跳出和返回 

    我把这个放在最后一点,在调试过程中,这些是必须要了解(最好掌握)的东西: 

    F5——进入:移动到下一个步骤,如果当前行有一个方法调用,该控件将会跳转到被调用方法的第一行执行。 

    F6——跳出:移动到下一行。如果在当前行有方法调用,那么会直接移动到下一行执行。不会进入被调用方法体里面。 

    F7——返回:从当前方法中跳出,继续往下执行。 

    F8——移动到下一个断点处执行。 

     

    posted @ 2012-09-20 00:57 奋斗成就男人 阅读(130) | 评论 (0)编辑 收藏

    ibatis 开发指南 3

         摘要: 接 ibatis 开发指南 2 Cache 在特定硬件基础上(同时假设系统不存在设计上的缺漏和糟糕低效的 SQL 语句) Cache往往是提升系统性能的最关键因素)。 相对 Hibernate 等封装较为严密的 ORM 实现而言(因为对数据对象的操作实现 了较为严密的封装,可以保证其作用范围内的缓存同步,而 ibatis 提供的是半封闭 ...  阅读全文

    posted @ 2012-09-20 00:56 奋斗成就男人 阅读(558) | 评论 (0)编辑 收藏

    Java语言中内存管理的几个技巧

    Java做的系统给人的印象是什么?占内存!说道这句话就会有N多人站出来为java辩护,并举出一堆的性能测试报告来证明这一点。 

      其实从理论上来讲java做的系统并不比其他语言开发出来的系统更占用内存,那么为什么却有这么N多理由来证明它确实占内存呢?两个字,陋习。 

      (1)别用new Boolean()。 

      在很多场景中Boolean类型是必须的,比如JDBC中boolean类型的set与get都是通过Boolean封装传递的,大部分ORM也是用Boolean来封装boolean类型的,比如: 

      ps.setBoolean("isClosed",new Boolean(true)); 

      ps.setBoolean("isClosed",new Boolean(isClosed)); 

      ps.setBoolean("isClosed",new Boolean(i==3)); 

      通常这些系统中构造的Boolean实例的个数是相当多的,所以系统中充满了大量Boolean实例小对象,这是相当消耗内存的。Boolean类实际上只要两个实例就够了,一个true的实例,一个false的实例。 

      Boolean类提供两了个静态变量: 

      public static final Boolean TRUE = new Boolean(true); 

      public static final Boolean FALSE = new Boolean(false); 

      需要的时候只要取这两个变量就可以了, 

      比如: 

      ps.setBoolean("isClosed",Boolean.TRUE); 

      那么象2、3句那样要根据一个boolean变量来创建一个Boolean怎么办呢?可以使用Boolean提供的静态方法: Boolean.valueOf() 

      比如: 

      ps.setBoolean("isClosed",Boolean.valueOf(isClosed)); 

      ps.setBoolean("isClosed",Boolean.valueOf(i==3)); 

      因为valueOf的内部实现是:return (b ? TRUE : FALSE); 

      所以可以节省大量内存。相信如果Java规范直接把Boolean的构造函数规定成private,就再也不会出现这种情况了。 

      (2)别用new Integer. 

      和Boolean类似,java开发中使用Integer封装int的场合也非常多,并且通常用int表示的数值通常都非常小。SUN SDK中对Integer的实例化进行了优化,Integer类缓存了-128到127这256个状态的Integer,如果使用Integer.valueOf(int i),传入的int范围正好在此内,就返回静态实例。这样如果我们使用Integer.valueOf代替new Integer的话也将大大降低内存的占用。如果您的系统要在不同的SDK(比如IBM SDK)中使用的话,那么可以自己做了工具类封装一下,比如IntegerUtils.valueOf(),这样就可以在任何SDK中都可以使用这种特性。 

      (3)用StringBuffer代替字符串相加。 

      这个我就不多讲了,因为已经被人讲过N次了。我只想将一个不是笑话的笑话,我在看国内某“著名”java开发的WEB系统的源码中,竟然发现其中大量的使用字符串相加,一个拼装SQL语句的方法中竟然最多构造了将近100个string实例。无语中! 

      (4)过滥使用哈希表 

      有一定开发经验的开发人员经常会使用hash表(hash表在JDK中的一个实现就是HashMap)来缓存一些数据,从而提高系统的运行速度。比如使用HashMap缓存一些物料信息、人员信息等基础资料,这在提高系统速度的同时也加大了系统的内存占用,特别是当缓存的资料比较多的时候。其实我们可以使用 

      操作系统中的缓存的概念来解决这个问题,也就是给被缓存的分配一个一定大小的缓存容器,按照一定的算法淘汰不需要继续缓存的对象,这样一方面会因为进行了对象缓存而提高了系统的运行效率,同时由于缓存容器不是无限制扩大,从而也减少了系统的内存占用。现在有很多开源的缓存实现项目,比如ehcache、oscache等,这些项目都实现了FIFO、MRU等常见的缓存算法。 

      (5)避免过深的类层次结构和过深的方法调用。 

      因为这两者都是非常占用内存的(特别是方法调用更是堆栈空间的消耗大户。 

      (6)变量只有在用到它的时候才定义和实例化。 

      (7)尽量避免使用static变量,类内私有常量可以用final来代替。 

    posted @ 2012-09-20 00:56 奋斗成就男人 阅读(120) | 评论 (0)编辑 收藏

    ibatis 开发指南 3

    ibatis的调试相对困难,出错的时候主要依据是log4生成的log文件和.net的出错提示,这方面要能比较熟练的看懂. 
    下面这个配置基本上包含了最复杂的功能:分页\搜索\排序\缓存\传值Hash表\返回hash表\动态sql 
    如果对下面这段配置能信手粘来的话,那开发速度将会大大的提升. 
    <statement id="XinxiTable_SelectAll" listClass="ArrayList" >
    resultMap="SimpleXinxi" parameterClass="Hashtable" cacheModel="xinxi-cache" > 
    SELECT 
    <dynamic prepend="top"> 
    <isNotEqual prepend="top" property="TopNum" compareValue = "0"> 
    $TopNum$ 
    </isNotEqual> 
    </dynamic> 

    FROM 
    (select a.[iXinxiID],a.[sXinxiTitle],a.[iXinxiClassId],b.[sClassName], 
    a.[dXinxiDate],a.[dXinxiYxq],a.[iXinxiHits],a.[sXinxiUser],a.[sRedirectUrl], 
    ROW_NUMBER() OVER( 
    <dynamic prepend="order by"> 
    <isEqual prepend="order by" property="Sort" compareValue = "0"> 
    a.iXinxiID desc 
    </isEqual> 
    <isEqual prepend="order by" property="Sort" compareValue = "1"> 
    a.iXinxiID asc 
    </isEqual> 
    <isEqual prepend="order by" property="Sort" compareValue = "2"> 
    a.iXinxiHits desc 
    </isEqual> 
    <isEqual prepend="order by" property="Sort" compareValue = "3"> 
    a.iXinxiHits asc 
    </isEqual> 
    </dynamic> 
    ) as row 
    FROM 
    [dbo].[XinxiTable] as a,[dbo].[XinxiClass] as b 
    <dynamic prepend="where"> 
    <isParameterPresent> 
    <isNotEmpty prepend="and" property="XinxiType" > 
    a.[iXinxiState]= $XinxiType$ 
    </isNotEmpty> 
    <isNotEqual prepend="and" property="XinxiClass" compareValue = "0"> 
    a.[iXinxiClassID]= $XinxiClass$ 
    </isNotEqual> 
    <isEqual prepend="and" property="SearchType" compareValue = "1"> 
    a.[sXinxiTitle] LIKE '%$Keyword$%' 
    </isEqual> 
    <isEqual prepend="and" property="SearchType" compareValue = "2"> 
    (a.[sXinxiTitle] LIKE '%$Keyword$%' or a.[sXinxiContent] LIKE '%$Keyword$%') 
    </isEqual> 
    </isParameterPresent> 
    </dynamic> 
    and a.iXinxiClassId=b.iClassId 
    )a 
    <dynamic prepend="where"> 
    <isParameterPresent> 
    <isEqual prepend="and" property="IsPage" compareValue = "1"> 
    row between $PageLower$ and $PageUpper$ 
    </isEqual> 
    </isParameterPresent> 
    </dynamic> 
    </statement> 

    posted @ 2012-09-20 00:55 奋斗成就男人 阅读(386) | 评论 (0)编辑 收藏

    iBatis中使用动态查询

         摘要: iBatis中的动态查询还是比较好用的 如果想深入学习,可以参考 Manning.iBATIS.in.Action.Jan.2007 下面给出几个例子和dtd定义: <select id="selectDispatchedKey" parameterClass="KeyAndKeyFlowInfo" resultMap="KeyAndKeyFlowResult"...  阅读全文

    posted @ 2012-09-20 00:54 奋斗成就男人 阅读(969) | 评论 (0)编辑 收藏

    JSTL 学习、应用记录

         摘要: JSP 标准标记库( Standard Tag Library , JSTL) 是一组以标准化格式实现许多通用的 Web 站点功能的定制标记。 JSP 技术的优势之一在于其定制标记库工具。除了核心 JSP 标记,如 jsp:include 之外,定制标记库工具使您能够创建唯一的标记来描述以站点或应用程序为导向的操作。一旦您创建了定制标记库 ( 简称 taglib) ,当您扩展项目或转向另...  阅读全文

    posted @ 2012-09-20 00:53 奋斗成就男人 阅读(266) | 评论 (0)编辑 收藏

    Spring,hibernate,struts的面试笔试题(含答案)

    发表时间:2012-06-08 13:10:03楼主  引用 

    Hibernate工作原理及为什么要用? 
    原理: 
    1.读取并解析配置文件 
    2.读取并解析映射信息,创建SessionFactory 
    3.打开Sesssion 
    4.创建事务Transation 
    5.持久化操作 
    6.提交事务 
    7.关闭Session 
    8.关闭SesstionFactory 

    为什么要用: 
    1. 对JDBC访问数据库的代码做了封装,大大简化了数据访问层繁琐的重复性代码。 

    2. Hibernate是一个基于JDBC的主流持久化框架,是一个优秀的ORM实现。他很大程度的简化DAO层的编码工作 

    3. hibernate使用Java反射机制,而不是字节码增强程序来实现透明性。 

    4. hibernate的性能非常好,因为它是个轻量级框架。映射的灵活性很出色。它支持各种关系数据库,从一对一到多对多的各种复杂关系。 

    2. Hibernate是如何延迟加载? 
    1. Hibernate2延迟加载实现:a)实体对象 b)集合(Collection) 

    2. Hibernate3 提供了属性的延迟加载功能 

    当Hibernate在查询数据的时候,数据并没有存在与内存中,当程序真正对数据的操作时,对象才存在与内存中,就实现了延迟加载,他节省了服务器的内存开销,从而提高了服务器的性能。 

    3.Hibernate中怎样实现类之间的关系?(如:一对多、多对多的关系) 

    类与类之间的关系主要体现在表与表之间的关系进行操作,它们都市对对象进行操作,我们程序中把所有的表与类都映射在一起,它们通过配置文件中的many-to-one、one-to-many、many-to-many、 

    4. 说下Hibernate的缓存机制 

    1. 内部缓存存在Hibernate中又叫一级缓存,属于应用事物级缓存 

    2. 二级缓存: 
    a) 应用及缓存 
    b) 分布式缓存 
    条件:数据不会被第三方修改、数据大小在可接受范围、数据更新频率低、同一数据被系统频繁使用、非 关键数据 
    c) 第三方缓存的实现 

    5. Hibernate的查询方式 
    Sql、Criteria,object comptosition 
    Hql: 
    1、 属性查询 
    2、 参数查询、命名参数查询 
    3、 关联查询 
    4、 分页查询 
    5、 统计函数 

    6. 如何优化Hibernate? 
    1.使用双向一对多关联,不使用单向一对多 
    2.灵活使用单向一对多关联 
    3.不用一对一,用多对一取代 
    4.配置对象缓存,不使用集合缓存 
    5.一对多集合使用Bag,多对多集合使用Set 
    6. 继承类使用显式多态 
    7. 表字段要少,表关联不要怕多,有二级缓存撑腰 

    7. Struts工作机制?为什么要使用Struts? 
    工作机制: 
    Struts的工作流程: 
    在web应用启动时就会加载初始化ActionServlet,ActionServlet从 
    struts-config.xml文件中读取配置信息,把它们存放到各种配置对象 
    当ActionServlet接收到一个客户请求时,将执行如下流程. 
    -(1)检索和用户请求匹配的ActionMapping实例,如果不存在,就返回请求路径无效信息; 
    -(2)如果ActionForm实例不存在,就创建一个ActionForm对象,把客户提交的表单数据保存到ActionForm对象中; 
    -(3)根据配置信息决定是否需要表单验证.如果需要验证,就调用ActionForm的validate()方法; 
    -(4)如果ActionForm的validate()方法返回null或返回一个不包含ActionMessage的ActuibErrors对象, 就表示表单验证成功; 
    -(5)ActionServlet根据ActionMapping所包含的映射信息决定将请求转发给哪个Action,如果相应的 Action实例不存在,就先创建这个实例,然后调用Action的execute()方法; 
    -(6)Action的execute()方法返回一个ActionForward对象,ActionServlet在把客户请求转发给 ActionForward对象指向的JSP组件; 
    -(7)ActionForward对象指向JSP组件生成动态网页,返回给客户; 

    为什么要用: 
    JSP、Servlet、JavaBean技术的出现给我们构建强大的企业应用系统提供了可能。但用这些技术构建的系统非常的繁乱,所以在此之上,我们需要一个规则、一个把这些技术组织起来的规则,这就是框架,Struts便应运而生。 

    基于Struts开发的应用由3类组件构成:控制器组件、模型组件、视图组件 

    8. Struts的validate框架是如何验证的? 
    在struts配置文件中配置具体的错误提示,再在FormBean中的validate()方法具体调用。 

    9. 说下Struts的设计模式 
    MVC 模式: web应用程序启动时就会加载并初始化ActionServler。用户提交表单时,一个配置好的ActionForm对象被创建,并被填入表单相应的数 据,ActionServler根据Struts-config.xml文件配置好的设置决定是否需要表单验证,如果需要就调用ActionForm的 Validate()验证后选择将请求发送到哪个Action,如果Action不存在,ActionServlet会先创建这个对象,然后调用 Action的execute()方法。Execute()从ActionForm对象中获取数据,完成业务逻辑,返回一个ActionForward对 象,ActionServlet再把客户请求转发给ActionForward对象指定的jsp组件,ActionForward对象指定的jsp生成动 态的网页,返回给客户。 

    10. spring工作机制及为什么要用? 
    1.spring mvc请所有的请求都提交给DispatcherServlet,它会委托应用系统的其他模块负责负责对请求进行真正的处理工作。 
    2.DispatcherServlet查询一个或多个HandlerMapping,找到处理请求的Controller. 
    3.DispatcherServlet请请求提交到目标Controller 
    4.Controller进行业务逻辑处理后,会返回一个ModelAndView 
    5.Dispathcher查询一个或多个ViewResolver视图解析器,找到ModelAndView对象指定的视图对象 
    6.视图对象负责渲染返回给客户端。 

    为什么用: 
    {AOP 让开发人员可以创建非行为性的关注点,称为横切关注点,并将它们插入到应用程序代码中。使用 AOP 后,公共服务 (比 如日志、持久性、事务等)就可以分解成方面并应用到域对象上,同时不会增加域对象的对象模型的复杂性。 
    IOC 允许创建一个可以构造对象的应用环境,然后向这些对象传递它们的协作对象。正如单词 倒置 所表明的,IOC 就像反 过来的 JNDI。没有使用一堆抽象工厂、服务定位器、单元素(singleton)和直接构造(straight construction),每一个对象都是用其协作对象构造的。因此是由容器管理协作对象(collaborator)。 
    Spring即使一个AOP框架,也是一IOC容器。 Spring 最好的地方是它有助于您替换对象。有了 Spring,只要用 JavaBean 属性和配置文件加入依赖性(协作对象)。然后可以很容易地在需要时替换具有类似接口的协作对象。} 

    posted @ 2012-09-20 00:51 奋斗成就男人 阅读(190) | 评论 (0)编辑 收藏

    Java执行sql语句并获取指定返回值

    当我们插入一条数据的时候,我们很多时候都想立刻获取当前插入的主键值返回以做它用。我们通常的做法有如下几种: 

     1、先 select max(id) +1 ,然后将+1后的值作为主键插入数据库; 

      2、使用特定数据库的 auto_increment 特性,在插入数据完成后,使用 select max(id) 获取主键值; 

      3、对于Oracle,使用 sequence 获取值。 

      对于以上3种方法都无法绝对保证在高并发情况下的操作的原子性。 

      现记录以下几种获取数据库主键值方法: 

      1、数据库原生支持的sql方法: 

      SQLServer: 

    INSERT INTO table_name (.....) VALUES(......) SELECT @@IDENTITY AS aliasname; 


      上面的语句相当于查询语句,从结果集中使用 getXXX(aliasname) 方法获取主键值。 

      Oracle: 

    INSERT INTO table_name(......) VALUES(......) RETURNING[primaryKey INTO]:aliasname; 


      也是相当于查询语句,从结果集中使用 getXXX(aliasname) 方法获取主键值。 

      2、java.sql.Statement 返回键获取: 

      a: 使用JDBC 3.0提供的 getGeneratedKeys(推荐使用) 

    Statement stmt = ... ; 

    stmt.executeUpdate("INSERT INTO table_name(......) VALUES(......)", Statement.RETURN_GENERATED_KEYS); 

    ResultSet rs = stmt.getGeneratedKeys(); 

    int keyValue = -1; 

    if (rs.next()) { 

    keyValue = rs.getInt(1); 


      b:使用特定数据库特有的SQL 

    Statement stmt = ... ; 

    stmt.executeUpdate("INSERT INTO table_name(......) VALUES(......)", Statement.RETURN_GENERATED_KEYS); 

    ResultSet rs = stmt.executeQuery("SELECT LAST_INSERT_ID()"); 

    int keyValue = -1; 

    if (rs.next()) { 

    keyValue = rs.getInt(1); 


      那么现在我就一个例子来看一下原生的sql怎么能得到执行的返回结果 

      项目背景:数据库是oracle数据库,id生成规则是通过触发器插入数据的时候自动增长,所以在插入数据的时候在sql中就不需要指明id值。但是另外一张表需要引用这个id值作为外键,那么就必须获得被引用的这个表的ID,为了避免并发问题,我们只能在插入前面那张表的时候就获得他的ID,所以我使用了下面的方法来处理。 

    Connection con = DBConnector.getconecttion(); // 取得一个数据库连接 
    CallableStatement cst = null; 
    con.setAutoCommit(false); 
    String insertSql = "begin insert into TABLE (field_0,field_1) values (value_0,value_1) returning id into ?;end; "; 
    try { 
    cst = con.prepareCall(insertSql); //执行存储过程 
    cst.registerOutParameter(1, Types.INTEGER); //为存储过程设定返回值 
    int count = cst.executeUpdate(); //得到预编译语句更新记录或删除操作的结果 
    int id = cst.getInt(1); //得到返回值 
    System.out.println("成功执行了:" + count + "条数据,其ID值:" + id); 
    } catch (SQLException e1) { 
    con.rollback(); 
    con.setAutoCommit(true); 
    }finally{ 
    con.commit(); 
    con.close(); 
     

    posted @ 2012-09-20 00:50 奋斗成就男人 阅读(1262) | 评论 (0)编辑 收藏

    java简介(问答模式)

         摘要: 一、 JAVA语言 1、 面向对象的三个基本特征 答:继承、封装、多态 2、 方法重载和方法重写的概念和区别 答:方法重载:方法名称相同但方法内的参数个数和参数类型不一样。 方法重写:在类的继承中,当子类的成员变量与父类的成员变量同名时,子类的成员变量会隐藏父类的成员变量;当子类的方法与父类的方法同名,参数列表、反回值类型相同时,子类的方法将覆盖父...  阅读全文

    posted @ 2012-09-20 00:49 奋斗成就男人 阅读(176) | 评论 (0)编辑 收藏

    开发dao模型

    开发dao模型: 

    接口是用来定义操作的,在这里应该定义:添、删、改、查(ID查、查询全部、模糊查询)等操作。 
    import java.util.* ; 
    // 规定出了操作person表在此项目里的全部方法 
    public interface PersonDAO 

    // 增加操作 
    public void insert(Person person) throws Exception; 
    // 修改操作 
    public void update(Person person) throws Exception; 
    // 删除操作 
    public void delete(String id) throws Exception; 
    // 按ID查询操作 
    public Person queryById(String id) throws Exception; 
    // 查询全部 
    public List queryAll() throws Exception; 
    // 模糊查询 
    public List queryByLike(String cond) throws Exception; 

    另创建一个类 
    import java.util.*; 
    public class PersonDAOImpl implements PersonDAO 

    // 增加操作 
    public void insert(Person person) throws Exception 


    // 修改操作 
    public void update(Person person) throws Exception 


    // 删除操作 
    public void delete(String id) throws Exception 


    // 按ID查询操作 
    public Person queryById(String id) throws Exception 


    // 查询全部 
    public List queryAll() throws Exception 


    // 模糊查询 
    public List queryByLike(String cond) throws Exception 



    接下来我们按方法一个一个的实现功能: 
    (1)添加操作,传入参数是Person person,同学们要理解为什么传入Person,因为Person是数据bean,是用来存放数据的不管从前台到后台数据库还是从后台数据库到前台,Person的角色都是用来传送数据的。 

    sql = "INSERT INTO person (id,name,password,age,email) VALUES (?,?,?,?,?)" ; 
    (2)修改操作与添加操作类似传入参数也为person对象,只是SQL的执行语句不同,当然修改要有条件,即修改谁,这里是以id作为修改条件的。 
    sql = "UPDATE person SET name=?,password=?,age=?,email=? WHERE id=?" ; 
    (3)删除操作,为什么这里没有以Person做参数呢,原因是使用的过程中删除操作都是通过id来标志一行记录的,为了使用方便所以传一个id就可以实现删除操作。 
    sql = "DELETE FROM person WHERE id=?" ; 
    (4)查询操作一般分为三种:按ID查询、查询全部、模糊查询。 
    第一种:按ID查询操作,传入一个id号返回一条记录,也就是一个person对象,person对应着数据库里的一行记录,所以返回值应该为Person类型。 

    sql = "SELECT id,name,password,age,email FROM person WHERE id=?" ; 
    第二种:查询全部,也就是查询整张表的全部数据,因为整张表有多条记录,所以对应就应该有多个person对象,查询的时候我们可以用list存放多个person对象,查询之后将该list返回。 

    sql = "SELECT id,name,password,age,email FROM person" ; 
    第三种:模糊查询,所谓模糊查询是指在数据表中查找与指定字符串部分相匹配的字段的行,如我们可以在一个用户的数据库中查找姓名中含有“静”字的所有记录,可以用like语句来实现。由于结果可能有多条记录,所以返回值好是存放Person对象的List。 

    sql = "SELECT id,name,password,age,email FROM person "+"WHERE name LIKE ? or email LIKE ?" ; 

    posted @ 2012-09-20 00:48 奋斗成就男人 阅读(310) | 评论 (0)编辑 收藏

    打印出Ibatis最终的SQL语句

    打印出Ibatis最终的SQL语句 

    log4j.appender.stdout=org.apache.log4j.ConsoleAppender 
    log4j.appender.stdout.layout=org.apache.log4j.PatternLayout 
    log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n 


    log4j.logger.com.ibatis=debug 
    log4j.logger.com.ibatis.common.jdbc.SimpleDataSource=debug 
    log4j.logger.com.ibatis.common.jdbc.ScriptRunner=debug 
    log4j.logger.com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate=debug 
    log4j.logger.java.sql.Connection=debug 
    log4j.logger.java.sql.Statement=debug 
    log4j.logger.java.sql.PreparedStatement=debug,stdout 

    posted @ 2012-09-20 00:44 奋斗成就男人 阅读(205) | 评论 (0)编辑 收藏

    全注解SSH

         摘要: 全注解SSH 一,hibernate annotation Class注解: 1. @Entity:表明当前类是一个持久化类 2. @Table(name="team",catalog="NBA"):映射一个表team,所对应的数据库是NBA,可以省略 字段属性注解: 1. @GenericGenerator(name = "genera...  阅读全文

    posted @ 2012-09-20 00:43 奋斗成就男人 阅读(2587) | 评论 (0)编辑 收藏

    Java 集合框架

         摘要: 在常见用法中,集合(collection)和数学上直观的集(set)的概念是相同的。 集是一个唯一项组,也就是说组中没有重复项。实际上,“集合框架”包含了一个 Set 接口和许多具体的 Set 类。但正式的集概念却比 Java 技术提前了一个世纪,那时英国数学家 George Boole 按逻辑正式的定义了集的概念。大部分人在小学时通过我们熟悉的维恩图引入的“集...  阅读全文

    posted @ 2012-09-20 00:42 奋斗成就男人 阅读(389) | 评论 (0)编辑 收藏

    doc系统的一些代码的运用

    如何进入dos操作界面 
    开始键+R输入cmd回车 

    如何切换盘符 
    例:F:+enter这样就切换到F盘了,(C盘D盘E盘)同理。 

    1.进出文件夹 
    进入目录 cd 文件夹名 
    例:F:\>cd空格(文件夹名) 
    F:\>cd (aa) 
    F:\aa>cd (bb) 
    F:\aa\bb>cd(cc) 
    2.录 cd .. 
    例:F:\aa\bb\cc>cd.. 
    F:\aa\bb>cd.. 
    F:\aa>cd.. 
    F:> 
    3.清屏命令 cls 

    4.查看目录命令: 
    查看当前文件夹目录 dir 
    查看当前目录以及子目录中的所有文件 
    dir/s 
    分页查看当前目录以及子目录中的所有文件 dir/s/p 

    5. 创建文件夹 
    md空格(文件夹名字) 

    6.删除文件夹 
    rd 空格(文件夹名字) 

    7.建立一个 打不开 删不掉的文件夹 
    md\文件夹名字..\ 
    只能通过dos命令删除 
    rd\文件夹名字..\ 

    8.关机命令 
    shutdown空格-s空格-t(时间) 
    取消关机:shutdown空格-a 
    注销:shutdown空格-l 

    9.定时关机 
    At 12:00 shutdown –s 

    10:Copy 文件名1(带后缀) 文件名2(带后缀) 

    posted @ 2012-09-20 00:41 奋斗成就男人 阅读(121) | 评论 (0)编辑 收藏

    Java命名规范

         摘要: 1命名规范 1.1 package (*) 包名全部由小写的ASCII字母组成,用“.”分隔。 在此项目中,所有的包均以“com.prosten.ticket”开头。 1.2 class (*) 类名应当是名词,每个内部单词的头一个字母大写。应当使你的类名简单和具有说明性。用完整的英语单词或约定俗成的...  阅读全文

    posted @ 2012-09-20 00:40 奋斗成就男人 阅读(1548) | 评论 (0)编辑 收藏

    Quartz 框架快速入门(四)

    Spring的scheduling.quartz包中对Quartz框架进行了封装,使得开发时不用写任何QuartSpring的代码就可以实现定时任务。Spring通过JobDetailBean,MethodInvokingJobDetailFactoryBean实现Job的定义。后者更加实用,只需指定要运行的类,和该类中要运行的方法即可,Spring将自动生成符合Quartz要求的JobDetail。
    在上一篇文章《Quartz 框架快速入门(三)》中我们将示例迁移到Web环境下了,但使用的是Quartz的启动机制,这一篇中我们将让Web服务器启动Spring,通过Spring的配置文件来进行任务的调度
    1,创建一个Web项目,加入spring.jar,quartz-1.6.0.jar,commons-collections.jar,jta.jar ,commons-logging.jar这几个包.
         2,创建一个类,在类中添加一个方法execute,我们将对这个方法进行定时调度.

    package com.vista.quartz;

    import java.util.Date;

    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.quartz.JobExecutionContext;
    import org.quartz.JobExecutionException;

    public class HelloWorld 
    {
        private static Log logger = LogFactory.getLog(HelloWorld.class);//日志记录器
        public HelloWorld()
        {
        }
        public void execute()
        {
            logger.info("Kick your ass and Fuck your mother! - " + new Date()); 
        }
    }

    2. Spring配置文件applicationContext.xml 修改如下:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans
        xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">

        <!-- 要调用的工作类 -->
        <bean id="quartzJob" class="com.vista.quartz.HelloWorld"></bean>
        <!-- 定义调用对象和调用对象的方法 -->
        <bean id="jobtask" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
            <!-- 调用的类 -->
            <property name="targetObject">
                <ref bean="quartzJob"/>
            </property>
            <!-- 调用类中的方法 -->
            <property name="targetMethod">
                 <value>execute</value>
            </property>
        </bean>
        <!-- 定义触发时间 -->
        <bean id="doTime" class="org.springframework.scheduling.quartz.CronTriggerBean">
            <property name="jobDetail">
                <ref bean="jobtask"/>
            </property>
            <!-- cron表达式 -->
            <property name="cronExpression">
                <value>10,15,20,25,30,35,40,45,50,55 * * * * ?</value>
            </property>
        </bean>
        <!-- 总管理类 如果将lazy-init='false'那么容器启动就会执行调度程序  -->
        <bean id="startQuertz" lazy-init="false" autowire="no" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
            <property name="triggers">
                <list>
                   <ref bean="doTime"/>
                </list>
            </property>
        </bean>
    </beans>

    3,先在控制台中对上面的代码进行测试,我们要做的只是加载Spring的配置文件就可以了,代码如下:

    package com.vista.quartz;

    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;

    public class Test 
    {
        public static void main(String[] args) 
        {
             System.out.println("Test start.");
                ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
                //如果配置文件中将startQuertz bean的lazy-init设置为false 则不用实例化
                
    //context.getBean("startQuertz");
             System.out.print("Test end..");
        }
    }

    4,然后将Web.xml修改如下,让tomcat在启动时去初始化Spring:

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app version="2.4" 
        xmlns="http://java.sun.com/xml/ns/j2ee" 
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
        http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
         <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>
                /WEB-INF/classes/applicationContext.xml
            </param-value>
        </context-param> 
        
        <servlet>
            <servlet-name>SpringContextServlet</servlet-name>
            <servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>
            <load-on-startup>1</load-on-startup>
        </servlet> 

      <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
      </welcome-file-list>
    </web-app>

    5,最后启动Tomcat,测试结果如下图所示:
     


    posted @ 2012-09-14 18:31 奋斗成就男人 阅读(169) | 评论 (0)编辑 收藏

    Quartz 框架快速入门(三)

      在前面两篇文章中简单介绍了在java应用程序中如何使用Quartz框架,这一篇中我们将看到如何在web环境下通过配置文件来完成Quartz的后台作业调度,而不必手工去创建Trigger和Scheduler,其步骤如下:
    首先创建一个Web项目,将quartz-1.6.0.jar,以及lib目录下面core下所有jar,optional目录下的所有commons-beanutils.jar和commons-digester-1.7.jar,build目录下的jta.jar都放入Web项目的WEB-INF"lib目录下。
    创建一个简单的job类HelloWorld,它的功能很简单,就是输出当前的时间,代码如下:

    package com.vista.quartz;

    import java.util.Date;

    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.quartz.Job;
    import org.quartz.JobExecutionContext;
    import org.quartz.JobExecutionException;

    public class Helloworld implements Job
    {
        private static Log logger = LogFactory.getLog(Helloworld.class);//日志记录器
        public Helloworld()
        {
        }
        public void execute(JobExecutionContext context) throws JobExecutionException 
        {
            logger.info("Hello World! - " + new Date()); 
        }
    }

    然后按照上一篇文章《Quartz 框架快速入门(二)》中所讲述的内容编写quartz.properties文件。如果启动项目的时候,Quartz没有在工程中找到该文件,就会从自己的jar包下面读取其默认的properties文件,其内容如下

    #============================================================================
    # Configure Main Scheduler Properties  
    #============================================================================
    org.quartz.scheduler.instanceName = QuartzScheduler
    org.quartz.scheduler.instanceId = AUTO
    #============================================================================
    # Configure ThreadPool  
    #============================================================================
    org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
    org.quartz.threadPool.threadCount = 5
    org.quartz.threadPool.threadPriority = 5
    #============================================================================
    # Configure JobStore  
    #============================================================================
    org.quartz.jobStore.misfireThreshold = 60000
    org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
    #============================================================================
    # Configure Plugins 
    #============================================================================
    org.quartz.plugin.triggHistory.class = org.quartz.plugins.history.LoggingJobHistoryPlugin
    org.quartz.plugin.jobInitializer.class = org.quartz.plugins.xml.JobInitializationPlugin
    org.quartz.plugin.jobInitializer.fileNames = jobs.xml
    org.quartz.plugin.jobInitializer.overWriteExistingJobs = true
    org.quartz.plugin.jobInitializer.failOnFileNotFound = true
    org.quartz.plugin.jobInitializer.scanInterval = 10
    org.quartz.plugin.jobInitializer.wrapInUserTransaction = false

    然后编写任务配置文件jobs.xml,内容如下:

    <?xml version='1.0' encoding='utf-8'?>
    <quartz xmlns="http://www.opensymphony.com/quartz/JobSchedulingData"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.opensymphony.com/quartz/JobSchedulingData
      http://www.opensymphony.com/quartz/xml/job_scheduling_data_1_5.xsd"
      version="1.5">   
     <job>      
        <job-detail>      
         <name>HelloWorld</name>      
         <group>DEFAULT</group>      
         <description>      
               A job that just for test       
         </description>      
         <job-class>      
                com.vista.quartz.Helloworld      
         </job-class>      
         <volatility>false</volatility>      
         <durability>false</durability>      
         <recover>false</recover>          
      </job-detail>      
      <trigger>      
        <simple>      
         <name>HelloTrigger1</name>      
         <group>DEFAULT</group>      
         <job-name>HelloWorld</job-name>      
         <job-group>DEFAULT</job-group>      
         <start-time>2008-09-03T15:56:30</start-time>      
         <!-- repeat indefinitely every 10 seconds -->      
         <repeat-count>-1</repeat-count>      
         <repeat-interval>10000</repeat-interval>      
        </simple>      
      </trigger>      
    </job>      
    </quartz>

    可以看到,在配置文件中把jobdetail和trigger都作了完整的定义,并组合成一个job。下面,我们把上面两个文件都放入/WEB-INF/classes目录下,然后按照api中的说明修改一下web.xml,内容如下

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app version="2.4" 
        xmlns="http://java.sun.com/xml/ns/j2ee" 
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
        http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
        <servlet>  
            <servlet-name>QuartzInitializer</servlet-name>  
            <display-name>Quartz Initializer Servlet</display-name>
            <servlet-class>  
                 org.quartz.ee.servlet.QuartzInitializerServlet  
            </servlet-class>  
            <load-on-startup>1</load-on-startup>  
            <init-param>  
                <param-name>config-file</param-name>  
                <param-value>/quartz.properties</param-value>  
            </init-param>  
            <init-param>  
                <param-name>shutdown-on-unload</param-name>  
                <param-value>true</param-value>  
           </init-param>  
        </servlet>  
      <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
      </welcome-file-list>
    </web-app>

    这样,在启动Tomcat的时候,QuartzInitializerServlet这个Servlet就会自动读取quartz.properties这个配置文件,并初始化调度信息,启动Scheduler。
    启动tomcat后,就可以看到输出的结果:
     

    posted @ 2012-09-14 18:29 奋斗成就男人 阅读(156) | 评论 (0)编辑 收藏

    Quartz 框架快速入门(二)

    尽可能的用声明式处理软件配置,其次才考虑编程式的方式。在上一篇《Quartz 框架快速入门(一)》中,如果我们要在 Job 启动之后改变它的执行时间和频度,必须去修改源代码重新编译。这种方式只适用于小的例子程序,但是对于一个大且复杂的系统,这就成了一个问题了。因此,假如能以声明式部署 Quart Job 时,并且也是需求允许的情况下,你应该每次都选择这种方式 
    ·配置 quartz.properties 文件
    文件 quartz.properties 定义了 Quartz 应用运行时行为,还包含了许多能控制 Quartz 运转的属性。这个文件应该放在classpath所指的路径下,比如我们这个java工程,就将它和下面将介绍的jobs.xml一起放在项目根目录下就是。如果不清楚就查看.classpath文件,它里面就配置了你的项目的classpath。
    我们来看看最基础的 quartz.properties 文件,并讨论其中一些设置。下面是一个修剪版的 quartz.propertis文件

    #============================================================================
    # Configure Main Scheduler Properties  
    #============================================================================
    org.quartz.scheduler.instanceName = TestScheduler
    org.quartz.scheduler.instanceId = AUTO
    #============================================================================
    # Configure ThreadPool  
    #============================================================================
    org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
    org.quartz.threadPool.threadCount = 3
    org.quartz.threadPool.threadPriority = 5
    #============================================================================
    # Configure JobStore  
    #============================================================================
    org.quartz.jobStore.misfireThreshold = 60000
    org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
    #============================================================================
    # Configure Plugins 
    #============================================================================
    org.quartz.plugin.triggHistory.class = org.quartz.plugins.history.LoggingJobHistoryPlugin
    org.quartz.plugin.jobInitializer.class = org.quartz.plugins.xml.JobInitializationPlugin
    org.quartz.plugin.jobInitializer.fileNames = jobs.xml
    org.quartz.plugin.jobInitializer.overWriteExistingJobs = true
    org.quartz.plugin.jobInitializer.failOnFileNotFound = true
    org.quartz.plugin.jobInitializer.scanInterval = 10
    org.quartz.plugin.jobInitializer.wrapInUserTransaction = false

    ·调度器属性
    第一部分有两行,分别设置调度器的实例名(instanceName) 和实例 ID (instanceId)。属性 org.quartz.scheduler.instanceName 可以是你喜欢的任何字符串。它用来在用到多个调度器区分特定的调度器实例。多个调度器通常用在集群环境中。(Quartz 集群将会在第十一章,“Quartz 集群”中讨论)。现在的话,设置如下的一个字符串就行:org.quartz.scheduler.instanceName = QuartzScheduler
    实际上,这也是当你没有该属性配置时的默认值。
    调度器的第二个属性是 org.quartz.scheduler.instanceId。和 instaneName 属性一样,instanceId 属性也允许任何字符串。这个值必须是在所有调度器实例中是唯一的,尤其是在一个集群当中。假如你想 Quartz 帮你生成这个值的话,可以设置为 AUTO。如果 Quartz 框架是运行在非集群环境中,那么自动产生的值将会是 NON_CLUSTERED。假如是在集群环境下使用 Quartz,这个值将会是主机名加上当前的日期和时间。大多情况下,设置为 AUTO 即可。
    ·线程池属性
    接下来的部分是设置有关线程必要的属性值,这些线程在 Quartz 中是运行在后台担当重任的。threadCount 属性控制了多少个工作者线程被创建用来处理 Job。原则上是,要处理的 Job 越多,那么需要的工作者线程也就越多。threadCount 的数值至少为 1。Quartz 没有限定你设置工作者线程的最大值,但是在多数机器上设置该值超过100的话就会显得相当不实用了,特别是在你的 Job 执行时间较长的情况下。这项没有默认值,所以你必须为这个属性设定一个值。
    threadPriority 属性设置工作者线程的优先级。优先级别高的线程比级别低的线程更优先得到执行。threadPriority 属性的最大值是常量 java.lang.Thread.MAX_PRIORITY,等于10。最小值为常量 java.lang.Thread.MIN_PRIORITY,为1。这个属性的正常值是 Thread.NORM_PRIORITY,为5。大多情况下,把它设置为5,这也是没指定该属性的默认值。
    最后一个要设置的线程池属性是 org.quartz.threadPool.class。这个值是一个实现了 org.quartz.spi.ThreadPool 接口的类的全限名称。Quartz 自带的线程池实现类是 org.quartz.smpl.SimpleThreadPool,它能够满足大多数用户的需求。这个线程池实现具备简单的行为,并经很好的测试过。它在调度器的生命周期中提供固定大小的线程池。你能根据需求创建自己的线程池实现,如果你想要一个随需可伸缩的线程池时也许需要这么做。这个属性没有默认值,你必须为其指定值。
    ·作业存储设置
    作业存储部分的设置描述了在调度器实例的生命周期中,Job 和 Trigger 信息是如何被存储的。我们还没有谈论到作业存储和它的目的;因为对当前例子是非必的,所以我们留待以后说明。现在的话,你所要了解的就是我们存储调度器信息在内存中而不是在关系型数据库中就行了。
    把调度器信息存储在内存中非常的快也易于配置。当调度器进程一旦被终止,所有的 Job 和 Trigger 的状态就丢失了。要使 Job 存储在内存中需通过设置  org.quartz.jobStrore.class 属性为 org.quartz.simpl.RAMJobStore。假如我们不希望在 JVM 退出之后丢失调度器的状态信息的话,我们可以使用关系型数据库来存储这些信息。这需要另一个作业存储(JobStore) 实现,我们在后面将会讨论到。第五章“Cron Trigger 和其他”和第六章“作业存储和持久化”会提到你需要用到的不同类型的作业存储实现。
    ·插件配置
    在这个简单的 quartz.properties 文件中最后一部分是你要用到的 Quart 插件的配置。插件常常在别的开源框架上使用到,比如 Apache 的 Struts 框架(见 http://struts.apache.org/)。
    一个声明式扩框架的方法就是通过新加实现了 org.quartz.spi.SchedulerPlugin 接口的类。SchedulerPlugin  接口中有给调度器调用的三个方法。
    要在我们的例子中声明式配置调度器信息,我们会用到一个 Quartz 自带的叫做 org.quartz.plugins.xml.JobInitializationPlugin 的插件。
    默认时,这个插件会在 classpath 中搜索名为 quartz_jobs.xml 的文件并从中加载 Job 和 Trigger 信息。在下下面中讨论 quartz_jobs.xml 文件,这是我们所参考的非正式的 Job 定义文件。
    ·为插件修改 quartz.properties 配置
    JobInitializationPlugin 找寻 quartz_jobs.xml 来获得声明的 Job 信息。假如你想改变这个文件名,你需要修改 quartz.properties 来告诉插件去加载那个文件。例如,假如你想要 Quartz 从名为 my_quartz_jobs.xml 的 XML 文件中加载 Job 信息,你不得不为插件指定这一文件

    org.quartz.plugin.triggHistory.class = org.quartz.plugins.history.LoggingJobHistoryPlugin
    org.quartz.plugin.jobInitializer.class = org.quartz.plugins.xml.JobInitializationPlugin
    org.quartz.plugin.jobInitializer.fileNames = jobs.xml
    org.quartz.plugin.jobInitializer.overWriteExistingJobs = true
    org.quartz.plugin.jobInitializer.failOnFileNotFound = true
    org.quartz.plugin.jobInitializer.scanInterval = 10
    org.quartz.plugin.jobInitializer.wrapInUserTransaction = false

    我们添加了属性 org.quartz.plugin.jobInitializer.fileName 并设置该属性值为我们想要的文件名。这个文件名要对 classloader 可见,也就是说要在 classpath 下。
    当 Quartz 启动后读取 quartz.properties 文件,然后初始化插件。它会传递上面配置的所有属性给插件,这时候插件也就得到通知去搜寻不同的文件。
    下面就是目录扫描例子的 Job 定义的 XML 文件。正如上一篇所示例子那样,这里我们用的是声明式途径来配置 Job 和 Trigger 信息的

    <?xml version='1.0' encoding='utf-8'?>
    <quartz xmlns="http://www.opensymphony.com/quartz/JobSchedulingData"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.opensymphony.com/quartz/JobSchedulingData
      http://www.opensymphony.com/quartz/xml/job_scheduling_data_1_5.xsd"
      version="1.5">   
      <job>      
        <job-detail>      
         <name>ScanDirectory</name>      
         <group>DEFAULT</group>      
         <description>      
              A job that scans a directory for files       
         </description>      
         <job-class>      
                com.vista.quartz.ScanDirectoryJob       
         </job-class>      
         <volatility>false</volatility>      
         <durability>false</durability>      
         <recover>false</recover>      
         <job-data-map allows-transient-data="true">      
             <entry>      
             <key>SCAN_DIR</key>      
             <value>D:\conf1</value>      
           </entry>      
         </job-data-map>      
        </job-detail>      
          
        <trigger>      
         <simple>      
           <name>scanTrigger</name>      
           <group>DEFAULT</group>      
           <job-name>ScanDirectory</job-name>      
           <job-group>DEFAULT</job-group>      
           <start-time>2008-09-03T14:43:00</start-time>      
           <!-- repeat indefinitely every 10 seconds -->      
           <repeat-count>-1</repeat-count>      
           <repeat-interval>10000</repeat-interval>      
         </simple>      
        </trigger>      
      </job>      
    </quartz>

    在jobs.xml 中 <start-time> 的格式是:
    <start-time>2008-09-03T14:43:00</start-time>
    其中T隔开日期和时间,默认时区 
    或者:
    <start-time>2008-09-03T14:43:00+08:00</start-time> 
    其中+08:00 表示东八区
    <job> 元素描述了一个要注册到调度器上的 Job,相当于我们在前面章节中使用 scheduleJob() 方法那样。你所看到的<job-detail> 和  <trigger> 这两个元素就是我们在代码中以编程式传递给方法 schedulerJob() 的参数。前面本质上是与这里一样的,只是现在用的是一种较流行声明的方式。<trigger>元素也是非常直观的:它使用前面同样的属性,但更简单的建立一个 SimpleTrigger。因此仅仅是一种不同的(可论证的且更好的)方式做了上一篇代码 中同样的事情。显然,你也可以支持多个 Job。在上一篇代码 中我们编程的方式那么做的,也能用声明的方式来支持


    <?xml version='1.0' encoding='utf-8'?>
    <quartz xmlns="http://www.opensymphony.com/quartz/JobSchedulingData"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.opensymphony.com/quartz/JobSchedulingData
      http://www.opensymphony.com/quartz/xml/job_scheduling_data_1_5.xsd"
      version="1.5">   
     <job>      
        <job-detail>      
         <name>ScanDirectory1</name>      
         <group>DEFAULT</group>      
         <description>      
               A job that scans a directory for files       
         </description>      
         <job-class>      
                com.vista.quartz.ScanDirectoryJob       
         </job-class>      
         <volatility>false</volatility>      
         <durability>false</durability>      
         <recover>false</recover>      
          
         <job-data-map allows-transient-data="true">      
         <entry>      
           <key>SCAN_DIR</key>      
             <value>D:\dyk\Java\Tomcat\conf</value>      
         </entry>      
        </job-data-map>      
      </job-detail>      
      <trigger>      
        <simple>      
         <name>scanTrigger1</name>      
         <group>DEFAULT</group>      
         <job-name>ScanDirectory1</job-name>      
         <job-group>DEFAULT</job-group>      
         <start-time>2008-09-03T15:00:10</start-time>      
         <!-- repeat indefinitely every 10 seconds -->      
         <repeat-count>-1</repeat-count>      
         <repeat-interval>10000</repeat-interval>      
        </simple>      
      </trigger>      
    </job>       
    <job>      
      <job-detail>      
        <name>ScanDirectory2</name>      
        <group>DEFAULT</group>      
        <description>      
              A job that scans a directory for files       
        </description>      
        <job-class>      
              com.vista.quartz.ScanDirectoryJob       
        </job-class>      
        <volatility>false</volatility>      
        <durability>false</durability>      
        <recover>false</recover>      
        <job-data-map allows-transient-data="true">      
          <entry>      
           <key>SCAN_DIR</key>      
           <value>D:\dyk\Java\Tomcat\webapps\MyTest\WEB-INF</value>      
         </entry>      
        </job-data-map>      
      </job-detail>      
      <trigger>      
        <simple>      
         <name>scanTrigger2</name>      
         <group>DEFAULT</group>      
         <job-name>ScanDirectory2</job-name>      
         <job-group>DEFAULT</job-group>      
         <start-time>2008-09-03T15:00:20</start-time>      
         <!-- repeat indefinitely every 15 seconds -->      
         <repeat-count>-1</repeat-count>      
         <repeat-interval>15000</repeat-interval>      
        </simple>      
      </trigger>      
     </job>   
    </quartz>

    最后我们来看看原来的代码简化成如何了:

    package com.vista.quartz;

    import java.util.Date;       

    import org.apache.commons.logging.Log;       
    import org.apache.commons.logging.LogFactory;       
    import org.quartz.JobDetail;
    import org.quartz.Scheduler;       
    import org.quartz.SchedulerException;       
    import org.quartz.Trigger;
    import org.quartz.TriggerUtils;
    import org.quartz.impl.StdSchedulerFactory;

    public class SimpleScheduler 
    {
        static Log logger = LogFactory.getLog(SimpleScheduler.class);         
        public static void main(String[] args) 
        {       
             SimpleScheduler simple = new SimpleScheduler();       
             try 
             {       
                 // Create a Scheduler and schedule the Job       
                 Scheduler scheduler = simple.createScheduler();         
                 // Jobs can be scheduled after Scheduler is running       
                 scheduler.start();          
                 logger.info("Scheduler started at " + new Date());         
            } 
            catch (SchedulerException ex)
            {       
                 logger.error(ex);       
            }       
        }       
        public Scheduler createScheduler() throws SchedulerException 
        {//创建调度器       
            return StdSchedulerFactory.getDefaultScheduler();
        }   
    }

    posted @ 2012-09-14 18:28 奋斗成就男人 阅读(219) | 评论 (0)编辑 收藏

    Quartz 框架快速入门(一)

    创建一个 Java 工程,引入几个 JAR 到工程中才能成功构建它们。首先,你需要 Quartz 的二进制版本,包的名字是 quartz-<version>.jar。Quartz 还需要几个第三方库;这依赖于你要用到框架的什么功能而定,Commons Digester 库可以在<QUARTZ_HOME>/lib/core 和 <QUARTZ_HOME>/lib/optional 目录中找到。如果出现java.lang.NoClassDefFoundError: javax/transaction/UserTransaction的错误,解决办法是:引入jta.jar包,这个包在quartz-1.6.0/lib/build 下。
    ·创建一个 Quartz Job 类
    每一个 Quartz Job 必须有一个实现了 org.quartz.Job 接口的具体类。这个接口仅有一个要你在 Job 中实现的方法,execute(),方法 execute() 的原型如下:
    public void execute(JobExecutionContext context) throws JobExecutionException;
    当 Quartz 调度器确定到时间要激发一个 Job 的时候,它就会生成一个 Job 实例,并调用这个实例的 execute() 方法。调度器只管调用 execute() 方法,而不关心执行的结果,除了在作业执行中出问题抛出的 org.quartz.JobExecutionException 异常。
    下面是我们的第一个 Quartz job,它被设计来扫描一个目录中的文并显示文件的详细信息.
    package com.vista.quartz;

    import java.io.File;       

    import java.io.FileFilter;

    import java.util.Date;       

          

    import org.apache.commons.logging.Log;       

    import org.apache.commons.logging.LogFactory;       

    import org.quartz.Job;       

    import org.quartz.JobDataMap;       

    import org.quartz.JobDetail;       

    import org.quartz.JobExecutionContext;       

    import org.quartz.JobExecutionException;  



    public class ScanDirectoryJob implements Job 

    {

        static Log logger = LogFactory.getLog(ScanDirectoryJob.class);//日志记录器

        

        public void execute(JobExecutionContext context) throws JobExecutionException 

        {

            //Every job has its own job detail       

            JobDetail jobDetail = context.getJobDetail();       

            // The name is defined in the job definition       

            String jobName = jobDetail.getName();//任务名称       

            
    // Log the time the job started       

            logger.info(jobName + " fired at " + new Date());//记录任务开始执行的时间       

            
    // The directory to scan is stored in the job map       

            JobDataMap dataMap = jobDetail.getJobDataMap();//任务所配置的数据映射表       

            String dirName = dataMap.getString("SCAN_DIR");//获取要扫描的目录       

            
    // Validate the required input       

            if (dirName == null

            {//所需要的扫描目录没有提供       

                 throw new JobExecutionException( "Directory not configured" );       

            }       

            // Make sure the directory exists       

            File dir = new File(dirName);       

            if (!dir.exists()) 

            {//提供的是错误目录       

                throw new JobExecutionException( "Invalid Dir "+ dirName);       

            }       

            // Use FileFilter to get only XML files       

            FileFilter filter = new FileExtensionFileFilter(".xml");       

            //只统计xml文件

            File[] files = dir.listFiles(filter);       

            if (files == null || files.length <= 0) 

            {//目录下没有xml文件       

                logger.info("No XML files found in " + dir);       

                // Return since there were no files       

                return;

            }       

            // The number of XML files       

            int size = files.length;          

            // Iterate through the files found       

            for (int i = 0; i < size; i++) 

            {

                File file = files[i];       

                // Log something interesting about each file.       

                File aFile = file.getAbsoluteFile();       

                long fileSize = file.length();       

                String msg = aFile + " - Size: " + fileSize;       

                logger.info(msg);//记录下文件的路径和大小

            } 

        }

    }
    当 Quartz 调用 execute() 方法,会传递一个 org.quartz.JobExecutionContext 上下文变量,里面封装有 Quartz 的运行时环境和当前正执行的 Job。通过 JobexecutionContext,你可以访问到调度器的信息,作业和作业上的触发器的信息,还有更多更多的信息。在代码中,JobExecutionContext 被用来访问 org.quartz.JobDetail 类,JobDetail 类持有 Job 的详细信息,包括为 Job 实例指定的名称,Job 所属组,Job 是否被持久化(易失性),和许多其他感兴趣的属性。
    JobDetail 又持有一个指向 org.quartz.JobDataMap 的引用。JobDataMap 中有为指定 Job 配置的自定义属性。例如,在代码中我们从 JobDataMap 中获得欲扫描的目录名,我们可以在 ScanDirectoryJob 中硬编码这个目录名,但是这样的话我们难以重用这个 Job 来扫描别的目录了。在后面你将会看到目录是如何配置到 JobDataMap 的。
    execute() 方法中剩下的就是标准 Java 代码了:获得目录名并创建一个 java.io.File 对象。它还对目录名作为简单的校验,确保是一个有效且存在的目录。接着调用 File 对象的 listFiles() 方法得到目录下的文件。还创建了一个 java.io.FileFilter 对象作为参数传递给 listFiles() 方法。org.quartzbook.cavaness.FileExtensionFileFilter 实现了 java.io.FileFilter 接口,它的作用是过滤掉目录仅返回 XML 文件。默认情况下,listFiles() 方法是返回目录中所有内容,不管是文件还是子目录,所以我们必须过滤一下,因为我们只对 XML 文件感兴趣。
    FileExtensionFileFilter 被用来屏蔽名称中不含字符串 “.xml” 的文件。它还屏蔽了子目录--这些子目录原本会让 listFiles() 方法正常返回。过滤器提供了一种很便利的方式选择性的向你的 Quartz 作业提供它能接受的作为输入的文件.
    package com.vista.quartz;

    import  java.io.File;       

    import  java.io.FileFilter;   



    public class FileExtensionFileFilter implements  FileFilter 

    {

         private  String extension;//文件后缀     

         

         public  FileExtensionFileFilter(String extension)

         {       

             this.extension = extension;

         }             

         public   boolean  accept(File file)

         {//只接受指定后缀的文件       

             
    // Lowercase the filename for easier comparison       

             String lCaseFilename = file.getName().toLowerCase();//小写化

             return  (file.isFile() &&(lCaseFilename.indexOf(extension) >  0 )) ?  true : false ;       

         }       

    }
    到目前为止,我们已经创建了一个 Quartz job,但还没有决定怎么处置它--明显地,我们需以某种方式为这个 Job 设置一个运行时间表。时间表可以是一次性的事件,或者我们可能会安装它在除周日之外的每个午夜执行。你即刻将会看到,Quartz Schduler 是框架的心脏与灵魂。所有的 Job 都通过 Schduler 注册;必要时,Scheduler 也会创建 Job 类的实例,并执行实例的 execute() 方法。
    ·编程式安排一个 Quartz Job
    所有的要 Quartz 来执行的作业必须通过调度器来注册。大多情况下,这会在调度器启动前做好。正如前面说过,这一操作也提供了声明式与编程式两种实现途径的选择。
    因为每一个 Job 都必须用 Scheduler 来注册,所以先定义一个 JobDetail,并关联到这个 Scheduler 实例。
    下面的程序提供了一个理解如何编程式安排一个 Job 很好的例子。代码首先调用 createScheduler() 方法从 Scheduler 工厂获取一个 Scheduler 的实例。得到 Scheduler 实例之后,把它传递给 schedulerJob() 方法,由它把 Job 同 Scheduler 进行关联。
    首先,创建了我们想要运行的 Job 的 JobDetail 对象。JobDetail 构造器的参数中包含指派给 Job 的名称,逻辑组名,和实现 org.quartz.Job 接口的全限类名称。我们可以使用 JobDetail 的别的构造器。
    在前面有说过,JobDetail 扮演着某一 Job 定义的角色。它带有 Job 实例的属性,能在运行时被所关联的 Job 访问到。其中在使用 JobDetail 时,的一个最重要的东西就是 JobDataMap,它被用来存放 Job 实例的状态和参数。在代码中,待扫描的目录名称就是通过  scheduleJob() 方法存入到 JobDataMap 中的。
    Job 只是一个部分而已。注意我们没有在 JobDetail 对象中为 Job 设定执行日期和次数。这是 Quartz Trigger 该做的事。顾名思义,Trigger 的责任就是触发一个 Job 去执行。当用 Scheduler 注册一个 Job 的时候要创建一个 Trigger 与这个 Job 相关联。Quartz 提供了四种类型的 Trigger,但其中两种是最为常用的,它们就是在下面要用到的 SimpleTrigger 和  CronTrigger.
    SimpleTrigger 是两个之中简单的那个,它主要用来激发单事件的 Job,Trigger 在指定时间激发,并重复 n 次--两次激发时间之间的延时为 m,然后结束作业。CronTrigger 非常复杂且强大。它是基于通用的公历,当需要用一种较复杂的时间表去执行一个 Job 时用到。例如,四月至九月的每个星期一、星期三、或星期五的午夜。
    为更简单的使用 Trigger,Quartz 包含了一个工具类,叫做 org.quartz.TriggerUtils. TriggerUtils 提供了许多便捷的方法简化了构造和配置 trigger. 本文的例子中有用的就是 TriggerUtils 类;SimpleTrigger 和 CronTrigger 会在后面用到。
    正如你看到的那样,调用了 TriggerUtils 的方法 makeSecondlyTrigger() 来创建一个每10秒种激发一次的 trigger(实际是由 TriggerUtils 生成了一个 SimpleTrigger 实例,但是我们的代码并不想知道这些)。我们同样要给这个 trigger 实例一个名称并告诉它何时激发相应的 Job;与之关联的 Job 会立即启动,因为由方法 setStartTime() 设定的是当前时间
    package com.vista.quartz;



    import java.util.Date;       



    import org.apache.commons.logging.Log;       

    import org.apache.commons.logging.LogFactory;       

    import org.quartz.JobDetail;

    import org.quartz.Scheduler;       

    import org.quartz.SchedulerException;       

    import org.quartz.Trigger;

    import org.quartz.TriggerUtils;

    import org.quartz.impl.StdSchedulerFactory;



    public class SimpleScheduler 

    {

        static Log logger = LogFactory.getLog(SimpleScheduler.class);         

        public static void main(String[] args) 

        {       

             SimpleScheduler simple = new SimpleScheduler();       

             try

             {       

                 // Create a Scheduler and schedule the Job       

                 Scheduler scheduler = simple.createScheduler();       

                 simple.scheduleJob(scheduler);       

        

                 // Start the Scheduler running       

                 scheduler.start();       

        

                 logger.info( "Scheduler started at " + new Date());       

        

            } catch (SchedulerException ex) {       

                 logger.error(ex);       

            }   

            

        }       

        public Scheduler createScheduler() throws SchedulerException 

        {//创建调度器       

            return StdSchedulerFactory.getDefaultScheduler();

        }   

        

        //Create and Schedule a ScanDirectoryJob with the Scheduler       

        private void scheduleJob(Scheduler scheduler) throws SchedulerException 

        {       

             // Create a JobDetail for the Job       

             JobDetail jobDetail = new JobDetail("ScanDirectory",Scheduler.DEFAULT_GROUP,ScanDirectoryJob.class); 

             // Configure the directory to scan       

             jobDetail.getJobDataMap().put("SCAN_DIR","D:\\Tomcat\\conf"); //set the JobDataMap that is associated with the Job.            

             
    // Create a trigger that fires every 10 seconds, forever       

             Trigger trigger = TriggerUtils.makeSecondlyTrigger(10);//每10秒触发一次       

             trigger.setName("scanTrigger");       

             // Start the trigger firing from now       

             trigger.setStartTime(new Date());//设置第一次触发时间            

             
    // Associate the trigger with the job in the scheduler       

             scheduler.scheduleJob(jobDetail, trigger);       

        }       

    }
    假如你有不只一个个 Job (你也许就是),你将需要为每一个 Job 创建各自的 JobDetail。每一个 JobDetail 必须通过 scheduleJob() 方法一一注册到 Scheduler 上。而如果你想重用了一个 Job 类,让它产生多个实例运行,那么你需要为每个实例都创建一个 JobDetail。例如,假如你想重用 ScanDirectoryJob 让它检查两个不同的目录,你需要创建并注册两个 JobDetail 实例
    package com.vista.quartz;



    import java.util.Date;       



    import org.apache.commons.logging.Log;       

    import org.apache.commons.logging.LogFactory;       

    import org.quartz.JobDetail;

    import org.quartz.Scheduler;       

    import org.quartz.SchedulerException;       

    import org.quartz.Trigger;

    import org.quartz.TriggerUtils;

    import org.quartz.impl.StdSchedulerFactory;



    public class SimpleScheduler 

    {

        static Log logger = LogFactory.getLog(SimpleScheduler.class);         

        public static void main(String[] args) 

        {       

             SimpleScheduler simple = new SimpleScheduler();       

             try 

             {       

                 // Create a Scheduler and schedule the Job       

                 Scheduler scheduler = simple.createScheduler();         

                 // Jobs can be scheduled after Scheduler is running       

                 scheduler.start();          

                 logger.info("Scheduler started at " + new Date());         

                 // Schedule the first Job       

                 simple.scheduleJob(scheduler, "ScanDirectory1",ScanDirectoryJob.class,"D:\\conf1", 10);          

                 // Schedule the second Job       

                 simple.scheduleJob(scheduler, "ScanDirectory2",ScanDirectoryJob.class,"D:\\conf2 ", 15);       

            } 

            catch (SchedulerException ex)

            {       

                 logger.error(ex);       

            }       

        }       

        public Scheduler createScheduler() throws SchedulerException 

        {//创建调度器       

            return StdSchedulerFactory.getDefaultScheduler();

        }   

        

        private void scheduleJob(Scheduler scheduler, String jobName,Class jobClass, String scanDir, int scanInterval) throws SchedulerException 

        {         

            // Create a JobDetail for the Job       

           JobDetail jobDetail = new JobDetail(jobName,Scheduler.DEFAULT_GROUP, jobClass);         

           // Configure the directory to scan       

           jobDetail.getJobDataMap().put("SCAN_DIR", scanDir);         

           // Trigger that repeats every "scanInterval" secs forever       

           Trigger trigger = TriggerUtils.makeSecondlyTrigger(scanInterval);         

           trigger.setName(jobName + "-Trigger");         

           // Start the trigger firing from now       

           trigger.setStartTime(new Date());         

           // Associate the trigger with the job in the scheduler       

           scheduler.scheduleJob(jobDetail, trigger);       

      }       

    }



    posted @ 2012-09-14 18:27 奋斗成就男人 阅读(180) | 评论 (0)编辑 收藏

    使用Jquery实现复选框的全选和反选

    使用JQuery实现复选框的全选和反选
         jQuery(document).ready(function($) {
              $("#checkAll").click(function(){
                 if(this.checked){
                      $("[name='complaintReasonVO.complaintReasons']").attr("checked",'true');  // 全选
                 }else {
                     $("[name='complaintReasonVO.complaintReasons']").removeAttr("checked");    // 反选
                 }
             });







    posted @ 2012-09-10 09:47 奋斗成就男人 阅读(117) | 评论 (0)编辑 收藏

    ibatis动态参数和集合参数配置

    iterate 

    // 此处必须要$,不能用#property<result property="" column=""/>    ibatis是轻量的ORM,类似于一个半自动化化数据操作框架。而hibernate是全自动的ORM。
        ibatis主要是让实体类与数据库的字段名称一一对应,然后在xml编写操作数据库的SQL语句。
        ibatis数据库操作主要包括增删查改。
       主要包括:一:在代码中:
                         通过sqlMapper.queryForList("sql_id",param),其中:sql_id就是我们在xml中编写的sql语句id号(通过此id找到数据库sql语句)
                         parm就是查询条件参数值(一般是一个参数(也有两个参数或者无参数)),参数值可以使对象,int或者String类型。
                    二:在xml编写sql语句,主要包括增删查改
                        在写sql语句前,可以做一些其他的简单说明:比如,类别名(类似给类弄一个简称,方法类以后使用),实体类与数据字段一一对应说明等等。
                        <sqlMap namespace="空间名称">
                    <typeAlias alias="teacher" type="com.wsw.ibatis.bean.Teacher"/>        // 给类取一个别名,方便以后在后来使用。
                    <resultMap class="" id="">                                                             // 给返回的类定一个id号,以后就可以直接用该id表示这个类    
                    <result property="属性名" column="数据库字段名"/>                      // 返回的实体类的属性与数据库字段匹配,两者名称可相同或者不同 
                                   
    <result property="属性名" column=" 数据库字段名"/>
                    </resultMap>
                    <parameterMap class="" id="">                                                       // 参数类,用于执行sql的参数值,与上面的返回类不同。
                <parameter property="属性名" jdbcType="属性类型"/>                                        
                    </parameterMap>
                       </sqlMap>
                      还有就是: parameterClass 表示参数类,用于做参数值。
                                    parameterClass  表示返回值类,用于返回值。
                                    在这种情况下 ,没有把实体类属性和数据库的字段一一写出,表示实体类属性和数据库的字段名称和类型完全一致。
                   ----------------------------------------------------------------------------------------------------------------------------
                        (1):增:     <insert id="addTeacher" parameterClass="com.wsw.ibatis.bean.Teacher">
                                               insert into teacher (id,username, age)values (#id#,#username#,#age#)
                                            </insert>
                                 
                        (2):删:   <delete id="deleteAccountById" parameterClass="String">
    delete from teacher where id = #id#
    </delete>

                       (3):改: <update id="updateTeacher" parameterClass="com.wsw.ibatis.bean.Teacher">
    update teacher set username=#username#,age= #age# where id=#id#
    </update>

                       (4):查:    <!-- 查找某一条记录 -->
                                    <select id="selectTeacherById" parameterClass="int" resultClass="com.wsw.ibatis.bean.Teacher">
                                select * from teacher where id = #id#
    </select>
                                           <!-- 查询所有记录 -->
                                    <select id="selectAllTeacher" resultClass="com.wsw.ibatis.bean.Teacher">
    select * from teacher
    </select>
                  ===============================================================================================
                        (5):动态按照条件查询 (如果需要循环迭代,最好用list,不要用数组)
                                           <!-- 按照提交参数记录 -->
    <select id="selectSomeTeacher" parameterClass="com.wsw.ibatis.bean.Teacher"                                                                   resultClass="com.wsw.ibatis.bean.Teacher" >
                                                select * from teacher 
                                    <dynamic prepend="WHERE">                 // 表示动态
                                  <isNotEmpty prepend="AND" property="username">        // isNotEmpty 表示如果非空,property表示类属性名
                                  <![CDATA[ username in ]]>        
                                                                          <iterate conjunction="," open="(" close=")" property="username" >  // iterate 表示迭代
                                                $usernames[]$              // 此处必须要$,不能用#                     // 迭代必须是集合list 千万不能
                                            </iterate>                                                                                             //是数组
                                   <![CDATA[]]>
                                                    </isNotEmpty>
    <isNotEmpty prepend="AND" property="age">
    (age = #age#)                              // 此处最好用#,不要用$
    </isNotEmpty>
    </dynamic>
    </select>
      

    posted @ 2012-08-31 00:19 奋斗成就男人 阅读(5125) | 评论 (0)编辑 收藏

    struts2表单传值

        struts2表单传值类似栈,然后在action中把表单的各个名称用类属性表示就可以了。然后只需要加上get和set方法
       (1): 文本框:<s:textfield />
                  提交: <s:textfield name="paramname"/> 
                  Ation处理:用String或者int类型的paramname 表示
                  接收:(1):<s:textfield name="paramname "  value="%{paramname }"/>
                          (2):<s:property value="paramname" / "# paramname">
       (2):单选框:<s:radio />
                提交和接受:<s:radio list="{'男','女'}" name="sex" label="性别"/> 
               
       (3):多选框:<s:select />
                 提交和接收:<s:checkboxlist name="hobby" listKey="key" listValue="value" list="#{'1':'篮球', '2':'足球', '3':'乒乓球'}"  label="爱好"/>其中key表示值,而value指显示的文字。
                Action处理:用一个list集合表示(注意:千万不要用String[] 数组表示,否则,值无法传回)
       (4):下拉框:<s:select />
               提交和接受:<s:select list="#{1:'北京',2:'上海',3:'广东'}"  label="abc" listKey="key"  listValue="value"  name="address"/>
              Action处理:可以用一个list数组或者String 字符串表示都可以。
    =====================================================================================
    其中:一般的表单都有三种方式传值:
    (1):类似于set集合,只显示值,其中里面就是值

    <s:select list="{'aa','bb','cc'}" theme="simple" headerKey="00" headerValue="00"></s:select>

     (2):类似于map,list前面是value值,后面是显示的值

     <s:select list="#{1:'aa',2:'bb',3:'cc'}"  label="abc" listKey="key" listValue="value"  headerKey="0" headerValue="aabb">

     3.从action-->jsp页面:

     <%

     HashMap map = new LinkedHashMap();

    map.put(1,"aaa");map.put(2,"bbb");

    map.put(3,"ccc");

    request.setAttribute("map",map);

    request.setAttribute("aa","2");

    %>

    JSP页面:
     <s:select list="#request.map"  label="abc" listKey="key" listValue="value" value="#request.aa"  headerKey="0" headerValue="aabb"></s:select>

    posted @ 2012-08-30 22:49 奋斗成就男人 阅读(1475) | 评论 (2)编辑 收藏

    Eclipse Debug不为人知的秘密

    Debug视图

    认识debug视图,红色部分框为线程堆栈视图,黄色部分框为表达式、断点、变量视图,蓝色部分为代码视图。



     线程堆栈视图

    分别介绍一下这几个按钮的含义:

    1.表示当前实现继续运行直到下一个断点,快捷键为F8。

    2.表示打断整个进程

    3.表示进入当前方法,快捷键为F5。

    4.表示运行下一行代码,快捷键为F6。

    5.表示退出当前方法,返回到调用层,快捷键为F7。

    6.表示当前线程的堆栈,从中可以看出在运行哪些代码,并且整个调用过程,以及代码行号



     

    变量视图

    1.为变量名视图,显示当前代码行中所有可以访问的实例变量和局部变量

    2.显示所有的变量值

    3.可以通过该窗口来改变变量值



     

    断点视图

    1.显示所有断点

    2. 将当前窗口1中选中的端口失效,再次点击启用。

    3.异常断点



     

    表达式视图

    表达式视图:表达式视图是Debug过程中较为常用的一个视图,可以对自己的感兴趣的一些变量进行观察,也可以增加一些自己的表达式,也可以查看一行代码的运行结果。

    1.表达式

    2. 点击此可以新增一个表达式



     

    代码视图

    代码视图:用来显示具体的代码。其中绿色部分是指当前将要执行的代码



     

     

    场景一:小明辛苦了两天终于将自己的负责的任务完成了,第二天转测后,测试找到了小明说,小明的程序有bug,可以是小明经过仔细调试,发现本地没有任何问题,但是测试的环境上确实有问题,所以小明遇到了难题,测试的环境linux,又不能上去linux去debug,小明这个时候想要是Linux也可以debug就好了.

    远程debug

    远程debug:远程debug顾名思义,能够将远程操作系统上的任何java进行debug,但是有前提是本地需要有同步的代码。

    1.远程debug的步骤是在远程操作系统上启动java进程时增加特殊的

    -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=$DEBUG_PORT,server=y,suspend=n

    2.在Eclipse中新建一个Remote Java Application

    远程debug

    1.打开Debug Configurations视图

    2.右击Remote Java Application,

    New

    3.选择源码工程

    4.输入远程IP和端口,端口即服务

    端的$DEBUG_PORT,点击OK。




     
     

     

    场景一:小明写了一个任务执行者,该执行者不间断的执行一些任务,在现网上运行了一段时间后,发现有概率的出现一些故障,发现运行一段时间后,该任务者异常退出了,退出的因为是空指针,可以小明想要在本地debug,不知道断点打在哪里,该问题是概率事件,不一定会出现,所以小明debug几遍下来后,头晕眼花,连代码都看不清楚了,小明想要是能有个断点每当出现空指针异常的时候就停下来让他发现问题,那该多好呀。

    异常断点

    异常断点:在定位问题的过程中,常常会遇到断点无法打到合适的位置,以至于和问题的触发点千差万别,所以这个时候不妨试试异常断点,顾名思义,异常断点是指抛出某种异常后自动挂起的断点。

    点击红色部位,增加一个异常断点



     

    输入想要定位的异常类型,例如NullPointerException,这样系统中抛出任何NullPointerException异常后,都会挂起当前线程,给你机会去定位问题。

     

    场景一:小明写了一个巨大的循环,在调测代码时,小明发现每当循环到第100000次的时候,就是出现问题,没有达到自己的预期,于是小明在循环里打了个断点,想看看到底怎么回事,可小明万万没有想到,想要到达100000次循环是多么的困难,小明这个时候已经开始浮想联翩,如果能有这样的断点:

                 If 循环次数== 100000,线程停下来

    条件断点

    如右图,循环1000次,如果想要在循环到500

    次的时候停下来,可以创建一个条件断点,右

    击断点悬着Breakpoint Properties。



     

    选中Enable Condition

    在空白处,添加你自己的条件,如果条件返回true,线程会被挂起,如果为false,则忽略该异常

    Hit Count为该断点经过多少次后,正式挂起线程,如果设置为500,则表达前499次,经过该断点都不会停下,当第500次,该断点会挂起当前线程。

     

     

    表达式

    表达式可以查看一些在当前代码中没有的命令行,方便定位问题。

     

    场景一:小明最近遇到一个难题,在调用一个第三方插件时总是会有问题,小明怀疑是第三方插件的bug,但小明没有找到源码不能进行debug,小明该怎么办呢?

    Debug定位第三方插件的问题

    1.使用反编译工具将代码反编译

    2.将反编译后的源码进行过滤

    3.修复源码编译错误

    4.进行debug

    Debug一些经验

    1.尽量减少debug,少用debug,优秀的程序员总是花80%的时间来思考如何解决问题,20%的时间来动手完成代码,而糟糕的程序员总是用20%的时间去写代码,80%的时间去调试代码,动手之前尽量想好如何去做,并且已经为你自己的思路做了充分的实验。

    2.尽可能的提高debug的效率,设置合适的断点,使用快捷键。

    3.debug的F6快捷键经常用到,它与金山词霸的快捷键冲突,所以在debug的时候最好将金山词霸关掉。

    4.debug的表达式是可执行代码,将会对代码结果产生永久性影响,在调试时注意,经常将不用的表达式清除掉。

    posted @ 2012-08-30 18:16 奋斗成就男人 阅读(2848) | 评论 (0)编辑 收藏

    通过存储过程对SQLSERVER2005分页

    1 通过select top进行分页查询   
    /*查询原理:需要查询第N页时,首先取到前N页的所有数据,然后排除前N-1页的数据,就是第N页的数据*/  
    create  PROCEDURE GetDataWithPage  
    (   
           @pageIndex  int = 1,           -- 页码  
          @pageSize   int = 20,          -- 页尺寸    
    )  
    as  
        begin  
         if @pageIndex < 1  
    begin  
    Set @pageIndex=1  
    end                   
      
      
    --如果是第一页时要执行的语句  
      if @PageIndex = 1  
          begin  
                  select top ((@PageIndex)*@PageSize)   
                   field1,field2,--查询字段  
                   fieldOrderby --排序字段,按什么字段分页的字段,建议使用主键,或者唯一键  
                   from tableName --查询表名称  
                  where id>100 --查询条件  
                  order by fieldOrderby --排序字段,按什么字段分页的字段,  
                 select count(*) as Total from tableName where id>100--返回总记录数  
        end  
      else    
             begin  
                     select top ((@PageIndex)*@PageSize) --取出前PageIndex页的数据  
                                field1,field2,--查询字段  
                                fieldOrderby --排序字段,按什么字段分页的字段,建议使用主键,或者唯一键  
                                into #tempTable --插入临时表  
                                from tableName --查询表名称  
                                where id>100 --查询条件  
                               order by fieldOrderby --排序字段,按什么字段分页的字段,  
                      -----取出前pageIndex页数据插入临时表  
      
                     ------排除前pageIndex-1页的数据,取出第pageIndex的数据  
                      select top (@PageIndex) --  
                                 field1,field2,--排序字段  
                                fieldOrderby --  
                               from #tempTable --从临时表中取数据  
                              where fieldOrderby --  
                              not in (select  top ((@PageIndex-1)*@PageSize) fieldOrderby from #tempTable)  
                            ---- 从临时表取出 pageIndex的数据   
                                ----可以根据升序或者降序把not in 改为 <min(fieldOrderby)或者>max(fieldOrderby)  
                     select count(*) as Total from tableName where id>100--返回总记录数  
           end  
    end  


    2通过系统存储过程进行分页查询

    [sql] view plaincopy
     /*  
     一共返回三个表第一个表为空 查询字符串的条件中有 like ,in 可能出现问题,具体出现原因不明,第二个表包含总页数,总行数,  
    当前页第三个表包含查询记录  
      
    */  
    create   procedure [dbo].[GetOnePageData]  
       @sqlstr nvarchar(4000), --查询字符串  ,就是一般的查询语句,不需要top关键字  
       @currentpage int, --第N页  
       @pagesize int --每页行数  
    as  
       set nocount on  
       declare @P1 int, --P1是游标的id  
       @rowcount int--  
        exec sp_cursoropen @P1 output,@sqlstr,@scrollopt=1,@ccopt=1,@rowcount=@rowcount output  
       --定义与游标和游标选项相关联的 SQL 语句,然后填充游标。  
       --选择总页数,总行数,当前页  
        select ceiling(1.0*@rowcount/@pagesize) as TotalPages,@rowcount as TotalRows,@currentpage as CurPage  
        set @currentpage=(@currentpage-1)*@pagesize+1  
       --查询记录  
        exec sp_cursorfetch @P1,16,@currentpage,@pagesize --从游标中提取一行或一个行块。  
       --返回值  
        exec sp_cursorclose @P1--关闭并释放游标  
         set nocount off  
    go  


    3 通过新函数ROW_NUMBER()进行分页查询

    [sql] view plaincopy
    /*  
    适用于sql2005,据调查此方法限制最少,性能最佳  
    返回两个表,第一个表包含总行数,第二个表是查询到的记录  
    --分页查询的原理:  
    --1.先将预分页内容按照排序条件加上自增列导入到临时表中(或表变量)  
    --2.针对临时表操作,找到相应的N页对应的自增列编码范围  
    --3.根据第N页对应的自增列编码范围,查找第N页内容  
       
    --需要注意的是:  
    --第一是添加自增列,确定行号  
    --第二缩减中间处理过程的操作数据量  
      
    */  
      
    create  proc [dbo].[GetOnePageData]--//  
    (  
        @page int,  
        @pagesize int  
    )  
    as  
    begin      
            select top  (@pagesize*@page)  ROW_NUMBER() --可以减少处理的数据,加快速度  
             OVER(ORDER BY NodeID) as rowNum,--按什么字段分页的字段,不需要唯一性  
            NodeID,NodeName,ControlIP --查询字段  
            into #temp --插入临时表  
            from TableName   --  查询表名称   
            where NodeID>100 --查询条件  
             
           select count(*) from #temp--总记录条数  
           select * from #temp where rowNum>@pagesize*(@page-1) and rowNum<=@pagesize*@page--  
    end   

      综述,如果需要通用的存储过程,可以把第一或者第三种分页方法进行改写,在数据库拼字符串,但性能会差好多。这或许就是通用和性能之间的矛盾吧。















    posted @ 2012-08-29 21:31 奋斗成就男人 阅读(792) | 评论 (0)编辑 收藏

    SQL分页语句

    有关分页 SQL 的资料很多,有的使用存储过程,有的使用游标。本人不喜欢使用游标,我觉得它耗资、效率低;使用存储过程是个不错的选择,因为存储过程是经过预编译的,执行效率高,也更灵活。先看看单条 SQL 语句的分页 SQL 吧。

    方法1:
    适用于 SQL Server 2000/2005
    SELECT TOP 页大小 *
    FROM table1
    WHERE id NOT IN
              (
              
    SELECT TOP 页大小*(数排序-1) id FROM table1 ORDER BY id
              )
    ORDER BY id
    原理:其中id最好是主键或者索引,这样查询速度比较快)。由页码数,通过sELECT TOP 页大小*(页数排序-1) id FROM tablename ORDER BY id 获取最前面的那几行(top),然后通过id not in 表示要查询的那一页是最后的那一部分,而通过top +页大小表示去最后那一部分记录的最前面的那几天记录(每页记录数)。
    为什么直接取最后那一部分的,因为sql只有去前面几条记录top,而没有去最后几条记录的关键字。
    方法2:
    适用于 SQL Server 2000/2005
    --顺序写法:
     SELECT TOP 页大小 *
     FROM table1
     WHERE id >=
     (
     SELECT ISNULL(MAX(id),0) 
     FROM 
     (
     SELECT TOP 页大小*(页数-1)+1 id FROM table1 ORDER BY id
     ) A
     )
     ORDER BY id
     
     --降序写法:
     SELECT TOP 页大小 *
     FROM table1
     WHERE id <=
     (
     SELECT ISNULL(MIN(id),0) 
     FROM 
     (
     SELECT TOP 页大小*(页数-1)+1 id FROM table1 ORDER BY id Desc
     ) A
     )
     ORDER BY id Desc

    方法3:
    适用于 SQL Server 2005

    SELECT TOP 页大小 * 
    FROM 
            (
            
    SELECT ROW_NUMBER() OVER (ORDER BY id) AS RowNumber,* FROM table1
            ) A
    WHERE RowNumber > 页大小*(页数-1)


    说明,页大小:每页的行数;页数:第几页。使用时,请把“页大小”和“页大小*(页数-1)”替换成数字。

     

     

     

    其它的方案:如果没有主键,可以用临时表,也可以用方案三做,但是效率会低。
    建议优化的时候,加上主键和索引,查询效率会提高。

    通过SQL 查询分析器,显示比较:我的结论是:
    分页方案二:(利用ID大于多少和SELECT TOP分页)效率最高,需要拼接SQL语句
    分页方案一:(利用Not In和SELECT TOP分页)   效率次之,需要拼接SQL语句
    分页方案三:(利用SQL的游标存储过程分页)    效率最差,但是最为通用

    posted @ 2012-08-29 18:36 奋斗成就男人 阅读(448) | 评论 (0)编辑 收藏

    iBatis2之SqlMap配置总结(18条)

    iBatis2之SqlMap配置总结(18条)  

      订阅

    SqlMap的配置是iBatis中应用的核心。这部分任务占据了iBatis开发的70的工作量。
    1、命名空间:
      <sqlMap namespace="Account">,在此空间外要引用此空间的元素,则需要加上命名空间名。
     
    2、实体的别名:
      <typeAlias alias="Account" type="com.lavasoft.ibatissut.simple.domain.entity.Account"/>
      如果有用到的全名的地方,可以用别名代替,受命名空间约束。
     
    3、插入操作
        对于自增主键的表,插入可以不配置插入的主键列。否则是必须的。
     
    4、获取主键
         插入语句之前配置:主要是针对Sequence主键而言,插入前必须指定一个主键值给要插入的记录。Oracle、DB2亦如此,方法是在插入语句标签<insert....>之前配置上:
        <insert id="insertAccount" parameterClass="Account">
            <selectKey resultClass="long" keyProperty="sctId">
                SELECT SEQ_TEST.NEXTVAL FROM DUAL
            </selectKey>   
            insert into .... ........
        </insert>
      
        插入语句之后配置:蛀牙是针对自增主键的表而言,这类表在插入时不需要主键,而是在插入过程自动获取一个自增的主键。比如MySQL
        <insert id="insertAccount" parameterClass="Account">
            <selectKey resultClass="long" keyProperty="sctId">
                SELECT LAST_INSERT_ID() 
           </selectKey>   
            insert into .... ........
        </insert>
     
       当然,是否需要配置<selectKey>根据情况,只要能保证记录有主键即可。一旦配置了<selectKey>,就可以在执行插入操作时获取到新增记录的主键。 
     
    6、SQL入参parameterClass
      插入语句入参:parameterClass="类别名"  来设定。
      查询语句入参:可以设定类别名,也可以设定为map,也可以设定为iBatis支持的原生类型(比如string、int、long等),当只有一个原生类型入参时,则在SQL中用value关键字来引用。比如:
        <select id="getById"  parameterClass="long" resultMap="result_base">
            select * from customer where id = #value#
        </select>
        map是最强大的入参方式,任何入参方式都可以转换为这种入参方式,因为iBatis仅接受一个入参,当几个参数分布在不同对象中的时候,将这些对象的属性(或者对象本身put)到map中,然后一次传递给sql语句是非常有效。可以自己写一个将对象或者对象集合转换为map的工具(我已经实现一个了)。
        另外,map的中的元素(比如pobj)是个复杂对象,则还可以在SQL中以#pobj.protyename#的格式来引用其中内嵌的属性。当然不推荐这么干。
     
    7、返回值参数类型
          返回值参数也同样有两种类型,一种是对象类型resultClass="Account",一种是resultMap="AccountResult"。这两种类型的选择常常会令人迷惑不解,一言明其理:
    当结果集列名和类属性名完全对应的时候,则应该使用resultClass来指定查询结果类型。当然有些列明不对应,可以在sql中使用as重命名达到一致的效果。
     
    当查询结果列名和类属性名对应不上的时候,应该选择resultMap指定查询结果集类型。否则,则查询出来填充的对象属性为空(数字的为0,对象的为null)。
     
    但是实际上resultMap是对一个Java Bean的映射,需要先定义xml的映射后,才可以引用,例如:
        <resultMap id="AccountResult" class="Account">
            <result property="id" column="ACC_ID"/>
            <result property="firstName" column="ACC_FIRST_NAME"/>
            <result property="lastName" column="ACC_LAST_NAME"/>
            <result property="emailAddress" column="ACC_EMAIL"/>
        </resultMap>
        resultMap映射的结果的目的就是要将查询的结果集绑定到映射对象的属性上。
     
       不管使用哪种返回值参数类型,其最终目的就是要把每条记录映射到一个类的对象或者对象集合上,如果有某个类属性映射不上,则在得到的这个对象或对象集合中这个属性为空。映射的属性可以是表与实体中的一部分。不要同时使用两种返回值参数类型,这样只会令人迷惑。
     
    8、查询结果集分组
        查询结果集排序有两种方式:一是在结果集映射上定义<resultMap id="result" class="bar" groupBy="id">,另一种就是在SQL语句中分组。建议在SQL语句中分组,以获得更大的可控制性。
     
    9、SQL中参数的引用
         SQL中引用parameterClass的参数有三种方式:
         iBatis内置支持的类型,比如int、string,使用#value#来引用,这个value是关键字,不可变。
         map类型的参数,使用#keyName#来引用,keyName为键名。
         复杂对象的参数,使用#propertyName#来引用,propertyName类属性的名字。
     
    10、模糊查询中参数的引用
        模糊查询是针对字符串而言的,如果遇到两个单引号要包含一个参数,则不能再用#来引用变量了,而应该改为$,比如:'%$varName$%',当然,也可以使用 '%' || #varname# || '%' 来绕过此问题。
     
    11、SQL片段
           可以通过<sql id="sql_xxx">...</sql>定义SQL片段,然后<include refid="sql_xxx"/>来在各种语句中引用。达到服用目的,
     
    12、动态SQL
          可以通过使用动态SQL来组织灵活性更大的更通过的SQL,这样极大减少了编码量,是iBatis应用的第二大亮点。
         比如:一个动态的where条件
                    <dynamic prepend="where">
                            <isNotEmpty prepend="and" property="$$$$$">
                                    $name like '%'|| #$name# ||'%'
                            </isNotEmpty>
                            <isGreaterThan prepend="and" property="$$$$$" compareValue="$$$number">
                                    $code like '%'|| #$code# ||'%'
                            </isGreaterThan>
                    </dynamic>
         当然,prepend表示链接关键字,可以为任何字符串,当为sql关键字时,iBatis自动判断是否应该添加该关键字。该语法也很简单,关键是要会用心思考组织动态SQL。
        这里面有一点要注意:区别<isNotEmpty>和<isNotNull>区别,当为空空串时<isNotEmpty>返回true,当为空串时<isNotNull>返回真。哈哈,自己体会吧,说了反而啰嗦。
     
    13、结果集映射继承
    结果集映射的继承的目的是为了映射定义的复用,比如下面定义了两个映射,AccountResult继承了base:
        <resultMap id="base" class="Account">
            <result property="id" column="ACC_ID"/>
            <result property="firstName" column="ACC_FIRST_NAME"/>
            <result property="lastName" column="ACC_LAST_NAME"/>
        </resultMap>
        <resultMap id="AccountResult" class="Account" extends="Account.base">
            <result property="emailAddress" column="ACC_EMAIL"/>
        </resultMap>
    这样,就很容易扩展了一个映射策略。
           
    14、查询注入
    查询注入是在一个查询中嵌入另外一个查询,这样做的目的是为了实现实体对象之间的关联关联关系(一对一、一对多、多对多)分单项双向。有关这些内容,是比较复杂的,笔者对此做了深入研究,并分别写了三篇来讲述。
     
    查询注入的实现就是在实体属性为另外一个实体或者实体集合的时候,引入一个相关的查询来实现,例如,客户和订单的映射关系:
    public class Customer {
        private Long id;
        private String name;
        private String address;
        private String postcode;
        private String sex;
        private List<Orders> orderlist = new ArrayList<Orders>();
     
        <resultMap id="result" class="customer">
            <result property="id" column="id"/>
            <result property="name" column="name"/>
            <result property="address" column="address"/>
            <result property="postcode" column="postcode"/>
            <result property="sex" column="sex"/>
            <result property="orderlist" column="id" select="orders.findByCustomerId"/>
        </resultMap>
     
    在这个映射中,为了查询客户的时候,能查询到相关的订单,可以在映射orderlist属性的时候,将其指向另外一个查询orders.findByCustomerId,这个查询是以Customer的id为参数来查询的。
     
    select="orders.findByCustomerId"这个查询定义如下:
        <select id="findByCustomerId" resultMap="result_base" parameterClass="long">
            select * from orders where customerId = #value#
        </select>
     
    原理就是这么简单,然后根据实际情况,可以自由实现实体间的关联关系。
     
    14、iBatis的分页查询
    iBatis的分页有两种方式,一点都不神秘,不要被网上的流言所迷惑。
    第一种方式:结果集筛选分页。先执行部分页的SQL查询语句,然后得到一个ResultSet,然后根据分页范围选择有效的记录填充到对象中,最终以集合的形式返回。对于10w条一下的记录的表,不存在性能问题,如果存在,你可以选择第二中方式。
    第二种方式:SQL分页,通过组装分页类型的SQL来实现分页。这个关键在于分页参数的传递和分页SQL的构建。分页SQL构件每种数据库都不一样,不说了。分页参数的传递却可以通用。我主张用map分装入参,连同分页参数一块传递进来,就搞定了。如果原来没有考虑到分页,而用的是对象做参数,则可以通过apache 的 beanutils组件来实现一个object到map之间的转换工具,问题迎刃而解。
     
    当然,这还不是分页查询应用的最高境界。思考,分页需要计算一个总记录数,记录数执行的sql返回值是count(?),条件是除了分页以外的条件,因此应该将查询SQL静态分开,以MySQL为例,可以将查询分为查什么,和什么条件两部分,在条件部分对分页参数进行动态判断,如果分页参数就不分页,如果有则分页。这样最后只需要两个组装的sql就可以计算总数和分页查询了。大大简化了问题的难度。 Oracle的解决思路也一样,不一样的地方就是拼装分页SQL改变了。
     
    15、执行存储过程的配置
    SQL Map 通过<procedure>元素支持存储过程。下面的例子说明如何使用具有输出参数
    的存储过程。 
        <parameterMap id="swapParameters" class="map">
            <parameter property="email1" jdbcType="VARCHAR" javaType="java.lang.String" mode="INOUT"/>
            <parameter property="email2" jdbcType="VARCHAR" javaType="java.lang.String" mode="INOUT"/>
        </parameterMap>
        <procedure id="swapEmailAddresses" parameterMap="swapParameters">
            {call swap_email_address (?, ?)}
        </procedure> 
    调用上面的存储过程将同时互换两个字段(数据库表)和参数对象(Map)中的两个 email地址。如果参数的 mode 属性设为 INOUT 或 OUT,则参数对象的值被修改。否则保持不变。 
    注意!要确保始终只使用 JDBC 标准的存储过程语法。参考 JDBC 的 CallableStatement
    文档以获得更详细的信息。
     
    16、就是iBatis中各种id的命名了,这个看起来小菜一碟,但是搞砸了会很痛苦。建议如果有DAO层的话,DAO接口的名字和SQL语句id的名字保持一致。同时,在DAO中将save和update封装为一个方法(从Hibernate中学来的),这是非常好的。也可以直接在SQL层将插入和更新柔和在一块,太复杂,有点影响效率,这见机行事了。
     
       另外Spring提供了各种数据操作模板,通过模板,擦做数据也就是“一句话”的问题,写个DAO还有必要么,尤其对iBatis来说,根本没有必要。这样,就需要在领域活动层的设计上下功夫了。
     
    17 、iBatis的查询也可以配置缓存策略,缓存的配置很复杂,分很多中情况,可以参看附件中的iBATIS-SqlMaps-2_cn.pdf的39页内容,有详细介绍。
     
    18、偷懒的最高境界,让程序去干哪里80%的体力活。自己仅仅把把关。任何重复的活动都有规律可循的,一旦发现了其中的规律,你就可以想办法把自己从中解脱出来。
        iBatis也不例外,每个表都有增删改查、分页等操作。对应在每个DAO方法上亦如此。可以通过数据库生成sqlmap、entity、dao,然后将这些东西改吧改吧就完成大部分的工作量。本人已经实现过了,当然开发这个工具的前提是你对iBatis有深入研究和理解。
     
    -------------------------------------------------
    下面是iBatis开发指南中内容:
     
    附录:容易出错的地方 
    本附录是译者添加的,列出了初学者容易出错的地方,作为完成快速入门课程后的学习
    笔记,可以让初学者少走些弯路。仅供参考。 
    1)  在 parameterMap 和 resultMap 中,字段数据类型是 java.sql.Types 类定义的常量名
    称。常用的数据类型包括 BLOB,CHAR,CLOB,DATE,LONGVARBINARY, 
    INTEGER,NULL,NUMERIC,TIME,TIMESTAMP 和 VARCHAR 等。 
    2)  对于数据表中 NULLABLE 的字段,必须在 parameterMap 和 resultMap 中指定字段
    的数据类型。 
    3)  对于数据类型是 DATE,CLOB 或 BLOB 的字段,最好在 parameterMap 和 resultMap中指定数据类型。 
    4)  对于二进制类型的数据,可以将 LONGVARBINARY 映射成 byte[]。 
    5)  对于文本类型较大的数据,可以将 CLOB 映射成 String。 
    6) Java Bean 必须拥有缺省的构造器(即无参数的构造器)。 
    7) Java Bean 最好实现 Serializable 接口,以备应用的进一步扩展。
     
    本人认为:尽量避免在每个入参后面附加参数的类型。以保持配置简洁,并且本人在长期开发中,没有发现必须要那么做。

    posted @ 2012-08-28 00:42 奋斗成就男人 阅读(501) | 评论 (0)编辑 收藏

    struts2传值

        Struts2传值比struts1.X要方便多了。主要包括:页面--->Action   Action--->页面两个方面
       (1):页面到--->Action ,其中页面写法如下:
          <s:form action="/ssh/reg.action" method="post">
            <s:textfield label="UserName:" name="username"></s:textfield>                   //在action中直接写username属性和get和set方法
            <s:textfield label="Age:" name="person.age"></s:textfield>                         //在action中写对象Person person和get和set方法。注意:此处绝对不能写类名:Person,而应该是对象person 
            <s:textfield label="Address:" name="person.address"></s:textfield>              // 和person.age类似
            <s:submit value="Login"></s:submit>
        </s:form>

      (2):action类写法:可以继承或者不继承ActionSupport类。注意是属性和get和set方法
         public class RegAction extends ActionSupport{
        
        private Person person;
        private String username;
        private List<Person> personList;
        public List<Person> getPersonList() {
            return personList;
        }
        public void setPersonList(List<Person> personList) {
            this.personList = personList;
        }
        public String getUsername() {
            return username;
        }
        public void setUsername(String username) {
            this.username = username;
        }
        public Person getPerson() {
            return person;
        }
        public void setPerson(Person person) {
            this.person = person;
        }
       /**其中还可以加单一属性,对象,集合(包括list和map)**/
        @Override
        public String execute() throws Exception {
            List<Person> personList1 = new ArrayList<Person>();
            Person person = new Person();
            person.setAddress("hunan");
            person.setAge(25);
            Person person1 = new Person();
            person1.setAddress("beijing");
            person1.setAge(35);
            personList1.add(person);
            personList1.add(person1);
            this.setPersonList(personList1);
            return SUCCESS;
        }
    }

    (3):action---->页面
              (1):单一属性:<s:property value="username"/>      //属性名
              (2):对象:<s:property value="person.address"/>   // 对象名+属性名
              (3):list对象:List对象和Map对象        
                 <s:iterator value="personList" id="Person">           // value是集合对象名,id是别名,可以随便取
                    <s:property value="#Person.age"/>                // #+别名+属性名 其中#符号不可以缺少。
                    <s:property value="#Person.address"/>           // 同上
                </s:iterator>
            (4)<s:iterator value="map" id="id" status="st">      // value是集合对象名,id是别名,也可省,status也可以省。
                     key : <s:property value='key'/>                   // map的key值,其中,values只能为key或者value,不能为其他。
                     value:<s:property vlaue='value'/>                //同上
                 </s:iterator> 
    总结:在传值的时候,也可以采用servlet或者struts1.X的方式用request,session 进行传值。比如:request/session.setAttribute(name,values)等方式。
    然后在页面中,在使用request/session.getAttribute(name);但是不建议这么去做,建议还是用struts2的方式传值。





















    posted @ 2012-08-27 23:30 奋斗成就男人 阅读(947) | 评论 (0)编辑 收藏

    struts2基础

        
        struts2不是从strus1.X继承,而是从xwork继承而来。在使用struts中,尽量少用到struts的内容。
        1):导入strusts2的基本jar包:struts2-core-2.2.3.1.jar  xwork-core-2.2.3.1.jar

     ognl-3.0.1.jar  freemarker-2.3.16.jar   commons-logging-1.1.1.jar  commons-lang-2.5.jar  commons-io-2.0.1.jar  commons-fileupload-1.2.2.jar  commons-beanutils-1.7.0.jar javassist-3.11.0.GA.jar

    2):编写jsp页面。注意:form表单值为:form=/工程名/包的命名空间(namespace)/包名称(package)/处理名(action)”

    3):编写web.xml配置文件:

     

     <?xml version="1.0" encoding="UTF-8"?>

    <web-app version="2.5"

        xmlns="http://java.sun.com/xml/ns/javaee"

        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee

        http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

       

     <filter>

        <filter-name>struts2</filter-name>

    <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>

     </filter>

     <filter-mapping>

        <filter-name>struts2</filter-name>

        <url-pattern>/*</url-pattern>

     </filter-mapping>

     <welcome-file-list>

        <welcome-file>index.jsp</welcome-file>

     </welcome-file-list>

    </web-app>

     

    4)编写处理类。该处理类一般继承于ActionSupport,只需重新excute()方法即可。注意:此处理类也可以是一般的类:(不继承ActionSupport. 其中的方法名也可以是任意的。但是该处理方法必须要有返回值String,并且这个返回值与struts中的resutlname值必须一致。比如:

    public class Test {

        public String testaa(){

           System.out.println("Testaa-------Testaa-------Testaa");

           return "abc";

        }

    }

    5):配置struts.xml文件(struts.xml文件必须要放到src目录下,而不是与action类名在同一个目录)。其中

    i:package里面的命名空间:namespace可以与package名称不一致。

    (ii):actionMethod方法默认是excute,也可以是其他的方法。

    (iii):result中的name值不一定是success或者fail。可以是任意值,只需要这个值与处理类中的处理方法返回值一致就可以了。

    iv):struts.xml可以有多个package

    xv):<constant name="struts.action.extension" value="action,do" />

    表示提交地址必须要以.action或者.do结尾格式才能有效。

     

    <?xml version="1.0" encoding="UTF-8" ?>

    <!DOCTYPE struts PUBLIC

            "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"

            "http://struts.apache.org/dtds/struts-2.0.dtd">

    <struts>

        <package name="j2eetest" extends="struts-default" namespace="/j2eetestaa">

           <action name="test" class="com.wsw.struts.action.Test" method="testaa">

           <result name="abc">/main/success.jsp</result>

           <result name="fail">/main/fail.jsp</result>

           </action>

        </package>

    </struts>






























    posted @ 2012-08-27 23:08 奋斗成就男人 阅读(219) | 评论 (0)编辑 收藏

    SQLSERVERl时间函数

    Sql时间函数

    一、sql server日期时间函数
    Sql Server中的日期与时间函数 
    1.  当前系统日期、时间 
        select getdate()  

    2dateadd  在向指定日期加上一段时间的基础上,返回新的 datetime 值
       例如:向日期加上2天 
       select dateadd(day,2,'2004-10-15')  --返回:2004-10-17 00:00:00.000 

    3datediff 返回跨两个指定日期的日期和时间边界数。
       select datediff(day,'2004-09-01','2004-09-18')   --返回:17

    4datepart 返回代表指定日期的指定日期部分的整数。
      select DATEPART(month'2004-10-15')  --返回 10

    5datename 返回代表指定日期的指定日期部分的字符串
       select datename(weekday, '2004-10-15')  --返回:星期五

    6day(), month(),year() --可以与datepart对照一下

    select 当前日期=convert(varchar(10),getdate(),120
    ,当前时间=convert(varchar(8),getdate(),114

    select datename(dw,'2004-10-15'

    select 本年第多少周=datename(week,'2004-10-15')
          ,今天是周几=datename(weekday,'2004-10-15')

    二、日期格式转换
        select CONVERT(varchargetdate(), 120 )
     2004-09-12 11:06:08 
     select replace(replace(replace(CONVERT(varchargetdate(), 120 ),'-',''),' ',''),':','')
     20040912110608
     
     select CONVERT(varchar(12) , getdate(), 111 )
     2004/09/12
     
     select CONVERT(varchar(12) , getdate(), 112 )
     20040912

     select CONVERT(varchar(12) , getdate(), 102 )
     2004.09.12
     
     其它我不常用的日期格式转换方法:

     select CONVERT(varchar(12) , getdate(), 101 )
     09/12/2004

     select CONVERT(varchar(12) , getdate(), 103 )
     12/09/2004

     select CONVERT(varchar(12) , getdate(), 104 )
     12.09.2004

     select CONVERT(varchar(12) , getdate(), 105 )
     12-09-2004

     select CONVERT(varchar(12) , getdate(), 106 )
     12 09 2004

     select CONVERT(varchar(12) , getdate(), 107 )
     09 122004

     select CONVERT(varchar(12) , getdate(), 108 )
     11:06:08
     
     select CONVERT(varchar(12) , getdate(), 109 )
     09 12 2004 1

     select CONVERT(varchar(12) , getdate(), 110 )
     09-12-2004

     select CONVERT(varchar(12) , getdate(), 113 )
     12 09 2004 1

     select CONVERT(varchar(12) , getdate(), 114 )
     11:06:08.177
    举例:
    1.GetDate() 用于sql server :select GetDate()

    2.DateDiff('s','2005-07-20','2005-7-25 22:56:32')返回值为 514592 秒
    DateDiff('d','2005-07-20','2005-7-25 22:56:32')返回值为 5 天

    3.DatePart('w','2005-7-25 22:56:32')返回值为 2 即星期一(周日为1,周六为7)
    DatePart('d','2005-7-25 22:56:32')返回值为 25即25号
    DatePart('y','2005-7-25 22:56:32')返回值为 206即这一年中第206天
    DatePart('yyyy','2005-7-25 22:56:32')返回值为 2005即2005年
    附图
    函数参数/功能
    GetDate( )返回系统目前的日期与时间
    DateDiff (interval,date1,date2)以interval 指定的方式,返回date2 与date1两个日期之间的差值 date2-date1
    DateAdd (interval,number,date)以interval指定的方式,加上number之后的日期
    DatePart (interval,date)返回日期date中,interval指定部分所对应的整数值
    DateName (interval,date)返回日期date中,interval指定部分所对应的字符串名称

    参数 interval的设定值如下:

    缩 写(Sql Server)Access 和 ASP说明
    YearYyyyyy年 1753 ~ 9999
    QuarterQq季 1 ~ 4
    MonthMm月1 ~ 12
    Day of yearDyy一年的日数,一年中的第几日 1-366
    DayDd日,1-31
    WeekdayDww一周的日数,一周中的第几日 1-7
    WeekWkww周,一年中的第几周 0 ~ 51
    HourHh时0 ~ 23
    MinuteMi分钟0 ~ 59
    SecondSss秒 0 ~ 59
    MillisecondMs-毫秒 0 ~ 999

    posted @ 2012-08-27 14:59 奋斗成就男人 阅读(316) | 评论 (0)编辑 收藏

    Maven实战(1)Eclipse构建Maven项目

    1. 简介 

    Maven是基于项目对象模型(POM),可以通过一小段描述信息来管理项目的构建,报告和文档的软件项目管理工具. 

      如果你已经有十次输入同样的Ant targets来编译你的代码、jar或者war、生成javadocs,你一定会自问,是否有一个重复性更少却能同样完成该工作的方 法。 Maven便提供了这样一种选择,将你的注意力从作业层转移到项目管理层。Maven项目已经能够知道如何构建和捆绑代码,运行测试,生成文档并宿主项目 网页 

    2.核心价值 

    * 简单 

    Maven 暴露了一组一致、简介的操作接口,能帮助团队成员从原来的高度自定义的、复杂的构建系统中解脱出来,使用Maven现有的成熟的、稳定的组件也能简 化构建系统的复杂度。 

    * 交流与反馈 

    与版本控制系统结合后,多有人都能执行最新的构建并快速得到反馈。此外,自动生成的项目报告也能帮助成员了解项目的状态,促进团队的交流。 

    * 测试驱动开发 

    TDD强调测试先行,所有产品都应该由测试用例覆盖。而测试是maven生命周期的最重要组成部分之一,并且Maven有现成的成熟插件支持业界流行的测试框架,如Junit和TestNG。

    * 快速构建

    只需要一些配置,之后用一条简单的命令就能让Maven帮你清理、编译、测试、打包、部署,然后得到最终产品。[/size] 

    * 持续集成 

    更加方便的持续集成 

    * 富有信息的工作区 

    2.主要内容 

    我将会发表一系列课程来讲解Maven的应用,基于Maven3.0,主要内容如下: 

    1)安装和配置 

    2)Maven使用入门 

    3)坐标和依赖 

    4)Maven仓库 

    5) 生命周期和插件 

    6)聚合与继承 

    7)使用Nexus创建私服 

    8)使用Maven进行测试 

    9)m2eclipse的使用 

    10)自动部署maven项目 

    11)使用Hudson进行持续集成 


    3. 安装好JDK 

    以JDK1.5以上为例 


    4. Maven 的下载
    下载地址:http://maven.apache.org/download.html 


    5.Maven安装 

    将下载到的文件解压到指定目录即可,如:C:\maven\apache-maven-3.0.4 


    6.环境变量的配置

    在系统环境变量中新增如下环境变量 
    M2_HOME: Maven的安装目录,如:C:\maven\apache-maven-3.0.4 
    M2: %M2_HOME%\bin 
    并在path中添加%M2%,这样便可以在任何路径中执行mvn命令


    7. 检测安装是否成功 

    Cmd窗口执行命令:mvn –v 

    得到如下图所示结果: 

     

    8.设置代理

     

    有时候你所在的公司基于安全因素考虑,要求你使用通过安全认证的代理访问因特网。这时就需要为Maven配置HTTP代理。

     

    在目录~/.m2/setting.xml文件中编辑如下(如果没有该文件,则复制$M2_HOME/conf/setting.xml):

     

    Xml代码 收藏代码
    1. <proxies>
    2. <proxy>
    3. <id>optional</id>
    4. <active>true</active>
    5. <protocol>http</protocol>
    6. <username>proxyuser</username>
    7. <password>proxypass</password>
    8. <host>proxy.host.net</host>
    9. <port>80</port>
    10. <nonProxyHosts>local.net|some.host.com</nonProxyHosts>
    11. </proxy>
    12. </proxies>

     

    8、安装Maven后每次启动出现警告信息:

    Eclipse is running in a JRE, but a JDK is required
    Some Maven plugins may not work when importing projects or updating source folders.

     

    分两步解决问题:

     

    1. 检查Eclipse正在使用的JRE

     

    ‘Window’ -> ‘Preferences’ -> ‘Java’ -> ‘Installed JREs’ 确定正在使用JDK而非JRE.
    image

     

    如果没有JDK, 则先新增一个Standard VM.

     

    2. 配置Eclipse.ini

     

    检查Eclipse配置文件, 增加/编辑以下代码:

     

     

     

    1. -vm
    2. C:\Progra~2\Java\jdk1.6.0_16\jre\bin\javaw

     

     

     

    注意事项:

     

    1. 第一行参数名称, 第二行为值, 不能写到同一行中

     

    2. 关于第二行的值, 因为不允许出现空格, 所以使用Progra~1或2 替代”Program Files (x86)”.
    如果在Program Files下, 请使用Progra~1, 如果在x86下, 则使用Progra~2

     

    3. 在文件中的位置, 不能放到最后(不能在-vmargs之后), 不放心的直接放到文件最前, 如:

     

     

     

    1. -vm
    2. C:\Progra~2\Java\jdk1.6.0_16\jre\bin\javaw
    3. -startup
    4. .....
    5. --launcher.defaultAction
    6. openFile
    7. -vmargs
    8. -Dosgi.requiredJavaVersion=1.5
    9. -Xms240m
    10. -Xmx912m

    posted @ 2012-08-23 21:58 奋斗成就男人 阅读(2713) | 评论 (2)编辑 收藏

    Maven实战(二)构建简单Maven项目

    上一节讲了maven的安装和配置,这一节我们来学习一下创建一个简单的Maven项目

     

     

    1. 用Maven 命令创建一个简单的Maven项目

    在cmd中运行如下命令:

    Cmd代码  收藏代码
    1. mvn archetype:generate   
    2. -DgroupId=com.mycompany.app   
    3. -DartifactId=my-app-simple  
    4.  -Dversion=1.0   
    5. -DarchetypeArtifactId=maven-archetype-quickstart  

     

     即可在当前目录创建一个简单的maven项目,当然创建的时候会从Maven库中下载相关的依赖,耐心等待即可。

    maven的大致结构如下:

    Java代码  收藏代码
    1. my-app  
    2. |-- pom.xml  
    3. `-- src  
    4.     |-- main  
    5.     |   |-- java  
    6.     |   |   `-- com  
    7.     |   |       `-- mycompany  
    8.     |   |           `-- app  
    9.     |   |               `-- App.java  
    10.     |   `-- resources  
    11.     |       `-- META-INF  
    12.     |           `-- application.properties  
    13.     `-- test  
    14.         `-- java  
    15.             `-- com  
    16.                 `-- mycompany  
    17.                     `-- app  
    18.                         `-- AppTest.java  

     

       src/main/java : java源文件存放位置

       src/main/resource : resource资源,如配置文件等

       src/test/java : 测试代码源文件存放位置

     

    2.简单POM.xml

     打开项目即可看到pom.xml

    Xml代码  收藏代码
    1. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    2.   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">  
    3.   <modelVersion>4.0.0</modelVersion>  
    4.   <groupId>com.mycompany.app</groupId>  
    5.   <artifactId>my-app-simple</artifactId>  
    6.   <packaging>jar</packaging>  
    7.   <version>1.0</version>  
    8.   <name>my-app-simple</name>  
    9.   <url>http://maven.apache.org</url>  
    10.   <dependencies>  
    11.     <dependency>  
    12.       <groupId>junit</groupId>  
    13.       <artifactId>junit</artifactId>  
    14.       <version>3.8.1</version>  
    15.       <scope>test</scope>  
    16.     </dependency>  
    17.   </dependencies>  
    18. </project>  

     这段代码中最重要的是包含groupId, artifactId 和 version 的三行。这三个元素定义了一个项目基本的坐标

     

    groupId 定义了项目属于哪个组,这个组往往和项目所在的组织或公司存在关联。譬如在googlecode上建立了一个名为myapp的项目,那么groupId就应该是com.googlecode.myapp

     

    artifactId 定义了当前Maven项目在组织中唯一的ID, 可以理解为项目中的模块, 模块为Maven中最小单位构件

    version 项目的版本

     

       

    3.运行简单Maven命令

     我们已经创建了最简单的Maven项目,下面我们来执行一些简单的构建命令

     

      编译: compile

    在cmd中,将目录切换到my-app-simple下,执行mvn clean compile

    build success之后我们会在my-app-simple下看到新增了一个target目录,该目录下存放项目编译后的文件,如.class文件

     

      清理: clean

    cmd目录my-app-simple下执行命令 mvn clean

    会将target文件删除,即清理项目,该命令可以结合其他命令运行

     

      测试: test

    cmd目录my-app-simple下执行命令 mvn test

    会执行src/test/java 下的Junit 测试代码

    当然在执行测试之前会自动执行编译命令,运行结果如下图:



     

     打包: package

     cmd目录my-app-simple下执行命令 mvn package

     会将项目打成jar包,并放在target目录中

     执行此命令之前会先执行编译和测试命令

     

     安装:install 

     cmd目录my-app-simple下执行命令 mvn install

     会将项目jar包安装到本地仓库中,以便其他项目使用

    执行此命令之前会先执行编译,测试,打包命令 

    posted @ 2012-08-23 21:57 奋斗成就男人 阅读(1061) | 评论 (0)编辑 收藏

    Maven实战(六)依赖

         摘要: 我们项目中用到的jar包可以通过依赖的方式引入,构建项目的时候从Maven仓库下载即可。 1. 依赖配置    依赖可以声明如下:   Xml代码  <project>    ...    <dependenci...  阅读全文

    posted @ 2012-08-23 21:55 奋斗成就男人 阅读(11918) | 评论 (0)编辑 收藏

    Maven实战(5)坐标详解

    1.为什么要定义Maven坐标 
         在我们开发Maven项目的时候,需要为其定义适当的坐标,这是Maven强制要求的。在这个基础上,其他Maven项目才能应用该项目生成的构件。 

    2.Maven坐标详解

         Maven坐标为各种构件引入了秩序,任何一个构件都必须明确定义自己的坐标,而一组Maven坐标是通过一些元素定义的,它们是groupId,artifactId,version,packaging,class-sifer。下面是一组坐标定义:

      

    Xml代码  收藏代码
    1. <groupId>com.mycompany.app</groupId>  
    2.   <artifactId>my-app</artifactId>  
    3.   <packaging>jar</packaging>  
    4.  <version>0.0.1-SNAPSHOT</version>  

     下面讲解一下各个坐标元素:

     

    groupId :定义当前Maven项目隶属的实际项目。首先,Maven项目和实际项目不一定是一对一的关系。比如SpringFrameWork这一实际项目,其对应的Maven项目会有很多,如spring-core,spring-context等。这是由于Maven中模块的概念,因此,一个实际项目往往会被划分成很多模块。其次,groupId不应该对应项目隶属的组织或公司。原因很简单,一个组织下会有很多实际项目,如果groupId只定义到组织级别,而后面我们会看到,artifactId只能定义Maven项目(模块),那么实际项目这个层次将难以定义。最后,groupId的表示方式与Java包名的表达方式类似,通常与域名反向一一对应。

     

    artifactId : 该元素定义当前实际项目中的一个Maven项目(模块),推荐的做法是使用实际项目名称作为artifactId的前缀。比如上例中的my-app。

     

    version : 该元素定义Maven项目当前的版本

     

    packaging :定义Maven项目打包的方式,首先,打包方式通常与所生成构件的文件扩展名对应,如上例中的packaging为jar,最终的文件名为my-app-0.0.1-SNAPSHOT.jar。也可以打包成war, ear等。当不定义packaging的时候,Maven 会使用默认值jar

     

    classifier: 该元素用来帮助定义构建输出的一些附件。附属构件与主构件对应,如上例中的主构件为my-app-0.0.1-SNAPSHOT.jar,该项目可能还会通过一些插件生成如my-app-0.0.1-SNAPSHOT-javadoc.jar,my-app-0.0.1-SNAPSHOT-sources.jar, 这样附属构件也就拥有了自己唯一的坐标

    posted @ 2012-08-23 21:53 奋斗成就男人 阅读(318) | 评论 (0)编辑 收藏

    Maven实战(4)生命周期

    1. 三套生命周期 
        Maven拥有三套相互独立的生命周期,它们分别为clean,default和site。 
    每个生命周期包含一些阶段,这些阶段是有顺序的,并且后面的阶段依赖于前面的阶段,用户和Maven最直接的交互方式就是调用这些生命周期阶段。 
    以clean生命周期为例,它包含的阶段有pre-clean, clean 和 post clean。当用户调用pre-clean的时候,只有pre-clean得以执行,当用户调用clean的时候,pre-clean和clean阶段会得以顺序执行;当用户调用post-clean的时候,pre-clean,clean,post-clean会得以顺序执行。 

    较之于生命周期阶段的前后依赖关系,三套生命周期本身是相互独立的,用户可以仅仅调用clean生命周期的某个阶段,或者仅仅调用default生命周期的某个阶段,而不会对其他生命周期产生任何影响。 

    2. clean 生命周期

          clean生命周期的目的是清理项目,它包含三个阶段:

         1)pre-clean 执行一些清理前需要完成的工作。

         2)clean 清理上一次构建生成的文件。

         3)post-clean 执行一些清理后需要完成的工作。

     

    3. default 生命周期

           default生命周期定义了真正构件时所需要执行的所有步骤,它是生命周期中最核心的部分,它包含的阶段如下:

           1) validate 验证项目是否正确和所有需要的相关资源是否可用

           2) initialize 初始化构建

           3) generate-sources

           4)   process-sources 处理源代码

           5) generate-resources 

           6)   process-resources 处理项目主资源文件。对src/main/resources目录的内容进行变量替换等工作后,复制到项目输出的主classpath目录中。

           7) compile 编译项目的主源代码

           8) process-classes

           9)   generate-test-sources

           10) process-test-sources 处理项目测试资源文件

           11)generate-test-resources

           12)  process-test-resources 处理测试的资源文件

           13)test-compile 编译项目的测试代码

           14)process-test-classes

           15)  test 使用单元测试框架运行测试,测试代码不会被打包或部署

           16)prepare-package 做好打包的准备

           17)package 接受编译好的代码,打包成可发布的格式

           18)  pre-integration-test

           19)  integration-test

           20)  post integration-test

           21)  verify

           22)  install 将包安装到Maven本地仓库,供本地其他Maven项目使用

           23)deploy 将最终的包复制到远程仓库,供其他开发人员和Maven项目使用

           

     

    4. site 生命周期

          site生命周期的目的是建立和发布项目站点,Maven能够基于POM所包含的信息,自动生成一个友好的站点,方便团队交流和发布项目信息。该生命周期包含如下阶段:

          1)pre-site 执行一些在生成项目站点之前需要完成的工作

          2)site 生成项目站点文档

          3)post-site 执行一些在生成项目站点之后需要完成的工作

          4)site-deploy 将生成的项目站点发布到服务器上

    posted @ 2012-08-23 21:49 奋斗成就男人 阅读(220) | 评论 (0)编辑 收藏

    Eclipse构建Maven项目(3)

    1. 安装m2eclipse插件 
       要用Eclipse构建Maven项目,我们需要先安装meeclipse插件 
       点击eclipse菜单栏Help->Eclipse Marketplace搜索到插件Maven Integration for Eclipse 并点击安装即可,如下图:

     

     

    安装成成之后我们在Eclipse菜单栏中点击File->New->Other,在弹出的对话框中会看到如下图所示:



     

    2. 构建Maven项目  

         

          以eclipse3.6为例

          1)创建简单Maven项目

               点击Eclipse菜单栏File->New->Ohter->Maven得到如下图所示对话框:

               

     

    选中Maven Project并点击Next,到下一个对话框继续点击Next得到如下对话框



     如图示操作,选择maven-archetype-quickstart,点击Next



     按图示填写好groupId, artfactId,version等信息,点击Finish。

    由此我们成功创建了一个简单的Maven项目,项目结构如图所示



     

         2)创建Maven web项目

         操作跟创建简单Maven项目类似,点击Eclipse菜单File->New->Other->Maven->Maven Project

         在选择maven-archetype的界面进行如下操作:

         

     点击Next,填写好相应的groupId,artifactId,version等信息,点击Finish

    得到的Maven web项目结构如下图所示:

     

     

     右击项目,点击Properties->Project Facets



     

    如上图可以看到项目为web2.3 java1.5 当然我们也可以改成我们所需要的版本,打开xml文件my-app-web/.settings/org.eclipse.wst.common.project.facet.core.xml,进行修改即可:

    Xml代码  收藏代码
    1. <?xml version="1.0" encoding="UTF-8"?>  
    2. <faceted-project>  
    3.   <fixed facet="wst.jsdt.web"/>  
    4.   <installed facet="java" version="1.5"/>  
    5.   <installed facet="jst.web" version="2.3"/>  
    6.   <installed facet="wst.jsdt.web" version="1.0"/>  
    7. </faceted-project>  

     

         3)导入Maven项目

              在Eclipse project explorer中右击,在弹出框中选择import,得到如下图所示:          

     

          选择Existing Maven Projects,并点击Next,得到如下图所示对话框:

         

     

    选择一个已经创建好的Maven项目,并点击Finish。

    由此,导入Maven项目成功

     

     

        

    3. 运行Maven命令

         

        右击项目,点击Run as,如下图:

     

     

     即可看到有很多现有的maven命令,点击即可运行,并在控制台可以看到运行信息

     如果你想运行的maven命令在这里没有找到,点击Maven build创建新的命令,操作如下图所示:



     

     如下图填入Maven命令,点击Run即可



     

    新增的maven命令可以通过如下方式找到,并再次运行:



     

     

    posted @ 2012-08-23 21:46 奋斗成就男人 阅读(6921) | 评论 (0)编辑 收藏

    全面对比T-SQL与PL/SQL

         摘要: 以前一直用mssql 做开发,最近的项目都Oracle,   1)数据类型   TSQL PL/SQL   numeric(p,s) numeric(p,s) or NUMBER(p,s)   decimal(p,s) decimal(p,s) or NUMBER(p,s) ...  阅读全文

    posted @ 2012-08-16 08:46 奋斗成就男人 阅读(496) | 评论 (0)编辑 收藏

    Hibernate映射解析——七种映射关系

    首先我们了解一个名词ORM,全称是(Object Relational Mapping),即对象关系映射。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现,这样开发人员就可以把对数据库的操作转化为对这些对象的操作。Hibernate正是实现了这种思想,达到了方便开发人员以面向对象的思想来实现对数据库的操作。

    Hibernate在实现ORM功能的时候主要用到的文件有:映射类(*.java)、映射文件(*.hbm.xml)和数据库配置文件(*.properties/*.cfg.xml),它们各自的作用如下。

    映射类*.java:它是描述数据库表的结构,表中的字段在类中被描述成属性,将来就可以实现把表中的记录映射成为该类的对象了。

    映射文件(*.hbm.xml:它是指定数据库表和映射类之间的关系,包括映射类和数据库表的对应关系、表字段和类属性类型的对应关系以及表字段和类属性名称的对应关系等。

    数据库配置文件(*.properties/*.cfg.xml:它是指定与数据库连接时需要的连接信息,比如连接哪种数据库、登录数据库的用户名、登录密码以及连接字符串等。当然还可以把映射类的地址映射信息放在这里。

    接下来让我们就一起走进Hibernate的七种映射关系:

    1、单向一对一关联映射(one-to-one):

    两个对象之间一对的关系,例如:Person(人)-IdCard(身份证)

    有两种策略可以实现一对一的关联映射:

    *主键关联:即让两个对象具有相同的主键值,以表明它们之间的一一对应的关系;数据库表不会有额外的字段来维护它们之间的关系,仅通过表的主键来关联。如下图:

     

    例子:单向一对一主键关联例子连接

    *唯一外键关联:外键关联,本来是用于多对一的配置,但是加上唯一的限制之后(采用<many-to-one>标签来映射,指定多的一端uniquetrue,这样就限制了多的一端的多重性为一),也可以用来表示一对一关联关系,其实它就是多对一的特殊情况。如下图:

     

    例子:单向一对一唯一外键关联例子连接

    注意:因为一对一的主键关联映射扩展性不好,当我们的需要发生改变想要将其变为一对多的时候变无法操作了,所以我们遇到一对一关联的时候经常会采用唯一外键关联来解决问题,而很少使用一对一主键关联。

    2、单向多对一关联映射(many-to-one):

    多对一关联映射原理:在多的一端加入一个外键,指向一的一端,如下图:

     

    关键映射代码——在多的一端加入如下标签映射:

     

    Java代码 
    1. <many-to-one name="group" column="groupid"/>  

     

    3、单向一对多关联映射(one-to-many)

    一对多关联映射和多对一关联映射原理是一致的,都是在多的一端加入一个外键,指向一的一端。如下图(学生和班级):

     

    注意:它与多对一的区别是维护的关系不同

    *多对一维护的关系是:多指向一的关系,有了此关系,加载多的时候可以将一加载上来

    *一对多维护的关系是:一指向多的关系,有了此关系,在加载一的时候可以将多加载上来

    关键映射代码——在一的一端加入如下标签映射:

     

    Java代码 
    1. <set name="students">  
    2.       <key column="classesid"/>  
    3.       <one-to-many class="com.hibernate.Student"/>  
    4. </set>  

     

    缺陷:因为多的一端Student不知道Classes的存在(也就是Student没有维护与Classes的关系)所以在保存Student的时候关系字段classesid是为null的,如果将该关系字段设置为非空,则将无法保存数据,常用解决办法是改用双向关联映射,参见6

    4、单向多对多映射(many-to-many)

    多对多关联映射新增加一张表才完成基本映射,如下图:

     

    关键映射代码——可以在User的一端加入如下标签映射:

     

    Java代码 
    1. <set name="roles" table="t_user_role">  
    2.      <key column="user_id"/>  
    3.      <many-to-many class="com.hibernate.Role" column="role_id"/>  
    4. </set>  

     

    5、双向一对一关联映射

    对比单向一对一映射,需要在IdCard加入<one-to-one>标签,它不影响,只影响加载。如下图:

    双向一对一主键映射关键映射代码——在IdCard端新加入如下标签映射

     

    Java代码 
    1. <one-to-one name="person"/>  

     

    双向一对一唯一外键映射关键映射代码——在IdCard端新加入如下标签映射

     

    Java代码 
    1. <one-to-one name="person"property-ref="idCard"/>  

     

    注意:一对一唯一外键关联双向采用<one-to-one>标签映射,必须指定<one-to-one>标签中的property-ref属性为关系字段的名称

    6、双向一对多关联映射(非常重要

    采用一对多双向关联映射的目的主要是为了主要是为了解决一对多单向关联的缺陷而不是需求驱动的。

    一对多双向关联的映射方式:

    * 在一的一端的集合上采用<key>标签,在多的一端加入一个外键

    * 在多的一端采用<many-to-one>标签

    注意:<key>标签和<many-to-one>标签加入的字段保持一直,否则会产生数据混乱

    关键映射代码:

    在Classes的一端加入如下标签映射:

     

    Java代码 
    1. <set name="students"inverse="true">  
    2.        <key column="classesid"/>  
    3.       <one-to-many class="com.hibernate.Student"/>  
    4. </set>  

     

    在Student的一端加入如下标签映射:

     

    Java代码 
    1. <many-to-one name="classes" column="classesid"/>  

     

    注释:inverse属性

    * inverse属性可以用在一对多和多对多双向关联上,inverse属性默认为false,为false表示本端可以维护关系,如果inverse为true,则本端不能维护关系,会交给另一端维护关系,本端失效。所以一对多关联映射我们通常在多的一端维护关系,让一的一端失效。

    * inverse是控制方向上的反转,只影响存储

    7、双向多对多关联映射

    双向的目的就是为了两端都能将对方加载上来,和单向多对多的区别就是双向需要在两端都加入标签映射,需要注意的是:

    * 生成的中间表名称必须一样

    * 生成的中间表中的字段必须一样

    Role(角色)端关键映射代码:

     

    Java代码 
    1. <set name="users" table="t_user_role">  
    2.        <key column="role_id"/>  
    3.        <many-to-many class="com.hibernate.User" column="user_id"/>  
    4. lt;/set>  

     

    User(用户)端关键映射代码:

     

    Java代码 
    1. <set name="roles" table="t_user_role">  
    2.       <key column="user_id"/>  
    3.       <many-to-many class="com. hibernate.Role" column="role_id"/>  
    4. lt;/set>  

     

    总结:对于上面这七种关联映射中,最重要的就是一对多的映射,因为它更贴近我们的现实生活,比如:教室和学生就可以是典型的一对多的关系,而我们开发软件的目的之一就是为了解决一些生活中重复性问题,把那些重复的问题交给计算机帮助我们完成,从而来提高我们的工作效率。一句话:生活离开不开编程,编程更离不开生活

    posted @ 2012-08-15 12:31 奋斗成就男人 阅读(292) | 评论 (0)编辑 收藏

    轻松上手SpringMVC

         摘要: SpringMVC框架介绍 Spring框架提供了构造Web应用程序的全能MVC模块。Spring MVC分离了控制器、模型对象、分派器以及处理程序对象的角色,这种分离让它们更容易进行制定。是一个标准的MVC框架。 那你猜一猜哪一部分应该是哪一部分? SpringMVC框架图             &...  阅读全文

    posted @ 2012-08-15 12:30 奋斗成就男人 阅读(258) | 评论 (0)编辑 收藏

    Linux文件权限的那些事

    linux是一个多用户,多任务的操作系统,对于每一个文件它的属性中都包括:文件所有者(owner),文件所属组(group),其他用户(other),还必须具备与这三个角色对应的读,写,执行的权限,如下图:

    在tmp目录下面有一个a.txt文件,我们通过ls -l命令可以查看其详细信息:

    -:表示普通文件,d:表示目录文件,l:链接文件,b:设备文件中可以供存储的接口设备,c:设备文件中串行端口设备如键盘。

    由于最前面是-:所以a.txt是普通文件。

    再看  rw-r--r--部分,我们将其分为三组,分别对应文件所有者,文件所属组,其他用户的权限.

    其中r代表读取权限,w:代表写权限,x:代表执行权限(这里没出现),-:代表没有某种权限。

    那对上面的权限的解释就是:

    owner:可以读和写,不能执行

    group:可以读取不能写,不能执行

    other:可以读取,不能写,不能执行

     

    第一个root代表文件所有者,第二个root代表文件所属组

    那么现在我如果想修改文件所有者,文件所属组,文件权限该怎么做,请继续向下阅读:

    chgrp:修改用户所属组,chown:修改文件所有者,chmod:修改文件权限

     

    假设我的系统中又一个叫gavin的组(通过/etc/group查看)

    如上图,通过chgrp命令将该文件的group修改为了gavin

    下面修改其所有者:

     

    修改其权限:

     

    chmod  777 a.txt   这个777代表什么?

    在linux中使用数字代表权限:

    r:4 w:2 x:1

    r--   =4+0+0=4;

    rw- =4+2+0=6;

    rwx =4+2+1=7

    相信写到这里大家都应该明白了吧。

     

    权限对于文件和文件夹的意义是不一样的,

    对于文件:

    r:代表可以读取文件的内容,w:代表可以修改文件的内容,x:可以执行这个文件

    对于文件夹:

    r:可以获取文件夹中又哪些文件,w:可以添加和删除文件夹中的内容,x:可以进入文件夹,

    如果某个角色对于一个文件夹的权限是rw-;

    那么他仅仅可以使用ls获取文件夹中的内容,但是不可以使用cd进入该文件夹。

     

     

     

    文件的权限告一段落,现在来看看linux中的那些常见目录中的内容:

    /bin   系统有很多放置执行文件的目录,但是/bin比较特殊,因为/bin放置的是在单用户维护模式下还能够被操作的命令,在/bin下面的命令可以被root和一般账户使用,如:cat,chmod,chown,data,mv,mkdir,cp ,bash等常用命令。

    /boot  主要放置开机使用到的文件

    /dev  在linux系统中任何设备与接口设备都是以文件的形式存在于这个目录当中,你只要访问某个文件就相当于访问该设备

    /etc  系统的主要配置文件几乎都在这个文件夹类。

    /home 这是系统默认的用户主文件夹

    /lib 系统的函数库非常多,二/lib放置的是开机会使用到的函数库

    /mnt 如果你想临时挂在一些外部设备(光盘)一般建议放置到这个目录。

    /opt 这是给第三方软件放置的目录

    /root 系统管理员的主文件夹

    /tmp 这是让一般用户或者正在执行的程序放置文件的地方,这个目录是任何人都可以访问的,所以你需要定期清理一下,当然重要数据时不能放到这里来的。

     

     

    关于文件权限的最后一点就是:文件默认权限umask

    现在我们已经知道如何新建或者改变一个目录的属性了,不过你知道当你新建一个新的文件或则目录是,它的默认权限是什么吗?那就是于umask这东西有关了,那么umask是在搞什么呢,基本上,umask就是制定目前用户在新建文件或目录的时候权限的默认值,如果获得或设置umask,方法如下:

    #umask  或则  umask -S

    (四位数,第一位我们先不管,表示特殊权限,我们从第二位开始看起)

    在默认权限上,文件和目录是不一样的,对于一个目录,x权限是非常重要的 ,而对于一个文件,x权限在默认是不应该有的,因为文件大多是用来存储数据的,所以在linux中,文件的默认权限是666,目录的默认权限是777

     

     

    要注意的是umask的分数指的是“默认值需要剪掉的权限”,

    所以新建文件时权限:rw--r--r--

    新建目录:r-xr-xr-x



    posted @ 2012-08-15 12:28 奋斗成就男人 阅读(1694) | 评论 (0)编辑 收藏

    你若没有了动力就看看此篇文章吧

    1、人生只有走出来的美丽,没有等出来的辉煌。­

    2、在人生的道路上,即使一切都失去了,只要一息尚存,你就没有丝毫理由绝望。因为失去的一切,又可能在新的层次上复得。­

    3、自暴自弃便是命运的奴隶,自强不息是生命的天使;我不想用别人的汗水浇灌自己的心灵,我愿意用别人的棉袄,来温暖自己的躯体。我只想堂堂正正的做人,我只愿光明磊落做事,该记得的我不会遗忘,该遗忘的我不会存放。­

    4、没有一劳永逸的开始;也没有无法拯救的结束。人生中,你需要把握的是:该开始的,要义无反顾地开始;该结束的,就干净利落地结束。­

    5、再伟大的巨人也有他渺小的瞬间,再渺小的凡人也有他伟大的时刻。­

    6、生命的奖赏远在旅途终点,而非起点附近。我不知道要走多少步才能达到目标,踏上第一千步的时候,仍然可能遭到失败。但我不会因此放弃,我会坚持不懈,直至成功!­

    7、不要认为只要付出就一定会有回报,这是错误的。学会有效地工作,这是经营自己强项的重要课程。­

    8、世间万事,不可求其绝顶圆满。留一分不足,可得无限完美。物满则溢,强求必反。埋首努力之外,一切听其自然,届时自有机遇。­

    9、一花凋零荒芜不了整个春天,一次挫折也荒废不了整个人生。­

    10、你改变不了环境,但可以改变自己;你改变不了事实,但可以改变态度;你改变不了过去,但可以改变现在;你不能控制别人,但可以掌握自己;你不能预知明天,但可以把握今天;你不能样样顺利,但可以事事尽心;你不能选择容貌,但可以展现笑容。­

    11、Nothing is impossible to  a  willing  heart!   ­

    心之所愿,无事不成!­

                 ­

    图片 ­

    ­

    ­

                                                                      愚者与智者的48个差距­

    ­

    第一章   学会尊重他人 ­

    ·1.智者满脸微笑,愚者冷若冰霜·2.智者记住别人的名字,愚者希望名字被记住 ·3.智者了解别人的心思,愚者表示自己的需要 ·4.智者善于倾听,愚者没有耐心­

    ­

    第二章 不做无意义的争辩 ·5.智者先赞同,愚者先否定 ·6.智者让别人逐步说“是”,愚者会引起 更多争论 ·7.智者聪慧幽默,愚者呆板无趣 ·8.智者知过就改,愚者固执己见。 ­

    ­

    第三章 说话不说破 ­

    ·9.智者委婉建议,愚者直白否定 ·10.智者不把话说破,愚者单刀直入 ·11.智者三缄其口,愚者口不择言 ·12.智者委婉拒绝,愚者冷漠反对。 ­

    ­

    第四章 学会随机应变 ­

    ·13.智者说话看对象,愚者盲目乱开口 ·14.智者善于察言观色,愚者不会“投其所好·15.智者看场合,愚者“一根筋·16.智者谈对方感兴趣的事,愚者说自己 感兴趣的事­

    ­

    第五章 做个让人喜欢的人 ­

    ·17.智者低调谦虚,愚者骄傲张狂 ·18.智者宽容大度,愚者锱铢必较 ·19.智者诚实可信,愚者虚伪可憎 ·20.智者照顾他人的自重感,愚者满足自己的虚荣心­

    ­

    第六章 关心他人,快乐自己 ­

    ·21.智者细微处关心他人,愚者处处为自己打算 ·22.智者善意赞美,愚者乐于批评 ·23.智者给人以激励,愚者以冷水泼人 ·24.智者善于替人解围,愚者遇事避而远之­

    ­

    第七章 高效率做事 ­

    ·25.智者目标明确,愚者糊涂度日 ·26.智者善于制订计划,愚者眉毛胡子一把抓 ·27.智者与人有效合作,愚者喜欢单打独斗 ·28.智者挖掘自身潜能,愚者只会埋头苦干­

    ­

    第八章 行动成就梦想 ­

    ·29.智者付诸行动,愚者耽于幻想 ·30.智者雷厉风行,愚者拖沓懒惰 ·31.智者标新立异,愚者盲目从众 ·32.智者未雨绸缪,愚者亡羊补牢­

    ­

    第九章 不钻生活牛角尖 ­

    ·33.智者淡然看待得失,愚者为名为利所累 ·34.智者懂得放弃,愚者牢记忧伤 ·35.智者改善自己的弱点,愚者埋怨自己的短处 ·36.智者知道变通,愚者死钻牛角­

    ­

    第十章 信心是照亮成功的阳光 ­

    ·37.智者不为打翻的牛奶哭泣,愚者常常 拿过失处罚自己 ·38.智者克服自卑,愚者被自卑俘虏 ·39.智者对生活充满热忱,愚者缺乏激情 ·40.智者为最坏的结果做准备,愚者凡事 总往最坏处设想­

    ­

    第十一章 别和工作过不去 ­

    ·41.智者创造机遇,愚者等待好运 ·42.智者靠智慧工作,愚者靠体力工作 ·43.智者热爱自己的工作,愚者在工作中 变得麻木 ·44.智者懂得休息,愚者堪称工作狂­

    ­

    第十二章 享受生活,享受快乐 ­

    ·45.智者给心灵放假,愚者让心弦紧绷 ·46.智者驾驭金钱,愚者被金钱束缚 ·47.智者过好每一天,愚者浪费好时光 ·48.智者感受快乐点滴,愚者总是不快乐

    posted @ 2012-08-14 09:05 奋斗成就男人 阅读(313) | 评论 (0)编辑 收藏

    改变你一生的秘诀,你愿意花几分钟看完它吗?几分钟决定你的人生

    一切源于……一个疯狂的决定……只为帮助你……实现梦想……”

    特别提醒:请锁上门……关上手机……暂时与世隔绝……不要让任何人打扰你!否则,你可能失去一次彻底突破自我,改变命运的机会!这将是你生命中最重要的10分钟!你的事业和人生将会出现魔术般转变……

    “开展你的事业,你愿意怎么做,从开始走上正确的道路,还是以后改正?”

    请认真阅读以下每一个字,因为它将影响你,还有你的行业。。


    来自:陈安之(中国上海)

    时间:星期一 早晨 6:00

     

    图片

    亲爱的朋友:
    我是陈安之,很高兴有机会可以让您看到这封信,当您很认真的读完这封信,有可能您的企业业绩倍增,命运从此改变
    我经常看见一些企业家们凭感觉“驾驶飞机”。他们的嘴巴经常会迸出这样的词汇:
    “以后再决定吧。我很忙。现在我们需要销售。我们需要把产品推销出去。我们需要更多的人手。”我们需要,我们需要, 我们需要......你明白这样的情况。
    他们陷入困境。他们知道,如果他们停下来一会,重新组织,就会走上轨道。但前面总是有另一个危机。
    我承认-------我几乎成为其中一员--------非常近。
    我以前非常渴望成功,也不断的寻找成功的方法,研究为什么有些人会成功?我阅读各式各样可以帮助别人成功的书籍,上过许多帮助别人成功的课程。
    从17岁到21岁之间,我做过餐厅服务生、卖过净水器、汽车、皮肤保养品、电话卡、超级市场折价券、巧克力批发、邮购等18项工作,到21岁时———
    银行存款簿的金额竟然是$000.00,丝毫没有一点点进展。
    直到我遇到我的启蒙老师安东尼.罗宾,并藉由不断的学习成长,今天才有机会分享这些成功的讯息。

    人生取决于你看过的书和你所见的人
    ——世界第一潜能激发大师安东尼.罗宾
    和什么样的人在一起,你就会变成什么样的人!

    那个决定性时刻就是我初次遇到我的启蒙老师安东尼.罗宾(世界第一潜能激发大师)的时候,我决定我宁愿挨饿、没地方住也要黏住他。

    这一次命运的干预挽救了我数年的尝试和错误......
    还记得我的导师安东尼.罗宾吗?他23岁的时候穷困潦倒,住在不到10坪大的茅屋,在浴缸里洗碗。24岁的时候竟然搬进了城堡,还拥有自己的私人直升飞机。27岁的时候竟然成为世界第一名的演说家。
    他的学生有美国前总统克林顿英国女王戴安娜王妃南非总统曼德拉前苏联总统戈巴乔夫世界网球冠军安德烈.阿加西。。。他是当之无愧的世界成功终极导师
    为了寻找快速成功之道,在21岁的时候,我加入了安东尼.罗宾机构,拜在他的门下,零距离向他学习如何快速成功。在安东尼罗宾机构的日子,让我的整个人生都发生了天翻地覆的变化。
    安东尼.罗宾告诉我,这个世界上赚钱的行业很多,但是没有哪一个行业可以比得上帮助别人成功和帮助别人改变命运更加有价值、有意义

      “你知道为什么美国只有不到300年的历史却可以成为世界巨头吗?
    因为美国有成功学。”

    前世界首富钢铁大王卡内基学成功学,比尔盖茨学成功学,股神巴菲特学成功学,布什总统学成功学,拳王阿里学成功学,篮球之神迈克尔.乔丹学成功学,。。。。
    回到祖国,看到祖国这样日新月异的发展,看到这么多的人对我这样的亲切和熟悉,我再次立下第二个目标——

      “以最短的时间帮助最多人成功,我要把在海外学到的所有成功学知识,毫无保留地告诉给中国的每一个人,让中国在21世纪成为世界第一强国!”

    下面我想跟大家分享我从事成功学22年来最重要最重要的三个关键,有两句话是我觉得最重要最重要最重要,这两句话听起来再简单不过了,但是你的人生如果可以悟道这两句话,你2012年保证开始让你的人生起飞、事业腾飞起来。
    第一句话叫做:

    “成功一定有方法”

    比尔盖茨连续十几年成为世界首富,是他的运气比较好,还是他掌握了经营企业的方法

    迈克尔乔丹得过六次NBA总冠军,得过十次NBA得分王,是他的运气比较好,还是掌握了赢球的方法

    我的老师安东尼.罗宾24岁成为亿万富翁,27岁世界第一名演说家,你觉得安东尼.罗宾是运气好,还是掌握了成功的方法

    我25岁白手起家,27岁成为亿万富翁,你觉得我是运气好,还是掌握了成功的方法

    所以为什么我们还没有成功或是还没有到达自己设定的理想境界,事实上只有一个原因,就是我们非常缺乏成功的方法

    比尔盖茨生出来不会设计软件,乔丹生出来不会打篮球,陈安之生出来也不会演讲,所以没有成功者是天生的,所有世界上最成功的人都是靠学习而来的。
    第二句话就是

    “失败一定有原因”

    如果你有三十种成功的方法,但是你有20种失败的习惯和原因,请问你会成功还是不会成功,答案是:不会成功。
    因为每当你用成功方法往前走三步,你失败的习惯又向后退两步,每当你用成功的方法往前走四步,你失败的习惯又让你往后退一步,会成功还是不会成功?一定不会。是不是呢!
    所以我认为最好研究成功的方法是研究一个人为什么失败,然后把这个失败的原因摒除掉,然后学习成功的方法,这样子你比较容易成功。
    华人首富李嘉诚曾经接受一本杂志的访问,他们问李嘉诚先生:你经营公司57年来做过数十种行业,经营的区域几十个国家,那你有没有亏损过或不赚钱?

    他说:没有。李嘉诚先生57年来他的公司没有不赚钱过,他的个人的资产从来没有今年比去年低,从来没有过,持续57年。

    记者问他:你如何做到?李嘉诚先生说,他百分之90的时间在研究失败了后该怎么处理?如果你花百分之90的时间避开了所有可能失败的理由,请问你是不是已经非常接近成功了?
    可是一般的企业家头脑总是想找成功的方法,李嘉诚说:我们先把失败的原因全部研究一遍,当他研究这个步骤的时候,他已经立于不败。所以连续57年赚钱的人,他的思维模式跟我们一定不一样。
    现在我要下一个结论了,过去我接触数百万人,研究成功与失败的案例当中,我发现一个人最终失败的。

    大概可以总结下,只剩下一个原因,这一个叫做四个字,你一定要把它记下来,一旦你记下这四个字,你一辈子不要犯它,保证你迈向成功。这四个字叫做:

     "学习不够"

    学习不够是所有人失败最重要的关键因素,不是你不行,是你不会,你为什么不会?因为你学习不够,所以任何人成功就是学习,任何人失败就是学习不够,所以今天很幸运你已经读了这封信,你已经避免了失败是不是?

    可是有人就要问我了:那我现在已经避免失败了,那我怎么样迈向成功?接下来我要跟你分享三个字,这三个字就是超速成功的秘诀,不相信你就去问任何的世界第一名,只要他是世界之最,他一定在用这个观念,这个观念只有三个字叫做:

    “跟谁学”

    跟谁学学习这两个字我认为重要十万倍,我们都知道学习,但我们不知道什么叫做跟谁学,教练的级别会决定学员的表现,你相信吗?

    请问你刘翔的教练只是一个普通大专院校的田径老师吗?不可能,刘翔的教练一定是世界跨栏的顶级教练乔丹是篮球之神,请问你乔丹的教练只是一个会打篮球的人,还是他是NBA非常顶级的教练,肯定是顶尖的。

    我之所以成功不是我聪明,你要看教我的人是谁?安东尼.罗宾世界第一名,我比较逊色混来混去还亚洲第一。

    教你的是普通人,你就得到普通的结果,教你的是成功的人,你就得到成功的结果,教你是最顶级的人,你就得到最顶级的结果,是不是呢?

    所以不是你不行,不是你不会,是你压根不知道跟谁学的重要性,我在25岁的时候,我一直研究安东尼.罗宾为什么这么快速成功,怎么可能?我发现他就懂这三个字:跟谁学

    安东尼罗宾说他跟任何人学习,基本上他会问他自己四个问题,这四个问题决定你快速还是慢速的成长:

      1、这个人到底成不成功?
      2、教你的这个人到底有多年轻或者多快速成功?
      3、这个人帮助过多少人成功?
      (帮助过的人越多, 表示复制性越强)
      4、这个人在行业当中排第几名?

    你跟什么样的人接触,你一定像变色龙一样,发自不觉当中你就变成什么样的人,如果我们能够找到最顶级的人,行业的第一名来教我们,那我们成功的几率是不是更高了呢!
    2012年“世界末日”之前,我决定,给你一份世界上最珍贵的礼物——我决定在江苏苏州举办一次培训,课程名称叫《如何成为行业领袖之名师大舞台》。 
    在向你介绍课程中我将要教你的具体内容之前,首先让我解释一下……

      “为什么这是世界上最珍贵的礼物?
      为什么这是你最需要的礼物?”

    在我开设的课程当中,有一个《香港半岛总裁班》现在已涨价到28万人民币,一次只招收6——12个人,是许多人都望尘莫及的。
    我有一个学生庄玲,她在2006年上我《香港半岛总裁班》,从没有项目,没有资金,到现在创立了自己的品牌“莎蔓莉莎”美容美体店,被称为“中国的美容皇后”,在全国各地拥有超过2800多家的连锁店,而且全部是直营,一年有365天,从创立品牌到现在也就6年,多久开一家店?。。。。自己算吧。
    还有一个学生叫高凌风,是亚洲娱乐教父。是80年代身价最高的男艺人,当时身价最高的女艺人叫邓丽君,在当时他一天的出场费就可以买下一栋楼,但是后来他经商投资失败之后,被娱乐圈遗弃,得了忧郁症,人生跌到谷底,上了我的《香港半岛总裁班》,现在不仅重返娱乐圈,还在全国各地跟我巡回演讲。
    还有一个做网络营销的学员,他原来的月收入是4、5万一个月,上完课6个月后,他使用我教给他的方法,使用不同的管道,行销方式,结果他打电话给我,他的月收入已经达到2千万一个月
    。。。。。。。
    你有没有听过:思八达刘一秒、超越极限梁凯恩、商业模式林伟贤、中国启智教育训练第一人李强、盈利模式砍掉成本李践、学习型中国刘景澜、疯狂英语李阳、领导力权威张志诚、资源整合品牌战略孙晓岐、聚成董事长刘松琳,包括他们的大股东周荣罗恩、引爆潜能杨光、上海影响力易发久老师,。。。。。。
    这些人大家都听过,很有影响力,同时这些人都有一个共同点,就是全部上过安之老师的课程

      “出发点决定终点”

    我个人从未想过演讲会让我成为亿万富翁,我从来没有这样想过。因为当初我在美国学习了之后,有一天圣诞节假期,我跑回去台湾。结果后来,我的父亲就给我看了一本书,这本书叫《激发心灵潜力》
    作者当然就是我的恩师安东尼.罗宾,然后我想说,奇怪,我在美国刚刚在这家机构上班,安东尼.罗宾在美国刚刚展露头角,为什么台湾就已经把这本书翻译了,所以我很好奇的跑去问出版社的经理。
    我问他,为什么会把这本书翻译?这个这么新的东西。他说,安东尼.罗宾很棒,但是毕竟是美国人,而且从来没有来过亚洲,所以我正在寻找一个可以分享潜能激发资讯的中国人,他说,你愿不愿意回到台湾来帮助中国人?
    那工资呢,记得21岁在美国安东尼罗宾机构上班的时候,那时候我的工资是5000美金一个月,而且马上要升经理,1万美金1个月。可是他给我的工资是1000美金一个月,你猜我选择哪一个?是1万美金的安东尼罗宾机构继续待下去,还是选择1000块回到亚洲来?
    很明显,我选择1000块,所以我当初做这个事情,压根子就不是为了利润,因为出发点决定了终点,后来我在全亚洲每个小时的演讲费超过1万美金、2万美金
    可是来到中国,八、九年前,经济还没有这么发达,所以我自己降薪了,我自己又降了10倍的工资,所以选择来中国也不是要发大财,而是因为我有一个帮助中国人的使命。
    我从来不会计较哪个讲师比我优秀,我从来不会说,哪个讲师不好,因为我压根子只想帮助别人,所以上面我提到的那么多老师,第一个他们很成功,第二个他们很认真,第三个他们接受培训之后,他们都尽自己的最大力量在服务中国,在服务社会
    所以对此呢,我们需要在看这封信的你给他们掌声,感谢所有我提及到的老师,他们都是中国的影响力中心
    为了加速完成这个使命,当然了,只有一个陈安之是不够的,需要更多人的力量,为此我决定把《香港半岛总裁班》的精华,通通浓缩在《如何成为行业领袖之名师大舞台》这个课程里。

    posted @ 2012-08-14 09:04 奋斗成就男人 阅读(281) | 评论 (0)编辑 收藏

    当你举棋不定时,看看这100句话

    1.成功的人,就是那种能用别人扔向他的石头来铺设路基的人。

    2.批评你的人是你今天的敌人,明天的朋友;吹捧你的人是你今天的朋友,明天的敌人。

    3.Nothing is impossible.只要选择了目标,不要再想太远,每天脚踏实地,风雨兼程。生命不息,战斗不止。

    4.你和你的朋友会一起在将来打造一个可能很辉煌的事业。很好听是吗?记住,你们都要努力。

    5.很多事情当你再回忆时会发现其实没什么。所以,不管当时你多么生气都告诉自己不必这样,你会发现其实真的不必。
    6.
    别怕丢人,追求丢人是一种成功的尝试,至于为此笑话你的人,你可以把他们从你将来人生对手的名单中排除了,你也要为每一位上台唱歌的人鼓掌。

    7.人生在世,需要不断地为心灵除尘,自省、自责、自悟、自重……。

    8.永远不要对可能是坏事的事好奇,否则可能要了你的命。永远不要在痛苦的时候做决定,否则你以后一定会后悔。

    9.别为你自己和别人下定论,你所看到听到的可能只是一面。

    10.如果周围有人嫉妒你,那么你可以把他从你的竞争者之列排除了。

    11.很多事情别人通知你了,要说谢谢,没有通知你,不要责怪,因为那些事你其实应该自己弄清楚。

    12.一个人最大的痛苦,莫过于被圈在自己设定的圈子里出不来。就像一只蚕,丝吐的越多,对自己捆绑得越紧,直到最后完全把自己包上,想出也出不来。

    13.善良是一种智慧,是一种远见,一种自信,一种精神力量,是一种文化,一种快乐。

    14.一个人的脚步再大,也永远无法丈量完脚下的道路。人生有限,道路无限,要想在有限的生命中多走一程,就时刻别停下脚步,别浪费分秒时间。

    15.遇到再大困难的时候,不要惊慌,千万要学会冷静;不要去想着求别人,以前有家人帮你,现在需要你一个人面对挑战,从绝望中寻找希望,人生终将辉煌。

    16.学会说谢谢,但谢谢并不是随便敷衍,是对别人帮助的肯定和回报;更要学会说对不起,但对不起不是借口,是对自己过错的弥补和内疚。

    17.处事不必求功,无过便是功;为人不必感德,无怨便是德。

    18.有时你的快乐是你的微笑之源,但是有时候你的微笑却可能是你的快乐之源。

    19.不论男人还是女人,如果还把容貌当作重要的东西而过分重视的话,可能不会吃亏,但是早晚会吃亏.可能,很可能。

    20.放假的时候,要么留在家里多陪陪父母,帮他们做点事,远走高飞的你能像以前天天守在他们身旁的时间已不多;要么多去社会中体验生活,因为你不但要懂得生活,还要学会如何去生活。

    21.心烦意乱或者无聊闲着的时候,多到图书馆去泡泡,书中有现实中难得的纯明和清静;多看些书,生活会渐渐少一些迷茫,多一些追求。

    22.一个人如果心中时刻能够想着别人,别人也一定会时刻想着你。多替别人着想,就等于给自己铺设一条道路。你付出的越多,你得到的也会越多,这就叫做感情投资或感情积累。

    23.你可以输给任何人,但不能输给自己。

    24.经常给家里打个电话,即使嘴上都说不想对方,其实内心早已情动于中;有了女(男)朋友,也不能忘了爹和娘。

    25.多笑笑,会慢慢让自己真的快乐起来。

    26.好好利用公开场合锻炼、展示自我,哪怕只是一次课堂上的发言,别怕尴尬,更别怕丢人,也不要笑话在公众面前丢脸的人。

    27.小人的眼睛里没有君子,君子的眼睛却可以识破小人。

    28.屈原说:“路漫漫其修远兮,吾将上下而求索。”这种精神可贵,但在现实之中却很少有人能这样执着了。如果有人能够做到,他一定会是最成功的人。

    29.永远别渴望做个任何人都不得罪的人,有人反对有人支持然后自己做出决定是精彩的人生。

    30.一个生命完结,另一个生命诞生,世界就是在这种循环中得到永恒。用不着为死去的过于悲哀,也用不着为新生的过分高兴。生命都是一种相同的过程,关键在于能否使它辉煌。如果一个人能活得无愧无悔,坦坦荡荡,虽未轰轰烈烈,但这仍可算作是伟大的一生。

    31.后悔是一种耗费精神的情绪.后悔是比损失更大的损失,比错误更大的错误.所以不要后悔。

    32.你的确要学的有心计,但是记住,永远记住,在社会上要胜利的唯一的方法永远只是一个,那就是实力,永远不用怀疑。

    34.人生百态,不要对新的看不惯的东西生气,无所谓的。

    35.我们确实活得艰难,一要承受种种外部的压力,更要面对自己内心的困惑。在苦苦挣扎中,如果有人向你投以理解的目光,你会感到一种生命的暖意,或许仅有短暂的一瞥,就足以使我感奋不已,所以我们要学会感激。

    36.冷静,有大事时,能安静并能快速想出办法的人,很厉害。

    37.社会充满竞争,赢得竞争靠的是自己的实力。

    38.一种对工作和学习的冲击力及持久力会让你有特殊的魅力和个人实力

    39.父母给我们生命,生活给我们智慧。智慧产生于社会实践,这是千真万确的真理。因此,不仅要珍惜生命,珍视生活,更要重视社会实践。不经历风雨就无法见到彩虹,没有实践就无法得到智慧。

    40.积水成渊,积土成山。不积跬步无以致千里,做事万不可心急,必须从一点一滴做起,必须从每一件小事做起。现在的人常是小事不做,大事做不来,到头来空活一场,空耗一生。

    41.水涨船高,勿怕他人强于己。水落石出,别羡乌云压枝低。

    42.你可以选择坚持,也可以选择放弃。没有对错。我是说对爱情来说,但是重要的是坚持你的选择。

    43.如果老是去琢磨哪些人你讨厌,哪些人与你志趣相投,那么你就大错了,要想着如何让别人接纳你,而不是你能接受什么样的人。

    44.对陌生人,或者把对方当做一张白纸,或者把对方当你的朋友,总之别当做敌人,即使你听到再多的关于他(她)的不好的传闻。

    45.爱你的人,不管你接不接受,你都应该感谢对方,这是对他们的尊重。

    46.坚持在背后说别人好话,别担心这好话传不到当事人耳朵里,有人在你面前说某人坏话时,你只微笑。

    47.抽时间出来锻炼身体。

    48.不管现在你对未来多困惑,多迷茫,都不要忘了树立一个目标。一个人过去或现在的情况并不重要,将来想要获得什么成就才最重要。除非你对未来有理想,否则做不出什么大事来。

    49.不要把过去的事全让人知道,尊敬不喜欢你的人。

    50.成大事的方法多种多样 ,别不接受你看不惯的方法。 

    51.一切以健康为中心,遇事潇洒一点,看世事糊涂一点。

    52.气不鼓不能前进,气太足可能爆胎。

    53.三个忘记:忘记年龄,忘记过去,忘记恩怨。

    54.乐观的人看见问题后面的机会,悲观的人只看见机会后面的问题,机会是从来不会主动敲响你的门,无论你等待多少年。它也只会如一阵风一样拂面而过,需要你的反应能力和追随速度。朝着一个目标前进,尽量使用你的潜能,才华横溢的你会发现机会的存在。风虽然没有颜色,可是拂过之后却是绿意一片。

    55.后悔是一种耗费精神的情绪,后悔是比损失更大的损失,比错误更大的错误,所以不要后悔。

    56.人生唯一不会落空的等待是注定的死亡,世间唯一保持恒久不变的就是变化。

    57.最难战胜的敌人,是自己;最可怕的敌人,是朋友;最防不胜防的敌人,是欲望;最迷惑人的敌人,是感情。 

    58.生活是一种经历,也是一种体验;生活是一种感受,也是一种积累。生活没有答案,生活不需要答案。当生活即将不属于你时,你才会发现:生活仅仅是一个过程,而这个过程无论多么复杂,最终结局都是一样的。生活注重的是过程,而不是结局。

    59.奋斗人生的诀窍就是经营自己的长处。经营自己的长处能给你的人生增值。经营自己的短处必然使你的人生贬值。

    60.有所得是低级快乐,无所求是高级快乐。

    61.一个会讲话的人,不是记得别人说过话的人,而是能说些让人记得的话。

    62.是非窝里,人用口,我用耳;热闹场中,人向前,我落后。

    63.还能冲动,表示你还对生活有激情,总是冲动,表示你还不懂生活。

    64.从来没有得罪过人的人,注定也不可能与人深交。太多的平和与从容,反而丧失了做人的激情与率真。

    65.当不幸降临在他人头上时,他们往往都能像智者一样劝慰别人;而当同样的不幸降临自己身上时,人往往很难同样地开导自己。

    66.有些缺陷放在别人身上看起来微不足道,不值得一提;但是,这些缺陷若放在自己身上,则很难轻松看待,甚至一生都不能释怀。

    67.自己说过、做过伤害别人心灵的事,有可能转眼间就忘得一干二净;而别人说过或做过的伤害自己的事往往一辈子都能记得清清楚楚,且无法原谅。

    68.看别人生活时,我们总喜欢放大他们的幸福,忽略他们生活中的不幸,所以别人的生活怎么看都觉得幸福。而在看待自己的生活时,人们总喜欢缩小自己的幸福,扩大自己的烦恼,所以我们对自己的生活总有太多的不满。

    69.当别人在公众场所不小心出丑时,我们往往一笑了之;而当同样的情境在自己身上出现时,我们往往好长时间不能从尴尬中走出来。

    70.看到别人取得成功时,我们会说,他们的运气好;当他们遭遇失败时,我们会说,他们不努力。自己取得成功时,我们会说这是自己努力的结果;若遭遇失败,我们会自我解嘲说都是环境的错。 

    71.看别人谈恋爱挑肥拣瘦,我们暗说,不知自己长啥样,还在那儿挑挑拣拣。轮到自己谈恋爱时,总觉得没人能配得上自己。

    72.谁能永远顺利?人生的耻辱不在于输,而在于输不起;人生的光荣不在于永不仆到,而在于能屡仆屡起。

    73.思虑过少,可能失去做人的尊严;思虑过多,就会失去做人的乐趣。

    74.若能得而无愧疚,失而无怨悔,得失的结果,就由它去吧。

    75.光线强的地方,影子也比较黑。

    76.不要说自己有多好,别人一般不会相信;不要说自己有多坏,别人一般会相信的。

    77.不要在意别人对你的尖刻评论,学会超脱。

    78.不急于求回报,把帮助他人而得到的欣慰作为最好的回报。

    79.体贴他人的感情。嘲笑,必得不偿失,还可能造成意料不到的伤害。

    80.为了控制执著,必须观照好感觉的大门。

    81.每个人都有潜在的能量,只是很容易:被习惯所掩盖,被时间所迷离,被惰性所消磨。

    82.爱人就像粗布衣,虽然不美丽,可是能遮挡风寒。情人就像时装,感觉很美好,却不能穿出去。亲人就像老棉衣,就是出痱子,依然要捂着你。友人就像晴雨衣,需要了就穿,用过后放一边。

    83.人最聪明的,并不是捡起了别人还没捡到的东西,而是别人捡到了你不想捡的东西。

    84.创造机会的人是勇者。等待机会的人是愚者。

    85.忍耐是坚忍和能耐的简称。

    86.使人疲惫的不是远方的高山,而是鞋里的一粒沙子。

    87.人最悲哀的,并不是昨天失去得太多,而是沉浸于昨天的悲哀之中。

    88.昨天是一张废弃了的支票,明天是一笔尚未到期的存款,只有今天是你可以支配的现金。

    89.人人都讲理时有理可走遍天下,人人不讲理时有理将寸步难行。

    90.阳光虽然暖和,可照射的时间长了,也会遭到谩骂。

    91.乐观的人只顾著笑,而忘了怨;悲观的人只顾著怨,而忘了笑。

    92.如果成功方向是错误的,坚持到底就会错误到底。

    93.你有权发怒,但不应践踏别人的尊严;你有权失败,但不应自暴自弃;你有权争取成功,但不应以牺牲他人为代价;你有权要求争议,但不应以复仇为手段。你有权要求生活得更美好,但不应以今天的欺骗来捡取明天的快乐。

    94.人要有着眼点;又要有落脚点。前者是战略;后者是战术。

    95.世界上最永恒的幸福就是平凡,人生中最长久的拥有就是珍惜。

    96.不要贪图无所不有,否则你将一无所有;不要试图无所不知,否则你将一无所知;不要企图无所不能,否则你将一无所能。

    97.社会就像鱼塘,虽然泥沙俱下,可要真是清水一潭也有点可怕。家庭就像鱼缸,需要清洗,需要换气,需要精心护理,不然就生存不下去。

    98.面对失败和挫折一笑而过,是一种乐观自信;面对误解和仇恨一笑而过,是一种坦然宽容;面对赞扬和激励一笑而过,是一种谦虚清醒;面对烦恼和忧愁一笑而过,是一种平和释然。

    99.世上只有想不通的人,没有走不通的路。没有走不到顶的山,只有找不到路的人。

    100.放弃该放弃的是无奈,放弃不该放弃的是无能;不放弃该放弃的是无知,不放弃不该放弃的是执着。

    posted @ 2012-08-14 09:03 奋斗成就男人 阅读(296) | 评论 (0)编辑 收藏

    把想不通的事想通:——看完这篇文章受益终身!!!

    1、98年 马化腾等一伙凑了50万创办了腾讯 没买房;98年 史玉柱 借了50万搞脑白金 没买房;99年 丁磊用50万创办163.com 没买房;99年 陈天桥炒股赚了50万 创办盛大 没买房;99年 马云等18人凑了50万 注册阿里巴巴 没买房。如果当年他们用这50万买了房,现在估计还在还着银行的贷款吧。 

        2、年轻的我们必须懂得:1、你不勇敢,没人替你坚强。2、没有伞的孩子必须努力奔跑!3、自己选择的路、跪着也要把它走完。4、不要生气要争气,不要看破要突破,不要嫉妒要欣赏,不要拖延要积极,不要心动要行动。5、宁愿跑起来被拌倒无数次,也不愿规规矩矩走一辈子。就算跌倒也要豪迈的笑()

     

        3、人生三大遗憾:不会选择,不坚持选择,不断地选择;人生三不斗:不与君子斗名,不与小人斗利,不与天地斗巧;人生三修练:看得透想得开,拿得起放得下,立得正行得稳;人生三大陷阱:大意,轻信,贪婪;人生三大悲哀:遇良师不学,遇良友不交,遇良机不握。人生三大不争:不与领导争锋,不与同事争宠,不与下级争功

     

        4、一个人,如果你不逼自己一把,你根本不知道自己有多优秀。一个人,想要优秀,你必须要接受挑战;一个人,你想要尽快优秀,就要去寻找挑战。一个人,敢听真话,需要勇气;一个人敢说真话,需要魄力。一个人的知识,通过学习可以得到;一个人的成长,必须通过磨练。

     

        5、【最温暖的八种食物】①早上醒后来的一个煎蛋;②上班出门前塞在包里的一个苹果;③加班深夜回家后的一碗热汤;④睡觉前的一杯牛奶;⑤伏案工作时的一杯热茶;⑥生病卧床时的一碗白粥;⑦喝闷酒的时候一碟小菜;⑧酒醒后的一碗清汤面。《你吃到过几样?》

     

        6、网易CEO丁磊说:“千万不要以为我是抱着一个伟大的理想去创办一个伟大的公司,我从来没有远大的理想,也没有想要成为一个很有钱的人。创办网易时我只是想做一个小老板,就想有个房子有辆汽车,不用准时上班,可以睡懒觉。 我的梦想也是那么简单。”丁磊的话很实在。但是,现在创业已经不是那么简单了。

     

        7、人脉中需有的十种职业人:1 票贩子、 2旅行社、3律师、4 人才市场/猎头公司、 4 银行、5 当地公务人员/警察 、6 名人、7 保险/金融/理财专家、8 维修人员、9 媒体联络人、10 医生/护士/养生专家。《你认识这十种人吗?用心经营您的人脉关系吧!》

     

        8、【做人的底线】(1) 不做第三者,即使再喜欢(2) 骗我可以,如果被我知道超过两次,请你有多远滚多远(3) 如果你拿我不当回事,我会以同样方式对你(4) 我可以装傻,但别以为我真傻(5) 我可以容忍,但别超过我的底线(6) 我不是没脾气,只是不轻易发脾气(7) 任何真话,我都能接受。

     

        9、15岁觉得游泳难放弃游泳,到18岁遇到一个你喜欢的人约你去游泳,你只好说“我不会耶”。18岁觉得英文难,放弃英文,28岁出现一个很棒,但要会英文的工作,你只好说“我不会耶”。人生前期越嫌麻烦,越懒得学,后来就越可能错过让你动心的人和事,错过新风景—蔡康永(本文出自QQ123 234 661)

     

        10、25岁的英国士兵Barry Delaney穿着鲜亮的绿色吊带短裙和粉红腿套,在同袍好友Kevin Elliott的葬礼上哭的一塌糊涂,他俩是同在阿富汗执行任务的好友.他们之前有一个约定:无论谁先不幸西归,另一个都要穿女装亮相对方的葬礼,为那里灰暗的悲伤带去一丝亮色,很感人,一诺千金。《伟大的友谊,你有这样的朋友么?》

     

        11、慢慢成熟的标志:1早上无论多困,也会马上起床上班;2喜欢吃家常便饭多于外面的餐馆;3喜欢隐身,网络签名长时间不更改;4喜欢看新闻多于看八卦;5打电话给朋友的次数少了;6可以让你开心的人或事,越来越少了;7没结果的事情,渐渐就少做了;8低落的时候选择一个人呆着。

     

        12、美国旧金山有一老头查克费尼,穿旧衣服,戴烂手表,住出租屋,挤公交车。他为美国教育捐出了近20亿美金,还希望死前把仅有的40亿美金全部捐献给社会。在北京有个大富豪陈五喜,开豪车,住华宅,吃大餐,手上戴大钻戒,投资房地产,同时还在民政部门领取低保,8年间共得到10万元的社会救助。《中美差异》

     

        13、1931年的1月30日是世界现代史上灾难的一天,阿道夫·希特勒被任命为德国总理。他的名言:“消灭一个民族,首先瓦解它的文化;要瓦解它的文化,首先消灭承载它的语言;要消灭这种语言,首先先从他们的学校里下手。”,当今的中国大学里无论什么专业,英语是必修课,汉语却不是。

     

        14、尼古拉斯.科波拉,他的亲叔叔叫弗朗西斯.科波拉,名满天下的《教父》的导演。这个小伙子后来去好莱坞混,为了以自己的实力打天下,故意改名为尼古拉斯.凯奇。不想沾任何叔叔的光。中美文化的差异就在于此。《我爸是李刚》

     

        15、让你成熟至少5岁的8句话】1、如果你不喜欢现在的工作,要么辞职不干,要么闭嘴不言。2、学会忍受孤独。3、不要像玻璃那样脆弱,做个内心强大的人。4、管住自己的嘴巴。5、会创造机会。6、若电话老是不响,你该打出去。7、不要草率结婚。8、写出你一生要做的事情,把单子放在皮夹里,经常拿出来看。

     

        16、今年,年仅26岁的Facebook的创始人马克·扎克伯格,以40 亿美元身价登上2010 福布斯全球最年轻富豪榜榜首。目前已把自己过半财产捐赠给慈善事业。扎克伯格拥有亿万身家,但他至今仍和华裔女友普莉希拉·陈生活在一套租来的住房里,每天走路或骑自行车上班。

     

        17、澳大利亚老板帕尔默,他说:人每次只能睡一张床,吃一顿饭,驾一辆车,跟一个女人一起,所以我决定分一些给大家。为了感谢员工帮助他将企业扭亏为盈,他送给员工55辆奔驰,让750名员工出国度假,宴请2000名员工及家属。员工们兴奋的说,这样的老板,令我倾120%力量去工作。《神奇的领导力,无处不在》

     

        18、1992年一艘从中国出发的货船在太平洋上遭遇强烈风暴,船上一个装满2.9万只塑料玩具鸭的集装箱坠入大海。令人难以置信的是,其中1万多只玩具鸭组成的“鸭子舰队”在海洋上漂流了14年之后,竟抵达英国海岸。后来,这些鸭子售价激涨百倍。一个人的价值并不在其出身,而在于他谱写什么样的人生履历。。

     

        19、80后/90后的通病:1、近视;2、月光族;3、喜欢Money;4、从不锻炼身体;5、 一日三餐没有规律;6、路盲,没有方向感;7、搞不清楚自己的血型;8、有一颗狠宅狠宅的心;9、做事情都是三分钟热度;10、经常午夜12点以后才睡觉。《三条没有你就是神了》

     

        20、母亲一生的六个谎言:1.(童年时)快吃吧,我不饿;2.(少年时,深夜做针线活)快睡吧,我不困;3.(高考路上)快喝吧,我不渴;4.(参加工作,母亲生病时)你赶快去工作吧,我很好;5.(给母亲寄钱)你用,我有钱;6.(买房接她住)城里,我不习惯。愿天下的母亲健康长寿!《到了毕业的这个时候,更能体会妈妈的良苦用心,好好去爱她!》

     

        21、【永远都不要做的事】1,跟知己上床 2、和情人结婚 3、把同事当成朋友4、到朋友公司打工 5、在上司面前知无不言 6、轻信上司的许诺 7、喜怒哀乐都挂在脸上 8、在人堆里大声讲手机 9、习惯于给自己找借口 10、超车过去,看开着车有着窈窕背影的MM的脸 11、对MM的"字信以为真 12、指望前女友回心转意。

     

        22、【成功者的习惯】1.微笑。2.气质纯朴。3.不向朋友借钱。4.背后说别人好话。5.听到某人说别人坏话时只微笑。6.过去的事不让人全知道。 7. 尊敬不喜欢你的人。9.对事无情,对人有情。10.多做自我批评。11.为别人喝彩。12.感恩。13.学会聆听。14.说话时常用我们开头。15.少说话。16.喜欢自己。

     

        22、可敬可畏:1.日本电视台用中文进行广播,通知人们地震情况、躲避方式;2.每个家庭都有急救小包,包括药物、手摇式发电收音机;3、9级大震后东京建筑几乎安然无恙,尤其是人们避难时都井然有序的站在道路两侧尽量不阻碍交通,撤离后无一垃圾。日本是个危机意识、集体主义、纪律性极强的国家!

     

        23、【建立人脉的15个提示】1、学会换位思考;2、学会适应环境;3、学会大方;4、学会低调;5、嘴要甜;6、有礼貌;7、言多必失;8、学会感恩;9、遵守时间;10、信守诺言;11、学会忍耐;12、有一颗平常心;13、学会赞扬别人;14、待上以敬,待下以宽;15、经常检讨自己。

     

        24、55年前,就读于浙江大学的法国女子丹尼和中国学生袁迪宝相恋,但袁已婚了。1956年,丹尼伤痛中离开了中国。最初还通信,但慢慢就断了来往。去年初,袁试探着给丹尼写信,竟然回复了。9月,两人重逢第三天在厦门结婚,83岁的丹妮第一次穿上了婚纱。爱,它确实存在。《我相信爱情,你呢?》

     

        25、让你少奋斗10年的工作经验:1不要停留在心灵的舒适区域;2不要把好像、大概、晚些时候、或者、说不定之类的话放在嘴边;3不要拖延工作;4不要认为理论上可以实施就大功告成了;5不要让别人等你;6不要认为细节不重要;7不要表现得消极;8不要把改善工作能力仅寄托在公司培训上;9不要推卸责任。

     

        26、人平均一辈子只有7次决定人生走向的机会,两次机会间相隔约7年,大概25岁后开始出现机会,75岁以后就不会有什么机会了。这50年里的7次机会,第一次不易抓到,因为太年轻,最后一次也不用抓,因为太老,这样只剩5次了,这5次机会里又有两次不小心错过,所以实际上只有3次机会了。——哈佛的一项调查报告

     

        27、职场情商训练7法:1、把看不顺的人看顺;2、把看不起的人看起;3、把不想做的事做好;4、把想不通的事想通;5、把快骂出的话收回;6、把咽不下气的咽下;7、把想放纵的心收住;——你不需每时每刻这样做,但这样多做几回,你就会:1、情商高了2、职位升了3、工资涨了4、人爽了。

     

        28、泰勒语录:(1)我拥有一个女人的身体和一个孩子的情感。(2)我只和与我结婚的男人上过床。有多少女人敢这么说?(3)如果有人笨到花100万美元为我拍张照片,我当然不会笨到拒绝他。(4) 成功是一种了不起的除臭剂。它能带走所有你过去的味道。(5)我不会假装是个平凡的家庭主妇。

     

        29、她原系徐州女排队员,22岁嫁给50岁的cherry获绿卡后离婚、经新男友引荐入读耶鲁大学。96年旅行结识同座的starTV副总,经推荐在香港实习。97年晚宴她将一杯红酒洒在“传媒大亨”默多克身上,3年后他不顾家人反对而离婚并迎娶她。4年后她以高科技为他生下两个继承数十亿美金的女儿。她就是邓文迪。《运气总是留给有预谋的人。。》

     

        30、我年轻时曾与我们州最漂亮的女孩约会,但最后没有成功。我听说她后来离过三次婚,如果我们当时真在一起,我都无法想象未来会怎么样。所以,其实你人生中最重要的决定是跟什么人结婚!在选择伴侣上,如果你错了,将让你损失很多。而且,损失不仅仅是金钱上的。(BY巴菲特:结婚才是人生最大投资)

     

        31、盖茨39岁成世界首富,陈天桥31岁成中国首富,孙中山28岁创办兴中会,王然23岁当局长,孙权19岁据江东,丁俊晖15岁拿世界冠军,邓波儿7岁拿奥斯卡,贝多芬4岁开始作曲,葫芦娃刚出生就打妖怪。你说我们急不急。《我确实着急了!》

     

        32、理查森,男,纽约。从1984年起连续五次投资失败。2007彻底破产,妻离子散,朋友消遁,唯有一条名叫JOOY的狗与其不离不弃,忠伴左右,陪理查森一同在纽约的风雨街头乞讨。从“JOOY”安详恬静的睡姿中看得出它对主人的无限信任和依靠。有的人,在沧海变成桑田时,表现得还不如一条狗。《认识的人多了,我就喜欢了狗》

     

        33、?教父?经典台词:1、不要让别人知道你的想法。 2、当你说不时,你要使不听上去象是一样好听。 3、让朋友低估你的优点,让敌人高估你的缺点。4、痛苦不象死亡那样无可挽回!5、如果你没有时间和家人在一起,你就永远无法成为真正的男人。 6、永远不要恨你的敌人 ,因为这会影响你的判断力

     

        34、觉得自己做得到和做不到,其实只在一念之间。自己要先看得起自己,别人才会看得起你。一切伟大的行动和思想,都有一个微不足道的开始。有理想在的地方,地狱就是天堂;有希望在的地方,痛苦也成欢乐。乐观者在困难中看到机会;悲观者在机会中看到苦难。理想的路总是为有信心的人预备着。--﹣李嘉诚。

     

        35、女名叫安-德纳姆,生在美国堪萨斯。18岁的安在异族通婚非法的年代嫁给了一个非洲黑人留学生。后来,安和丈夫离婚成了单身母亲,她靠食品优惠券生活,是美国医保系统受害者,在重病时恳求保险公司赔付。然而她的孩子,图片里装扮成海盗的小孩,日后成了美利坚合众国第44任总统,巴拉克-奥巴马。《不要因为出身而看不起任何人!》

     

        36、阿米尔汗,8岁时出演一部轰动印度的电影,是公认的童星,长大后却一心打网球并获得过网球冠军。21岁爱上邻居家女孩,由于宗教原因两人决定私奔,现在过着幸福美满的生活。他是演员/制片人/导演。81届奥斯卡最佳影片《贫民窟的百万富翁》就是他担当的制片,2009年一部《三个白痴》震惊全球,他 45岁。《你相信坚持的力量么?》

     

        37、陈佩斯,因为央视出版他的小品而不给钱,较真打官司,遂被彻底封杀。此后陈消失,陈夫妇上山种树,脸朝黄土背朝天,两年获利30万。陈佩斯哭了,还想再演戏,可依旧被封杀,就砸30万改演话剧,第一部舞台喜剧《托儿》,在全国各地连续演出达120场,票房近4000万元,创造了当今话剧界无法超越的神话。《我就想说一句话:是金子在哪都发光。。。》

     

        38、她,37岁,癌症晚期。他,42岁,为筹钱给她治病,盗窃一辆电动自行车而入狱,刑期4年。2010年11月12日,他两人在监狱里举行了简单的婚礼,但这场童话般的婚礼,却让在场的数百位嘉宾感动得潸然泪下。偷辆电动车刑期4年,李刚儿子撞死人才3年。无语!一条人命还不如架电动单车。《生活在这个让人苦恼的社会。。。》

     

        39、天下只有两种人。比如一串葡萄到手,一种人挑最好的先吃,另一种人把最好的留到最后吃。照例第一种人应该乐观,因为他每吃一颗都是吃剩的葡萄里最好的;第二种人应该悲观,因为他每吃一颗都是吃剩的葡萄里最坏的。不过事实却适得其反,缘故是第二种人还有希望,第一种人只有回忆。——钱钟书。《你是哪种人?》

     

        40、他出身于书香门第,父亲是大学教授。他为爱妻,20年来从不上CCAV;他是个好爸爸;他顾家,厌恶应酬,滴酒不沾;他才华横溢,琴棋书画样样精通,学生时是体育全能,探戈高手;他饱读诗书,季羡林赞他可胜任北大的研究生导师,曾与钱钟书是忘年之交,他说他只是个戏子。他就是陈道明。一个很给力的男人。

     

        41、旧上海黑社会老大杜月笙的经典语录:1、做人有三碗面最难吃:人面、场面、情面。2、头等人,有本事没脾气;二等人,有本事有脾气;末等人,没本事大脾气。3、人可以不识字,但不能不识人。4、钱财用的完,交情吃不光。所以别人存钱,我存交情。存钱再多不过金山银海,交情用起来好比天地难量。

     

        42、成功根本没有秘诀,如果有的话,就只 有两个:第一个是坚持到底,永不放弃;第二个就是当你想放弃的时候,请回过头来再照着第一个秘诀去做。——丘吉尔

     

        43、善良的苏格兰农夫从粪池救出一个小男孩,男孩的绅士父亲酬谢,农夫拒。绅士说:让我们签个协议,我带走你的孩子,给他最好的教育,农夫允。农夫的孩子后来发明了青霉素,获得诺贝尔奖。数年后,绅士的儿子得了肺炎,青霉素治好了他。这两个孩子分别是弗莱明和丘吉尔。 《冥冥之中,自有天意》

     

        44、他,21岁,生意失败。22岁,州议员落选。24岁,生意再败。26岁,爱侣去世。27岁,一度精神崩溃。36岁,众议员落选。45岁,参议员落选。47岁,提名副总统落选。49岁时,参议员落选。52岁,当选美国第十六任总统。他叫林肯,坚信上帝的延迟,并不是上帝的拒绝,最终成就不凡。

    posted @ 2012-08-14 09:02 奋斗成就男人 阅读(145) | 评论 (0)编辑 收藏

    在SqlServer中 统计用户表中数据的行数 .

    declare @tableName nvarchar(50)
    declare @sql nvarchar(4000)
    declare @count int
    set @count=0
    set @tableName=''
    set @sql = ''

    declare cur cursor for
    select name from sysobjects
    where xtype='U'    --用户表

    open cur

    fetch next from cur into @tableName

    while @@fetch_status=0
    begin
        set @sql = N'select @count=count(1) from '+@tableName
        exec sp_executesql @sql,N'@count int output',@count output
    --    if(@count>0)
    --    begin
            print '表名称:'+@tableName+' 行数:'+cast(@count as varchar)
    --    end
        fetch next from cur into @tableName
    end

    close cur
    deallocate cur

    posted @ 2012-08-10 16:16 奋斗成就男人 阅读(858) | 评论 (0)编辑 收藏

    POI操作Excel表格

    在我们实际的开发中,表现层的解决方案虽然有多样,但是IE浏览器已成为最多人使用的浏览器,因为大家都用Windows。在企业办公系统中,常常有客户这样子要求:你要把我们的报表直接用Excel打开(电信系统、银行系统)。或者是:我们已经习惯用Excel打印。
    Apache的Jakata项目的POI子项目,目前比较成熟的是HSSF接口,处理MSExcel对象。它不象我们仅仅是用csv生成的没有格式的可以由Excel转换的东西,而是真正的Excel对象,你可以控制一些属性如sheet,cell等等。
    首先,理解一下一个Excel的文件的组织形式,一个Excel文件对应于一个workbook(HSSFWorkbook),一个workbook可以有多个sheet(HSSFSheet)组成,一个sheet是由多个row(HSSFRow)组成,一个row是由多个cell(HSSFCell)组成。
    POI可以到www.apache.org下载到。实际运行时,需要有poi包就可以了。HSSF提供给用户使用的对象在rg.apache.poi.hssf.usermodel包中,主要部分包括Excel对象,样式和格式,还有辅助操作。有以下几种对象:
    HSSFWorkbook excel的文档对象
    HSSFSheet excel的表单
    HSSFRow excel的行
    HSSFCell excel的格子单元
    HSSFFont excel字体
    HSSFDataFormat 日期格式
    在poi1.7中才有以下2项:
    HSSFHeader sheet头
    HSSFFooter sheet尾(只有打印的时候才能看到效果)
    和这个样式
    HSSFCellStyle cell样式
    辅助操作包括
    HSSFDateUtil 日期
    HSSFPrintSetup 打印
    HSSFErrorConstants 错误信息表
    以下可能需要使用到如下的类
    import org.apache.poi.hssf.usermodel.HSSFCell;
     import org.apache.poi.hssf.usermodel.HSSFCellStyle;
     import org.apache.poi.hssf.usermodel.HSSFDataFormat;
    import org.apache.poi.hssf.usermodel.HSSFFont;
     import org.apache.poi.hssf.usermodel.HSSFRow;
     import org.apache.poi.hssf.usermodel.HSSFSheet;
    import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.hssf.util.HSSFColor;
    先看poi的examples包中提供的最简单的例子,建立一个空xls文件。
    import java.io.FileOutputStream;
    import java.io.IOException;
    import org.apache.poi.hssf.usermodel.HSSFWorkbook;
    public class ExcelSample1 {
    public static void main(String[] args) throws IOException {
    //创建一个excel文件
    HSSFWorkbook wb= new HSSFWorkbook();
    FileOutputStream fileOut= new FileOutputStream("c:\\workbook.xls");
    // FileOutputStream fileOut= new FileOutputStream("c:/workbook.xls");
    wb.write(fileOut);
    fileOut.close();
    }
    }
    通过这个例子,我们在c盘下建立的是一个空白的xls文件(不是空文件)。
    在此基础上,我们可以进一步看其它的例子。
    import org.apache.poi.hssf.usermodel.*;
    import java.io.FileOutputStream;
    import java.io.IOException;
    public class CreateCells
    {
    public static void main(String[] args) throws IOException
    {
    HSSFWorkbook wb = new HSSFWorkbook(); //建立新HSSFWorkbook对象
    HSSFSheet sheet = wb.createSheet("new sheet"); //建立新的sheet对象
    HSSFRow row = sheet.createRow((short)0);
    //在sheet里创建一行,参数为行号(第一行,此处可想象成数组)
    HSSFCell cell = row.createCell((short)0);
    //在row里建立新cell(单元格),参数为列号(第一列)
    cell.setCellvalue(1); //设置cell的整数类型的值
    row.createCell((short)1).setCellvalue(1.2); //设置cell浮点类型的值
    row.createCell((short)2).setCellvalue("test"); //设置cell字符类型的值
    row.createCell((short)3).setCellvalue(true); //设置cell布尔类型的值
    HSSFCellStyle cellStyle = wb.createCellStyle(); //建立新的cell样式
    cellStyle.setDataFormat(HSSFDataFormat. getBuiltinFormat("m/d/yy h:mm"));
    //设置cell样式为定制的日期格式
    HSSFCell dCell =row.createCell((short)4);
    dCell.setCellvalue(new Date()); //设置cell为日期类型的值
    dCell.setCellStyle(cellStyle); //设置该cell日期的显示格式
    HSSFCell csCell =row.createCell((short)5);
    csCell.setEncoding(HSSFCell.ENCODING_UTF_16);
    //设置cell编码解决中文高位字节截断
    csCell.setCellvalue("中文测试_Chinese Words Test"); //设置中西文结合字符串
    row.createCell((short)6).setCellType(HSSFCell.CELL_TYPE_ERROR);
    //建立错误cell
    FileOutputStream fileOut = new FileOutputStream("workbook.xls");
    wb.write(fileOut);
    fileOut.close();
    }
    }
    通过这个例子,我们可以清楚的看到xls文件从大到小包括了HSSFWorkbook HSSFSheet HSSFRow HSSFCell这样几个对象。我们可以在cell中设置各种类型的值。尤其要注意的是如果你想正确的显示非欧美的字符时,尤其象中日韩这样的语言,必须设置编码为16位的即是HSSFCell.ENCODING_UTF_16,才能保证字符的高8位不被截断而引起编码失真形成乱码。其他测试可以通过参考examples包中的测试例子掌握poi的详细用法,包括字体的设置,cell大小和低纹的设置等。需要注意的是POI是一个仍然在完善中的公开代码的项目,所以有些功能正在不断的扩充。
    感觉上面的操作比较的繁琐,然后就自己写了一个方法。这个方法不需要事先创建row和cell,直接进行cteateCell就可以了,在程序中会自动进行判断,如果不存在的话会创建。
    private static void cteateCell(HSSFWorkbook wb,HSSFRow row,short col,short align,String val){
    HSSFCell cell = row.createCell(col);
    cell.setEncoding(HSSFCell.ENCODING_UTF_16);
    cell.setCellValue(val);
    HSSFCellStyle cellstyle = wb.createCellStyle();
    cellstyle.setAlignment(align);
    cell.setCellStyle(cellstyle);
    }
    对里面的几个参数的说明:
    short col 应该是你的cell单元格的位置也就是列号;
    short align 应该是你的对齐方式;
    String val 应该是你单元格里面要添加的值;
    具体的调用如下:
    HSSFRow row = sheet.createRow((short)1);
    cteateCell(wb,row,(short)0,HSSFCellStyle.ALIGN_CENTER_SELECTION,"SampleID");
    在上边的例子里我们看到了要设置一个单元格里面信息的格式(例如,要将信息居中)设置的操作如下:
    HSSFCellStyle cellstyle = wb.createCellStyle();
    cellstyle.setAlignment(HSSFCellStyle.ALIGN_CENTER_SELECTION);
    cell.setCellStyle(cellstyle);
    还有我们我们经常会用到的合并单元格,在这里我们也有这样的操作,代码如下:
    sheet.addMergedRegion(new Region(1,(short)1,2,(short)4));
     这里面我们还要介绍一个经常会遇到的问题,就是怎么来冻结一个窗口。poi也为我们集成了这样的事情了。代码如下:
    sheet.createFreezePane(1,2);
    λ 在这里我们需要注意的是
    一、该方法是在一个具体的sheet里面来进行操作。
    二、方法createFreezepane;有2个参数。前一个参数代表列;后一个参数代表行。
    上边的代码对应的excel文件如下:

    posted @ 2012-08-09 16:45 奋斗成就男人 阅读(917) | 评论 (1)编辑 收藏

    Java对Excel表格的操作

         摘要: Java对Excel表格的操作 目前软件开发多采用B/S架构。正B/S架构可以给软件的开发部署带来很大的便利,但是与此同时这种架构也带来了一些问题,例如Web报表的处理等,在B/S架构下,客户端的开发并没有丰富的、互动性能良好的界面组件供开发人员调用,而且调用客户端机器上的设备也很不方便。这些缺陷将会导致B/S架构的软件在客户端的一些功能开发陷入困境。    &n...  阅读全文

    posted @ 2012-08-09 16:31 奋斗成就男人 阅读(7034) | 评论 (1)编辑 收藏

    java中各种数据类型相互转换方法

    1如何将字串 String 转换成整数 int?

    A. 有两个方法:

    1). int i = Integer.parseInt([String]); 或
    i = Integer.parseInt([String],[int radix]);

    2). int i = Integer.valueOf(my_str).intValue();

    注: 字串转成 Double, Float, Long 的方法大同小异.


    2 如何将整数 int 转换成字串 String ?


    A. 有叁种方法:

    1.) String s = String.valueOf(i);

    2.) String s = Integer.toString(i);

    3.) String s = "" + i;

    注: Double, Float, Long 转成字串的方法大同小异.

    JAVA数据类型转换       ynniebo [收藏] 
    关键字     类型转换
    出处   

    这是一个例子,说的是JAVA中数据数型的转换.供大家学习引

    package cn.com.lwkj.erts.register;
    import java.sql.Date;
    public class TypeChange {
        public TypeChange() {
        }
        //change the string type to the int type
        public static    int stringToInt(String intstr)
        {
          Integer integer;
          integer = Integer.valueOf(intstr);
          return integer.intValue();
        }
        //change int type to the string type
        public static String intToString(int value)
        {
          Integer integer = new Integer(value);
          return integer.toString();
        }
        //change the string type to the float type
        public static    float stringToFloat(String floatstr)
        {
          Float floatee;
          floatee = Float.valueOf(floatstr);
          return floatee.floatValue();
        }
        //change the float type to the string type
        public static String floatToString(float value)
        {
          Float floatee = new Float(value);
          return floatee.toString();
        }
        //change the string type to the sqlDate type
        public static java.sql.Date stringToDate(String dateStr)
        {
          return    java.sql.Date.valueOf(dateStr);
        }
        //change the sqlDate type to the string type
        public static String dateToString(java.sql.Date datee)
        {
          return datee.toString();
        }

        public static void main(String[] args)
        {
          java.sql.Date day ;
          day = TypeChange.stringToDate("2003-11-3");
          String strday = TypeChange.dateToString(day);
          System.out.println(strday);
        }


    }

    JAVA中常用数据类型转换函数
    虽然都能在JAVA API中找到,整理一下做个备份。

    string->byte
    Byte static byte parseByte(String s) 

    byte->string
    Byte static String toString(byte b)

    char->string
    Character static String to String (char c)

    string->Short
    Short static Short parseShort(String s)

    Short->String
    Short static String toString(Short s)

    String->Integer
    Integer static int parseInt(String s)

    Integer->String
    Integer static String tostring(int i)

    String->Long
    Long static long parseLong(String s)

    Long->String
    Long static String toString(Long i)

    String->Float
    Float static float parseFloat(String s)

    Float->String
    Float static String toString(float f)

    String->Double
    Double static double parseDouble(String s)

    Double->String
    Double static String toString(Double)

    ++++++++++++++++++++++++++++++++++++++++++++++++++++++

    数据类型
    基本类型有以下四种:
    int长度数据类型有:byte(8bits)、short(16bits)、int(32bits)、long(64bits)、
    float长度数据类型有:单精度(32bits float)、双精度(64bits double)
    boolean类型变量的取值有:ture、false
    char数据类型有:unicode字符,16位
    对应的类类型:Integer、Float、Boolean、Character、Double、Short、Byte、Long

    转换原则
    从低精度向高精度转换
    byte 、short、int、long、float、double、char
    注:两个char型运算时,自动转换为int型;当char与别的类型运算时,也会先自动转换为int型的,再做其它类型的自动转换
    基本类型向类类型转换
    正向转换:通过类包装器来new出一个新的类类型的变量
    Integer a= new Integer(2);
    反向转换:通过类包装器来转换
    int b=a.intValue();
    类类型向字符串转换
    正向转换:因为每个类都是object类的子类,而所有的object类都有一个toString()函数,所以通过toString()函数来转换即可
    反向转换:通过类包装器new出一个新的类类型的变量
    eg1: int i=Integer.valueOf(“123”).intValue()
    说明:上例是将一个字符串转化成一个Integer对象,然后再调用这个对象的intValue()方法返回其对应的int数值。
    eg2: float f=Float.valueOf(“123”).floatValue()
    说明:上例是将一个字符串转化成一个Float对象,然后再调用这个对象的floatValue()方法返回其对应的float数值。
    eg3: boolean b=Boolean.valueOf(“123”).booleanValue()
    说明:上例是将一个字符串转化成一个Boolean对象,然后再调用这个对象的booleanValue()方法返回其对应的boolean数值。
    eg4:double d=Double.valueOf(“123”).doubleValue()
    说明:上例是将一个字符串转化成一个Double对象,然后再调用这个对象的doubleValue()方法返回其对应的double数值。
    eg5: long l=Long.valueOf(“123”).longValue()
    说明:上例是将一个字符串转化成一个Long对象,然后再调用这个对象的longValue()方法返回其对应的long数值。
    eg6: char=Character.valueOf(“123”).charValue()
    说明:上例是将一个字符串转化成一个Character对象,然后再调用这个对象的charValue()方法返回其对应的char数值。
    基本类型向字符串的转换
    正向转换:
    如:int a=12;
    String b;b=a+””;
    反向转换:
    通过类包装器
    eg1:int i=Integer.parseInt(“123”)
    说明:此方法只能适用于字符串转化成整型变量
    eg2: float f=Float.valueOf(“123”).floatValue()
    说明:上例是将一个字符串转化成一个Float对象,然后再调用这个对象的floatValue()方法返回其对应的float数值。
    eg3: boolean b=Boolean.valueOf(“123”).booleanValue()
    说明:上例是将一个字符串转化成一个Boolean对象,然后再调用这个对象的booleanValue()方法返回其对应的boolean数值。
    eg4:double d=Double.valueOf(“123”).doubleValue()
    说明:上例是将一个字符串转化成一个Double对象,然后再调用这个对象的doubleValue()方法返回其对应的double数值。
    eg5: long l=Long.valueOf(“123”).longValue()
    说明:上例是将一个字符串转化成一个Long对象,然后再调用这个对象的longValue()方法返回其对应的long数值。
    eg6: char=Character.valueOf(“123”).charValue()
    说明:上例是将一个字符串转化成一个Character对象,然后再调用这个对象的charValue()方法返回其对应的char数值

    posted @ 2012-08-09 16:29 奋斗成就男人 阅读(310) | 评论 (0)编辑 收藏

    Linux中常用命令学习总结

    前面的章节里对linux的文件的权限做了简单的解释。现在来看看常见的命令,从简单的开始:

    1 、切换目录

    cd

    到/tmp 目录:cd /tmp

    到上层目录:cd ..

    2 、查看当前目录

    pwd

    3、 创建一个新的文件夹:

    mkdir

    创建一层目录:

    创建多层目录:

    4 、删除目录:

    rmdir [-p]   如果需要层级删除目录,就需要带上p(只能删除空目录)

    5、查询环境变量

    echo $PATH  或者$PATH

     

    6、切换用户:

    su 用户名

    7、移动文件

     

     

    仔细阅读上面的命令,你会发现mv还可以对文件进行从命名,上面的命令将hellot.txt从a中移动到了b中,并改名为hello1.txt

     

    8、查看文件与目录

    ls

    ls -a  目录名称:列出目录中所有的文件

    ls -al 目录名:列出长字符串,包含文件的一些详细信息

    如果没有给定目录名,那么就是当前目录

     

    9、文件的复制:

    cp [-adfilprsu] 源文件  目标文件    //将源文件拷贝到目标文件

    cp  src1,src2,... des   //将多个源文件拷贝到目的文件夹

     

    cp这个命令非常重要,不同的身份执行对命令产生不同的效果,尤其是-a,-p参数,对不同的身份来说,区别非常大。

    例1:

    使用root执行:

    如果我们要将文件的所有的属性复制过来,则要加上参数-a

     

    复制一个目录到另外一个目录 cp -r /src /desc

     

     

    10 、移除文件或目录

    rm [-fir] 文件或目录

    -f 强制的意思,忽略不存在的文件,不会出现警告信息

    -i互动模式:删除前,会询问是否删除

    -r :递归删除

     

    这里不再演示,记得之前的rmdir吗,只能删除空目录,所以删除非空目录只能使用rm -r

    11、文件类容查询

    cat

    -b:列出行号

    -n:列出行号,包括空白行

     

    cat 是一次性将数据显示到屏幕上,如果想一页一页的看怎么办?

    使用more命令

    more在运行的过程中,你有几个按键可以按:

    空格键:代表向下翻一页

    Enter:代表向下滚动一行

    q:离开more

    b:往回翻页

     

     

    12 、创建文件

    touch

    touch a.txt 就会在当前目录下创建a.txt

     

    13、查找文件的命令

    whereis ,find

    whereis [-bmsu]  文件或目录名

    -b:二进制文件

    -m:只找在说明文件manual路径下的问津

    -s:只找source源文件

    -u:查找不在上述三个选项中的其他特殊文件

     

    whereis ifconfig

     

    下面看看find命令

     

    find [path] [option] [actioin]

    查找/home下面属于gavin的文件

    find   /home  -user  gavin

    查找系统中不属于任何人的文件

    find /  -nouser

    查找文件名为passwd的这个文件

    find    /     -name passwd

    查找文件类型为socket的文件

    find   /    -type s

     

    14、磁盘和目录的容量

    df:列出文件系统的整体磁盘使用量

    du:评估文件系统的磁盘使用量

    15 创建链接文件

    ln  [-sf] 源文件   目标文件

     

    -s  :创建软连接,如果不加则是硬连接

    -f:如果目标文件存在,则删除后再建

     

    [root@localhost test2]# echo 'good'>a.txt
    [root@localhost test2]# ls
    a.txt
    [root@localhost test2]# ln -s a.txt b
    [root@localhost test2]# ls
    a.txt  b
    [root@localhost test2]# ll
    total 12
    -rw-r--r-- 1 root root 5 Aug  8 01:09 a.txt
    lrwxrwxrwx 1 root root 5 Aug  8 01:09 b -> a.txt
    [root@localhost test2]# echo 'hello'>>b
    [root@localhost test2]# cat b
    good
    hello
    [root@localhost test2]# cat a.txt
    good
    hello
    [root@localhost test2]# ln a.txt c
    [root@localhost test2]# ll
    total 20
    -rw-r--r-- 2 root root 11 Aug  8 01:09 a.txt
    lrwxrwxrwx 1 root root  5 Aug  8 01:09 b -> a.txt
    -rw-r--r-- 2 root root 11 Aug  8 01:09 c
    [root@localhost test2]# echo 'bad'>>c
    [root@localhost test2]# cat c
    good
    hello
    bad
    [root@localhost test2]# cat a.txt
    good
    hello
    bad
    [root@localhost test2]# cat b
    good
    hello
    bad
    [root@localhost test2]# rm a.txt
    rm: remove regular file `a.txt'? y
    [root@localhost test2]# cat b
    cat: b: No such file or directory
    [root@localhost test2]# cat c
    good
    hello
    bad
    [root@localhost test2]#

     

    运行上面的命令行,相信你对ln的使用会非常清楚的。

     

    15、挂载CD

    16、文件压缩

    tar

    -c:创建一个压缩文件

    -v:显示压缩过程

    -f:给出压缩文件名

    -x:解压文件

    -t::查看压缩包中又哪些文件

    posted @ 2012-08-09 14:59 奋斗成就男人 阅读(270) | 评论 (0)编辑 收藏

    Linux文件权限的那些事

    linux是一个多用户,多任务的操作系统,对于每一个文件它的属性中都包括:文件所有者(owner),文件所属组(group),其他用户(other),还必须具备与这三个角色对应的读,写,执行的权限,如下图:

    在tmp目录下面有一个a.txt文件,我们通过ls -l命令可以查看其详细信息:

    -:表示普通文件,d:表示目录文件,l:链接文件,b:设备文件中可以供存储的接口设备,c:设备文件中串行端口设备如键盘。

    由于最前面是-:所以a.txt是普通文件。

    再看  rw-r--r--部分,我们将其分为三组,分别对应文件所有者,文件所属组,其他用户的权限.

    其中r代表读取权限,w:代表写权限,x:代表执行权限(这里没出现),-:代表没有某种权限。

    那对上面的权限的解释就是:

    owner:可以读和写,不能执行

    group:可以读取不能写,不能执行

    other:可以读取,不能写,不能执行

     

    第一个root代表文件所有者,第二个root代表文件所属组

    那么现在我如果想修改文件所有者,文件所属组,文件权限该怎么做,请继续向下阅读:

    chgrp:修改用户所属组,chown:修改文件所有者,chmod:修改文件权限

     

    假设我的系统中又一个叫gavin的组(通过/etc/group查看)

    如上图,通过chgrp命令将该文件的group修改为了gavin

    下面修改其所有者:

     

    修改其权限:

     

    chmod  777 a.txt   这个777代表什么?

    在linux中使用数字代表权限:

    r:4 w:2 x:1

    r--   =4+0+0=4;

    rw- =4+2+0=6;

    rwx =4+2+1=7

    相信写到这里大家都应该明白了吧。

     

    权限对于文件和文件夹的意义是不一样的,

    对于文件:

    r:代表可以读取文件的内容,w:代表可以修改文件的内容,x:可以执行这个文件

    对于文件夹:

    r:可以获取文件夹中又哪些文件,w:可以添加和删除文件夹中的内容,x:可以进入文件夹,

    如果某个角色对于一个文件夹的权限是rw-;

    那么他仅仅可以使用ls获取文件夹中的内容,但是不可以使用cd进入该文件夹。

     

     

     

    文件的权限告一段落,现在来看看linux中的那些常见目录中的内容:

    /bin   系统有很多放置执行文件的目录,但是/bin比较特殊,因为/bin放置的是在单用户维护模式下还能够被操作的命令,在/bin下面的命令可以被root和一般账户使用,如:cat,chmod,chown,data,mv,mkdir,cp ,bash等常用命令。

    /boot  主要放置开机使用到的文件

    /dev  在linux系统中任何设备与接口设备都是以文件的形式存在于这个目录当中,你只要访问某个文件就相当于访问该设备

    /etc  系统的主要配置文件几乎都在这个文件夹类。

    /home 这是系统默认的用户主文件夹

    /lib 系统的函数库非常多,二/lib放置的是开机会使用到的函数库

    /mnt 如果你想临时挂在一些外部设备(光盘)一般建议放置到这个目录。

    /opt 这是给第三方软件放置的目录

    /root 系统管理员的主文件夹

    /tmp 这是让一般用户或者正在执行的程序放置文件的地方,这个目录是任何人都可以访问的,所以你需要定期清理一下,当然重要数据时不能放到这里来的。

     

     

    关于文件权限的最后一点就是:文件默认权限umask

    现在我们已经知道如何新建或者改变一个目录的属性了,不过你知道当你新建一个新的文件或则目录是,它的默认权限是什么吗?那就是于umask这东西有关了,那么umask是在搞什么呢,基本上,umask就是制定目前用户在新建文件或目录的时候权限的默认值,如果获得或设置umask,方法如下:

    #umask  或则  umask -S

    (四位数,第一位我们先不管,表示特殊权限,我们从第二位开始看起)

    在默认权限上,文件和目录是不一样的,对于一个目录,x权限是非常重要的 ,而对于一个文件,x权限在默认是不应该有的,因为文件大多是用来存储数据的,所以在linux中,文件的默认权限是666,目录的默认权限是777

     

     

    要注意的是umask的分数指的是“默认值需要剪掉的权限”,

    所以新建文件时权限:rw--r--r--

    新建目录:r-xr-xr-x

    posted @ 2012-08-09 14:59 奋斗成就男人 阅读(126) | 评论 (0)编辑 收藏

    junit浅学笔记二

    上一节初步介绍了什么是单元测试,为什么要做单元测试,以及junit4的初步使用,这里我们接着说一下junit4中的注解。

      =============本节知识点============================

    *     Error和Failures

    *    Junit4 Annotation

    ==================================================================

     

    1.   在讲注解之前,先来认识 Error和Failures这两种错误有什么不同。

     

    Errors:表示程序本身错误

     

     

    @Test
    publicvoid testAdd() {
    int z=new T().add(5,3);
    assertEquals(
    8,z);
    int a=8/0; //这一句是有错误的
    }

     

    运行方法,会有一下错误提示:

    Failures: 是指测试失败。

    @Test
    publicvoid testAdd() {
    int z=new T().add(5,4); //这里修改了数值,把4该为3就正确了
    assertEquals(
    8,z);
    }

    在来运行这个方法,看一下错误提示:

    所以,我们在写测试程序的时候,要先保证Errors是没有错误的,再来看Failures有没有错误。

     

    2.  下面介绍junit4 的常用注解

    -----------------------------------------------------------------------------------------------

    *             @ Test:测试方法

                      A)  (expected=XXEception.class)

                    B)  (timeout=xxx)

    *.           @ Ignore: 被忽略的测试方法

    *.           @Before: 每一个测试方法之前云行。

    *.           @After : 每一个测试方法之后运行。

    *.           @BefreClass 所有测试开始之前运行。

    *.           @AfterClass 所有测试结果之后运行。

    ------------------------------------------------------------------------------------------------

    下面通过一个测试程序来解释这些注解含义

    复制代码
    package com.junit4.cc.test;

    importstatic org.junit.Assert.*;
    importstatic org.hamcrest.Matcher.*;

    import org.junit.Test;
    import com.junit4.cc.*;

    import org.junit.Before;
    import org.junit.BeforeClass;
    import org.junit.AfterClass;
    import org.junit.After;
    import org.junit.Ignore;


    publicclass TTest {

    @BeforeClass
    //的所有方法运行之前运行。
    publicstaticvoid beforeClass(){
    System.out.println(
    "------------beforeClass");
    }

    @AfterClass
    //在所有方法运行之后运行
    publicstaticvoid afterClass(){
    System.out.println(
    "-------------afterClass");
    }

    @Before
    //每个测试方法运行之前运行
    publicvoid before(){
    System.out.println(
    "=======before");
    }

    @After
    //每个测试方法运行之后运行
    publicvoid after(){
    System.out.println(
    "=======after");
    }

    @Test
    publicvoid testAdd() {
    int z=new T().add(5,3);
    assertEquals(
    8,z);
    System.out.println(
    "test Run through");
    }

    @Test ()
    publicvoid testdivision(){
    System.out.println(
    "in Test Division");

    }

    @Ignore
    //表示这个方法是不被运行的
    @Test
    (expected
    =java.lang.ArithmeticException.class,timeout=100) //timeout表示要求方法在100毫秒内运行完成,否则报错
    publicvoid testDivide(){
    int z =new T().divide(8,2);
    }



    }
    复制代码

    运行结果如下:

    标记红星(*)方法在每个方法开始和结尾都运行一次。

    标记绿星(*)的方法只在所有方法的开始和结尾运行一次。

    junit有多种注解,我们常用的也就上面几种。

    posted @ 2012-08-09 14:25 奋斗成就男人 阅读(137) | 评论 (0)编辑 收藏

    junit浅学笔记三

    这一节我们将学习进行批量处理,假如我们有多的测试,怎样进行批量处理,请跟着我做。

    ---------------------------------------------

    假如我们写了两个被测程序。如下:

    T.java

    复制代码
    package com.junit4.cc;

    publicclass T {
    publicint add(int x ,int y){
    return x+y;
    }
    publicstaticvoid main(String args[]){
    int z=new T().add(3,5);
    System.out.println(z);
    }
    }
    复制代码

    User.java

    复制代码
    package com.junit4.cc;

    publicclass User {
    public String geName(){
    return"刘若英"; //PS:她是我的偶像嘻嘻:)
    }
    }
    复制代码

    ------------------------------------测试类-------------------------

    下面要对上面的两个类写测试类。(关于测试类的创建的方法,不懂的可以看我的第一篇《junit浅学笔记一》)

    TTest.java   对应的是T.java的测试类。

    复制代码
    package com.junit4.cc.test;

    importstatic org.junit.Assert.*;

    import org.junit.Test;
    import com.junit4.cc.*;

    publicclass TTest {
    @Test
    publicvoid testAdd() {
    int z=new T().add(5,3);
    assertEquals(
    8,z);
    }
    }
    复制代码

    UserTest.java  对应的是User.java

    复制代码
    package com.junit4.cc.test;

    importstatic org.junit.Assert.*;

    import org.junit.Test;
    import com.junit4.cc.User;

    publicclass UserTest {

    @Test
    publicvoid testGeName() {
    assertEquals(
    new User().geName(),("刘若英"));
    }
    }
    复制代码

    完成之后的列表如下:

    要批量运行上面两个测试类,有两个方法。

    方法一

    右键点击测试包“com.junit4.cc.test”--->Run As--->Run Configurations.

    这种方式设置简单,但灵活度不高,假如有100个测试类。我只想运行其中的某几个测试类。下面看第二中方式。

     

    方法二

    方法引入一种“测试套件”的概念,JUnit提供了一种批量运行测试类的方法,叫测试套件。

      测试套件的写法需要遵循以下原则:

      1. 创建一个空类作为测试套件的入口;

      2. 使用注解 org.junit.runner.RunWith 和 org.junit.runners.Suite.SuitClasses 修饰这个空类

      3. 将org.junit.runners.Suite作为参数传入给注解RunWith,以提示Junit为此类测试使用套件运行器执行。

      4. 将需要放入此测试套件的测试类组成数组作为注解SuiteClasses的参数

      5. 保证这个空类使用public修饰,而且存在公开的不带任何参数的构造函数

    下面在测试包(com.junit4.cc.test)下面创建一个测试类,内容如下:

    AllTest.java

     

    复制代码
    package com.junit4.cc.test;


    import org.junit.runner.RunWith;
    import org.junit.runners.Suite;
    import org.junit.runners.Suite.SuiteClasses;
    @RunWith(Suite.
    class)
    @SuiteClasses({
    TTest.
    class,
    UserTest.
    class //这里自由加入需要运行的测试类
    })
    publicclass AllTest {

    }
    复制代码

     

    创建之后的列表:

     

    运行AllTest.java的结果(这里,两个方法的运行结果是一样的):

     

    ps:关于两种方式的比较,第一种方法简单,只用选择测试包,就可以批量运行里面的所有测试程序。第二种方式还有重新创建一个测试类,但它非常灵活,只用在这个类中加入需要运行的类就可以灵活的运行需要测试的类。

    posted @ 2012-08-09 14:24 奋斗成就男人 阅读(188) | 评论 (0)编辑 收藏

    junit浅学笔记一

     JUnit是一个回归测试框架(regression testing framework)。Junit测试是程序员测试,即所谓白盒测试,因为程序员知道被测试的软件如何(How)完成功能和完成什么样(What)的功能。Junit是一套框架,继承TestCase类,就可以用Junit进行自动测试了。

         虽然大多情况下他是程序员的活,但作为测试人员还是有必要了解一下,毕竟也是测试工作,提高自己人技术,扩展思想是主要,边学边做笔记,这样学过的东西才不会忘记,嘻嘻~!

     ========学习环境=================

    java编辑器: Eclipse SDK 3.5.6

    junit测试包:Eclipse中自带了junit 4 测试包

    =================================

    1.我们打开eclipse 创建一个工程名字为:Junit4,

    创建一个包,命名为:com.junit4.cc ,

    包下面创建一个类 T

    代码如下:

    复制代码
    package com.junit4.cc;
    publicclass T {
    publicint add(int x ,int y){
    return x+y;
    }

    }
    复制代码

    我们如何来做测试,当然了,上面的代码一眼就可以看出结果,需要测试么,我们这里只是想说明问题,如果我们不用测试框架,我们会用写一个main方法对上面的代码进行验证。全部代码如下。

    复制代码
    package com.junit4.cc;
    publicclass T {
    publicint add(int x ,int y){
    return x+y;
    }
    publicstaticvoid main(String args[]){
    int z=new T().add(3,5); //向T类传递两个参数3和5
    System.out.println(z); //打印z进行查看3和5是否做了加法运算
    }
    }
    复制代码

    云行上面的代码,通过查看结果来判断add方法是否正确。

    ---------------------------------------------------------------------------

    上面的单元测试有很多弊端:

    @ 需要花费很多的时间来写测试代码

    @ 测试代码不可重用,一段测试代码对应一段被测代码。被测代码变,测试代码就没用了

    @ 无法同时运行多个测试代码。假如有一百个被测试代码,要一个一个的运行测试代码,用肉眼观察结果,效率低还容易出错。

    这是我简单总结的几个缺点。

    ---------------------------------------------------------------------------

     

    2.   那么我们就要使用单元测试框架来提交效率。

    下面我们就使用eclipse来创建一个测试。还是测试上面的代码为例子。

    为了查看更加清晰,我们一般将测试代码与被测试的代码放在不同的包下面。

    我们在Junit工程下面重新创建一个包,命名为:com.junit4.cc.test

    ----------------------------

    创建一个测试类:TTest

    注意:这里要创建的是一个测试类:在com.junit4.cc.test包上面右键点击-->new-->Junit test Case

    点击“Next”会让你选择要测试的方法,选择后点击“Finish”则完成创建。

    创建完成如下图:

    TTest.java代码如下:

    复制代码
    package com.junit4.cc.test;

    importstatic org.junit.Assert.*;

    import org.junit.Test;
    import com.junit4.cc.*;

    publicclass TTest {

    @Test
    publicvoid testAdd() {
    int z=new T().add(5,3);
    assertEquals(
    8,z);
    }

    }
    复制代码

     

    3.   如果我们想要真正运行TTest.java这个测试类,还要对这个工程引入junit测试包。

    右键点击工程(junit4)--->Properties

    点击“next ” 按钮,celipse提供junit3和junit4两个测试包,我们选择junit4 点击“finish”就将测试包引入。

     

    4.  下面来运行我们TTest.java测试代码。

    看到我们左侧的绿色滚动条,说明我们的被代码是没有问题。

    你可以试着修改下面代码的参数:

    int z=new T().add(5,3);  
      assertEquals(8,z);    //将5、3、8等数字任意修改,查看绿色滚动条的颜色,给出的提示是什么?

    posted @ 2012-08-09 14:23 奋斗成就男人 阅读(136) | 评论 (0)编辑 收藏

    junit浅学笔记二

      上一节初步介绍了什么是单元测试,为什么要做单元测试,以及junit4的初步使用,这里我们接着说一下junit4中的注解。

      =============本节知识点============================

    *     Error和Failures

    *    Junit4 Annotation

    ==================================================================

     

    1.   在讲注解之前,先来认识 Error和Failures这两种错误有什么不同。

     

    Errors:表示程序本身错误

     

     

    @Test
    publicvoid testAdd() {
    int z=new T().add(5,3);
    assertEquals(
    8,z);
    int a=8/0; //这一句是有错误的
    }

     

    运行方法,会有一下错误提示:

    Failures: 是指测试失败。

    @Test
    publicvoid testAdd() {
    int z=new T().add(5,4); //这里修改了数值,把4该为3就正确了
    assertEquals(
    8,z);
    }

    在来运行这个方法,看一下错误提示:

    所以,我们在写测试程序的时候,要先保证Errors是没有错误的,再来看Failures有没有错误。

     

    2.  下面介绍junit4 的常用注解

    -----------------------------------------------------------------------------------------------

    *             @ Test:测试方法

                      A)  (expected=XXEception.class)

                    B)  (timeout=xxx)

    *.           @ Ignore: 被忽略的测试方法

    *.           @Before: 每一个测试方法之前云行。

    *.           @After : 每一个测试方法之后运行。

    *.           @BefreClass 所有测试开始之前运行。

    *.           @AfterClass 所有测试结果之后运行。

    ------------------------------------------------------------------------------------------------

    下面通过一个测试程序来解释这些注解含义

    复制代码
    package com.junit4.cc.test;

    importstatic org.junit.Assert.*;
    importstatic org.hamcrest.Matcher.*;

    import org.junit.Test;
    import com.junit4.cc.*;

    import org.junit.Before;
    import org.junit.BeforeClass;
    import org.junit.AfterClass;
    import org.junit.After;
    import org.junit.Ignore;


    publicclass TTest {

    @BeforeClass
    //的所有方法运行之前运行。
    publicstaticvoid beforeClass(){
    System.out.println(
    "------------beforeClass");
    }

    @AfterClass
    //在所有方法运行之后运行
    publicstaticvoid afterClass(){
    System.out.println(
    "-------------afterClass");
    }

    @Before
    //每个测试方法运行之前运行
    publicvoid before(){
    System.out.println(
    "=======before");
    }

    @After
    //每个测试方法运行之后运行
    publicvoid after(){
    System.out.println(
    "=======after");
    }

    @Test
    publicvoid testAdd() {
    int z=new T().add(5,3);
    assertEquals(
    8,z);
    System.out.println(
    "test Run through");
    }

    @Test ()
    publicvoid testdivision(){
    System.out.println(
    "in Test Division");

    }

    @Ignore
    //表示这个方法是不被运行的
    @Test
    (expected
    =java.lang.ArithmeticException.class,timeout=100) //timeout表示要求方法在100毫秒内运行完成,否则报错
    publicvoid testDivide(){
    int z =new T().divide(8,2);
    }



    }
    复制代码

    运行结果如下:

    标记红星(*)方法在每个方法开始和结尾都运行一次。

    标记绿星(*)的方法只在所有方法的开始和结尾运行一次。

    junit有多种注解,我们常用的也就上面几种。

    posted @ 2012-08-09 14:23 奋斗成就男人 阅读(116) | 评论 (0)编辑 收藏

    LR有的JMeter也有之二“检查点”

    检查点:简单的来理解一下,上一章讲到,我们对用户名和密码进行了参数化,那么怎样来判断jmeter有没有正确调用test.dat里面的文件呢。当然,我们可以从结果图表中查看。但我还是想在“登录”这个地方进行一下检查。

    jmeter里面的检查点通过添加断言来完成。

    1.

    右键点击我们的“登录”页面---->添加---->断言---->响应断言

    来设置一下断言页面,我们想断言什么呢?调用的用户名和密码是不是我们test.dat文件里的用户名和密码,怎样来进行呢。

     

    3.

    这里我们需要分别准备两个文件,一个放用户名,一个放密码。

        

    下面编写函数来调用这两个文件,如何编写先看我上一篇文章。

    在响应断言页面添加两个“模式”

    (第三步还有一种方法,直接调用原来test.dat的数据进行检查,我试了半天一直失败,不知道原因在哪儿?)

    4.

    添加一个断言结果

    右键点击我们的“登录”页面---->添加---->监听器---->断言结果

    还可以再添加一个“查看结果树” 右键点击我们的“登录”页面---->添加---->监听器---->查看结果树

     

    在线程组中设置5个用户,点击运行运行。

    查看断言结果:

    查看结果做:

    好了,检查点添加成功!

    posted @ 2012-08-09 14:22 奋斗成就男人 阅读(143) | 评论 (0)编辑 收藏

    LR有的JMeter也有之三“集合点”

    集合点:简单来理解一下,虽然我们的“性能测试”理解为“多用户并发测试”,但真正的并发是不存在的,为了更真实的实现并发这感念,我们可以在需要压力的地方设置集合点,

    还拿那个用户和密码的地方,每到输入用户名和密码登录的地方,所有的虚拟用户都相互之间等一等,然后,一起访问。(红军排长说:等一等!大家一起冲啊!这样给敌人的压力是很大的。嘻嘻!)

    1.

    接着之前创建的脚本,右键点击 step1---->定时器---->Synchronizing Timer

    这样子就添加了一个“集合点”,下面来设置一下集合点。

     

    2.

    我们添加完之后的列表是这个样子的,

     发现了没,我们集合点的位置不对,应该在登录的前面才对。怎么弄呢?

    点击“synchronizing Timer”拖动到“登录”面前的位置,不要松鼠标的左键,再点击鼠标的右键,选择在“之前插入”---有点难噢,慢慢来!

             

    OK!!

    posted @ 2012-08-09 14:22 奋斗成就男人 阅读(136) | 评论 (0)编辑 收藏

    使用JMeter创建FTP测试计划

    FTP服务主要提供上传和下载功能。有时间需要我们测试服务器上传和下载的性能。在这里我通过JMeter做一个FTP测试计划的例子。

    当然,JMeter官方网站的用户手册也有例子,但由于版本较早,我也算是对自己学习的一个总结,所以再整理一个。

    * 本人使用的是JMeter2.4版本。

    * 测试的服务器是IP:124.205.228.54  (由于找不到FTP站点,所以在“主机屋网站http://www.zhujiwu.com申请了一个免费的FTP空间”)

    1.创建一个线程组

    2.线程组--->添加--->配置元件--->FTP请求缺省值。

    3.线程组--->添加--->Sampler--->FTP请求

    说明:

    IP    为你FTP服务的IP

    Remote file 为你FTP服务器上的一个文件。

    local file  为本地你存放到本机上的路径。

    选择   get(RETR)  为下载方式。

    填写你的FTP服务器的用户名密码。

    3.按照第二步的方式再添加一个“FTP请求”。

    说明:

    IP    为你FTP服务的IP

    Remote file 为你要上传到FTP服务器上的文件路径及文件名

    local file  为本地你要上传的文件的路径。

    选择   put(RETR)  为上传方式。

    填写你的FTP服务器的用户名密码。

    4.添加一个监控器:线程组--->添加--->监控器--->Spline Visualizer

    一个FTP计划创建成功 :)

    posted @ 2012-08-09 14:21 奋斗成就男人 阅读(323) | 评论 (0)编辑 收藏

    LR有的JMeter也有之一“参数化”

    参数化:简单的来理解一下,我们录制了一个脚本,这个脚本中有登录操作,需要输入用户名和密码,假如系统不允许相同的用户名和密码同时登录,或者想更好的模拟多个用户来登录系统。

    这个时候就需要对用户名和密码进行参数化,使每个虚拟用户都使用不同的用户名和密码进行访问。

    前提:

    假如,我们录制好了一个脚本(可以用badboy工具录制),在jmeter中打开,找到有用户名和密码的页面。如下:

    1.

    我们需要“参数化”的数据,这里我用记事本写了五个用户名和密码,保存为.dat格式的文件。

    我将这个文件放在了我的( D:\test.dat  )路径下。关于如何得到成百上千的用户名和密码,首先要在数据库中创建这些数据,将数据导出,整理保存,这里就不深究。

     

    2.

    好,我们要编写函数来调用这个test.dat文件,怎么弄,

    点击菜单栏“选项”---->函数助手对话框,看下图。

     

    3.

    把我们写好的函数复制到“登录”页面用户名和密码胡位置。

    好了,现在我们的参数化设置完成,在脚本的时候,会调用我们D盘下面的test.dat文件,第一列是用户,第二列是密码。

    注意用户名和密码是一一对应的,中间用户逗号(,)隔开。

    posted @ 2012-08-09 14:21 奋斗成就男人 阅读(198) | 评论 (0)编辑 收藏

    一种简单的数据库性能测试方法

        这两天接到一个任务,要测试一个服务器的性能,客户要求向数据库内 1000/s(每插入一千条数据)  的处理能力,当时脑子赌赛了,想的是用LR来进行,由于LR接触不深,只知道LR实现参数化的时候可以调用数据库里面的数据,往里面大批量的插入数据,以前没试过。

        翻阅了一下资料,找一到了一篇《一种特殊的数据库性能测试》,大概思路是:通过编写一java程序来循环插入数据,编写一个批处理文件来调用java程序。再通过LR的system()函数来调用批处理文件来进行压力测试。但是对于我这种菜鸟来说,好多细节不懂。比如那个批处理就让我很为难。呵呵。

      其实,通过jmeter很简单就可以完成,可以参考我以前的一篇文章《jmeter创建数据库(MySql)测试》。

      前提条件:一个数据库:test   数据库下面有一张表:user   表中有两个字段:username、passworld 。

      要求:往数据库内大批量插入数据,1000/s  

    其实和之前的方法一样,为了简单,我还是把截图贴出来吧。

    1.

    创建一个测试计划,将我们所使用的数据库驱动包导入。

    2.

    添加一个线程组,并设置我们的虚拟用户数、启动时间、和循环次数

    3.

    创建一个线程,并在线程下面,创建一个JDBC Connection Configuration ,设置相关信息。

    4.

    创建一个JDBC Request.我们需要对数据库做插入操作。(详细设置,看截图上的说明)

    5.

    添加监听器,我们这里选择添加“图形结果”和“查看结果树”,点击菜单栏上的“启动”--->运行。

    查看我们的运行结果。

    在测试的过程中,通过数据库命令,可以查看当前数据库插入了多少数据

     

    posted @ 2012-08-09 14:20 奋斗成就男人 阅读(125) | 评论 (0)编辑 收藏

    JMeter基础之—录制脚本

    Jmeter 是一个非常流行的性能测试工具,虽然与LoadRunner相比有很多不足,比如:它结果分析能力没有LoadRunner详细;很它的优点也有很多:

      l       开源,他是一款开源的免费软件,使用它你不需要支付任何费用,

      l       小巧,相比LR的庞大(最新LR11将近4GB),它非常小巧,不需要安装,但需要JDK环境,因为它是使用java开发的工具。

          l       功能强大,jmeter设计之初只是一个简单的web性能测试工具,但经过不段的更新扩展,现在可以完成数据库、FTPLDAPWebService等方面的测试。因为它的开源性,当然你也可以根据自己的需求扩展它的功能。

    我觉得它更像一个瑞士军刀,小巧,且功能齐全。初次认识Jmeter的时候,我觉得它不好,是因为相比LR来说,它没有脚本录制功能,也许不是没有,只是我不知道,因为文档上介绍的是这样,我要做一个web性能测试的话,就手动的一个个添加循环控制器、http信息管理头、http请求等等各种元件。如果测试的脚本较多时,这无疑是个体力活。

           Badboy是一款不错web自动化测试工具,利用它来录制脚本,并且录制的脚本可以直接保存为JMeter文件来使用。我无疑给我们带来了很大我方便。

    ----------------------我的环境------------

    Badboy  version 2.1.1

    Apache  JMeter-2.3.4 (需要JDK环境来运行)

    --------------------------------------------

    第一种方法:通过bodboy来录制脚本。

     

    1.打开人badboy工具,点击工栏目上的红色圆形按钮,在地址栏目中输入被测试项目的地址。

     

    录制完成后,点击工具栏旁边黑色按钮,结束录制。

    选择“文件”--àExport to Jmeter…

     

     

     

    2.打开Jmeter工具,选择“文件”-->“打开”选择刚才保存的文件(.jmx类型),将文件导入进来了。

     

     

     

    第二种方法,通过JMeter自身设置来录制脚本。

     

    这种方法是我才发现的(鄙视一下自己的无知,嘻嘻~!),觉得方法比较简单。 

    <!--[if !supportLists]-->1.       <!--[endif]-->打开JMeter工具

    创建一个线程组(右键点击“测试计划”--->“添加”---->“线程组”)

    创建一个http代理服务器(右键点击“工作台”--->“添加”--->“非测试元件”--->“http代理服务器”

    完整的设置参照下图:

     

    2.  下面来设置一下IE浏览器

    IE--->“internet属性”--->“连接”--->“局域网设置”

    设置为本机IP就可以了,注意端口号要与Jmeter上的端口号一致。默认都是8080端口。

    3.   现在点击jmeter上的“启动”按钮,打开浏览器输入需要录制web项目地址,jmeter会自动记录你IE所访问的页面。

    PS:第二种方法是我刚才知道的一种,关于这两种方法哪个更好,现在还不知道,但第二方法有通过IE浏览器辅助的,我想可能只要IE能打开的,它都能记录,但它录制的脚本看上去比较乱(感觉上)

    还就是http代理服务器的设置,(比如:分组:每一个组放入一个新的服务器---只有这一个选项才能正常录制),有时间再仔细比较一下两种方法的不同之处。

    posted @ 2012-08-09 14:19 奋斗成就男人 阅读(301) | 评论 (1)编辑 收藏

    菜鸟学自动化测试(一)----selenium IDE

    对于,我们做测试的新手来说,自动化测试一直是一个比较高级的领域,当然是相对于手工测试来说。最近,对自动化测试产生了兴趣。不,具体点应该是对selenium工具产生了兴趣。为什么不是QTP呢,之前,QTP也有学习,后来还买了本《QTP自动化测试进阶指南》,看了几天,不知为什么看不下去。嗯!我一直偏爱于开源的技术和工具。最早用LR做性能测试,后来发现了JMeter那个小工具后,基本上能用JMeter解决的问题,就不在用LR了。开源的东西好处多多,当然了不足也多多。这里就不啰嗦了。呵呵。

        下面说说selenium吧!想学一样东西,找相关学习资料是第一步。说说我觉得比较好的资料:《selenium私房菜系列》、selenium官方文档、《selenium 1.0 testing tools 》。不过,我还是买了一本书,我把在当当网的评论贴过来。

    "本来想买,后来听朋友说,内容行间距很大,有凑页数的意思,前面部分是在翻译(selenium)官网的文档,包括后面也?有真正写出作者公司的实战经验。打开一看基本和朋友说的一样。为什么后来又要买了,有几分无奈在里面。selenium 的中文资料并不多,网上的都是零散的皮毛,本人英语很差,所以,英文的资料看起来太吃力。《selenium 1.0 testing tools 》其实是一本很好的书,可惜没有中文的,其实可以慢慢啃,但selenium 2.0都出来了,selenium RC 已经被selinum server替代,又加了很多新技术,跟不上啊。所以,只能选了这本书,希望对我有所帮助。" 下面我的笔记也算是基于《零成本实现web自动化测试---基于seleinum与Bromine》这本书的。

    ----//认识IDE面板

    关于selenium IDE的安装,请参考我的上一篇文章《selenium RC 配置

    为了方便简洁,我们就按照上图的数字标记介绍:

    1文件:创建、打开和保存测试案例和测试案例集。编辑:复制、粘贴、删除、撤销和选择测试案例中的所有命令。Options : 用于设置seleniunm IDE。

    2。用来填写被测网站的地址。

    3。速度控制:控制案例的运行速度。

    4。运行所有:运行一个测试案例集中的所有案例。

    5。运行:运行当前选定的测试案例。

    6。暂停/恢复:暂停和恢复测试案例执行。

    7。单步:可以运行一个案例中的一行命令。

    8。录制:点击之后,开始记录你对浏览器的操作。

    9。案例集列表。

    10。测试脚本;table标签:用表格形式展现命令及参数。source标签:用原始方式展现,默认是HTML语言格式,也可以用其他语言展示。

    11。查看脚本运行通过/失败的个数。

    12。当选中前命令对应参数。

    13。日志/参考/UI元素/Rollup

    日志:当你运行测试时,错误和信息将会自定显示。

    参考:当在表格中输入和编辑selenese命令时,面板中会显示对应的参考文档。

    UI元素/Rollup:参考帮助菜单中的,UI-Element Documentation。

     

    ----//编辑命令

    selenium为我们录制的脚本不是100%符合我们的需求的,所以,编辑录制的脚本是必不可少的工作。

    1.  编辑一行命令或注释。

     在Table标签下选中某一行命令,命令由command、Target、value三部分组成。可以对这三部分内容那进行编辑。

     2.  插入命令。

      在某一条命令上右击,选择“insert new command”命令,就可以插入一个空白,然后对空白行进程编辑。

      3. 插入注解

       以上面同样的方式右击选择“insert new comment”命令插入注解空白行,本行内容不被执行,可以帮助我们更好的理解脚本,插入的内容以紫色字体显示。

     4. 移动命令或注解

      有时我们需要移动某行命令的顺序,我们只需要左击鼠标拖动到相应的位置即可。

     

    ----//录制我们的第一个脚本

    我们的录制流程:

    用火狐浏览器,打开一个新的标签-----输入谷歌网址(http://www.google.com.hk/)----在搜索框输入:selenium----点击“google搜索”按钮。 

    注:注意开启和关闭selenium IDE面板上的红色圆形的录制按钮。

    录制的脚本:

     

    ----//调试脚本

    1. 设置断点。

      要设置断点,先选择一行命令,点击鼠标右键,在下拉菜单中选择“Toggle Breakpoint”命令,点击“运行”按钮,脚本会运行到断点处停止。用过myecilpse的debug功能来调试脚本的同学懂的!

    2. 通过页面源代码来调试脚本

      很多情况下,调试自动化测试案例都离不开查看页面源代码,我们可以借助firefox的firebug工具,关于firebug的安装(浏览器菜单栏---工具---查看组件---搜索firebug---安装并重启浏览器即可)。

    如:我们不确定或想获得谷歌搜索按钮的属性。在按钮上右击---查看元素

    在浏览器下方打开的firebug工具里面,就可以查看按钮代码了。

     

    3. 定位辅助

      当selenium IDE录制脚本时,它会存储额外的信息,支持用户挑选其他格式的定位器来代替默认格式的定位器,这种特殊性对于学习定位器很有用。

    我们可以选择其他的命令来代替“name=btnG” 命令,当然,脚本依然是可以运行的。

    posted @ 2012-08-09 14:18 奋斗成就男人 阅读(1425) | 评论 (0)编辑 收藏

    web安全测试---AppScan扫描工具

    安全测试应该是测试中非常重要的一部分,但他常常最容易被忽视掉。

      尽管国内经常出现各种安全事件,但没有真正的引起人们的注意。不管是开发还是测试都不太关注产品的安全。当然,这也不能怪我们苦B的“民工兄弟”。因为公司的所给我们的时间与精力只要求我们对产品的功能的实现以及保证功能的正常运行。一方面出于侥幸心理。谁没事会攻击我?

         关于安全测试方面的资料也很少,很多人所知道的就是一本书,一个工具。

      一本书值《web安全测试》,这应该是安全测试领域维数不多又被大家熟知的安全测试书,我曾看过前面几个章节,唉,鄙视一下自己,做事总喜欢虎头蛇尾。写得非常好,介绍了许多安全方面的工具和知识。我觉得就算你不去做专业的安全开发\测试人员。起码可以开阔你的视野,使你在做开发或测试时能够考虑到产品安全方面的设计。防患于未然总是好的,如果你想成为一个优秀的人。

      一个工具,其实本文也只是想介绍一下,这个工具----AappScan,IBM的这个web安全扫描工具被许多人熟知,相关资料也很多,因为我也摸了摸它的皮毛,所以也来人说两句,呵呵!说起sappScan,对它也颇有些感情,因为,上一份工作的时候,我摸过于测试相关的许多工具,AappScan是其它一个,当时就觉得这工具这么强大,而且还这么傻瓜!!^_^! 于是,后面在面试的简历上写了这个工具,应聘现在的这家公司,几轮面试下来都问到过这个工具,因为现在这家公司一直在使用这个工具做安全方面的扫描。我想能来这家公司和我熟悉AappScan应该有一点点的关系吧!呵呵

     

    AappScan下载与安装

     

    IBM官方下载;http://download2.boulder.ibm.com ... 2-AppScan_Setup.exe

        本连接为7.8 简体中文版本的

    破解补丁;http://www.vdisk.cn/down/index/4760606A4753

         破解补丁中有相应的注册机与破解步骤,生成注册码做一下替换就OK了,这里不细说。

      AppScan其实是一个产品家族,包括众多的应用安全扫描产品,从开发阶段的源代码扫描的AppScan source edition,到针对WEB应用进行快速扫描的AppScan standard edition.以及进行安全管理和汇总整合的AppScan enterprise Edition等,我们经常说的AppScan就是指的桌面版本的AppScan,AppScan standard edition.其安装在Windows操作系统上,可以对网站等WEB应用进行自动化的应用安全扫描和测试。

     

    使用AppScan来进行扫描

    我们按照PDCA的方法论来进行规划和讨论; 建议的AppScan使用步骤:PDCA: Plan,Do,check, Action and Analysis.

     

    计划阶段:明确目的,进行策略性的选择和任务分解。

    1)  明确目的:选择合适的扫描策略

    2)  了解对象:首先进行探索,了解网站结构和规模

    3)  确定策略:进行对应的配置

    a)   按照目录进行扫描任务的分解

    b)   按照扫描策略进行扫描任务的分解

     

    执行阶段:一边扫描一遍观察

    4)  进行扫描

    5)  先爬后扫(继续仅测试)

     

    检查阶段(Check)

    6)  检查和调整配置

     

    结果分析(Analysis)

    7)  对比结果

    8)  汇总结果(整合和过滤)

     

    AppScan的工作原理

      

      当我们单击“扫描”下面的小三角,可以出现如下的三个选型“继续完全扫描”,“继续仅探索”,“继续仅测试“,有木有?什么意思? 理解了这个地方,就理解了AppScan的工作原理,我们慢慢展开:

    还没有正式开始,所以先不管“继续“,直接来讨论’完全扫描”,“仅探索”,“仅测试”三个名词: 

      AppScan是对网站等WEB应用进行安全攻击,通过真刀真枪的攻击,来检查网站是否存在安全漏洞;既然是攻击,肯定要有明确的攻击对象吧,比如北约现在的对象就是卡扎菲上校还有他的军队。对网站来说,一个网站存在的页面,可能成千上万。每个页面也都可能存在多个字段(参数),比如一个登陆界面,至少要输入用户名和密码吧,这就是一个页面存在两个字段,你提交了用户名密码等登陆信息,网站总要有地方接受并且检查是否正确吧,这就可能存在一个新的检查页面。这里的每个页面的每个参数都可能存在安全漏洞,所有都是被攻击对象,都需要来检查。

      这就存在一个问题,你领命来检查一个网站的安全性,这个网站有多少个页面,有多少个参数,页面之间如何跳转,你可能很不明确,如何知道这些信息? 看起来很复杂,盘根错节;那就更需要找到那个线索,提纲挈领; 那就想一想,访问一个网站的时候,我们需要知道的最重要的信息是哪个?网站主页地址吧? 从网站地址开始,很多其他频道,其他页面都可以链接过去,对不对,那么可不可以有种技术,告诉了它网站的入口地址,然后它“顺藤摸瓜”,找出其他的网页和页面参数? OK,这就是”爬虫” 技术,具体说,是”网站爬虫“,其利用了网页的请求都是用http协议发送的,发送和返回的内容都是统一的语言HTML,那么对HTML语言进行分析,找到里面的参数和链接,纪录并继续发送之,最终,找到了这个网站的众多的页面和目录。这个能力AppScan就提供了,这里的术语叫“探索”,explorer,就是去发现,去分析,了解未知的,记录。

      在使用AppScan的时候,要配置的第一个就是要检查的网站的地址,配置了以后,AppScan就会利用“探索”技术去发现这个网站存在多少个目录,多少个页面,页面中有哪些参数等,简单说,了解了你的网站的结构。

      “探索”了解了,测试的目标和范围就大致确定了,然后呢,利用“军火库”,发送导弹,进行安全攻击,这个过程就是“测试”;针对发现的每个页面的每个参数,进行安全检查,检查的弹药就来自AppScan的扫描规则库,其类似杀毒软件的病毒库,具体可以检查的安全攻击类型都在里面做好了,我们去使用即可。

      那么什么是“完全测试呢”,完全测试就是把上面的两个步骤整合起来,“探索”+ “测试”;在安全测试过程中,可以先只进行探索,不进行测试,目的是了解被测的网站结构,评估范围; 然后选择“继续仅测试”,只对前面探索过的页面进行测试,不对新发现的页面进行测试。“完全测试”就是把两个步骤结合在一起,一边探索,一边测试。

    上图更容易理解:

    步骤1:探索(爬行,爬网)

    步骤2:真对找到的页面进行测试,生成安全攻击

     

    AppScan扫描大型网站

      经常有客户抱怨,说AppScan无法扫描大型的网站,或者是扫描接近完成时候无法保存,甚至保存后的结果文件下次无法打开?;同时大家又都很奇怪,作为一款业界出名的工具,如此的脆弱?是配置使用不当还是自己不太了解呢?我们今天就一起来讨论下AppScan扫描大型网站会遇到的问题以及应对。

      什么叫大型网站,顾名思义,网站规模大,具体说是页面很多,内容很全。比如www.sina.com.cn,比如http://music.10086.cn/,都包括上万个页面。而且除了这个,可能还有一个特点---页面参数多,即要填写的地方多,和用户的交互多;比如一个网站如果都是静态页面(.html,.jpg等),没有让用户输入的地方,那么可以利用,可以作为攻击点的地方也就不多。如果页面到处都是有输入,有查询,要求用户来参与的,你输入的越多,可能泄露的信息也越多,可能被别人利用的攻击点也就越多,所以和页面参数也是有关系的。AppScan声称测试用例的时候,也是根据每个参数来产生的,简单说,如果一个参数,对应了200个安全攻击测试用例,那么一个登陆界面至少就对应400个了,为什么?登陆界面至少有用户名和密码两个字段吧? 每个字段200个攻击用例。

     

    这个简单吧,还可以更复杂:如果遇到下面的两个地址,那要扫描多少次呢?

    http://www.cnblogs.com/fnng/focus/satisfy/file.jsp?id=1

    http://www.cnblogs.com/fnng/focus/satisfy/file.jsp?id=2

    上面的两个地址有类似的,“?”号以前的URL地址完全一样,”?”号后面带的参数不同,这种可以认为是重复页面,那么对于重复页面,是否要重复测试呢?

    这取决于“冗余路径设置”,默认的是最多测试5次;即,这种类型URL出现的前5次,那么就是要测试1000个攻击用例了。

     

    如果再继续修改下:遇到下面的URL呢

    http://www.cnblogs.com/fnng/focus/satisfy/file.jsp?id=1&Item=open

    http://www.cnblogs.com/fnng/focus/satisfy/file.jsp?id=2&Item=close

    每个URL里面都有2个参数,测试的次数就更多了。想象下,如果这个网页里面的参数如果是10个,或者更多的呢?比如很多网站提交注册信息的时候,要填写的内容足够多吧?

    要进行的安全测试用例也就随之不断增加…

     

      这是网站规模的影响,还有一个问题,就出在“每个参数,发送200个安全测试用例”这个假设上。这个假设的前提来源于哪里? 来源于我们选择的扫描规则库。即你关心那些安全威胁,这个需要在测试策略里面选择。同样来参照杀毒软件,你会用杀毒软件来查找一些专用的病毒吗,比如CIH,比如木马;应用安全扫描也是一样的道理,如果有明确的安全指标或者安全规则范围,那么就选择之。这些可能来源于企业的规范,来源于政府的法律法规。就要根据你的理解,在这里选择。

      很多时候,我们也很难在最开始的阶段,就把扫描规范制定下来,按照项目经理们的口头禅“渐进明细”,“滚动式规划”,在实践中,更多时候也是摸着石头过河,选择了一个扫描策略,然后根据结果分析,看是否需要调整,不断优化。比如选择默认的“缺省值扫描策略,对网站进行扫描,发现其”敏感信息“里面会去检查页面上是否含有Email地址,是否含有信用卡号码等,如果我们觉得这些信息,显示在页面上是正常的业务需要, 我们就可以取消掉这些规则,所以扫描规则也很大程度上影响着我们的扫描效率。

    posted @ 2012-08-09 14:16 奋斗成就男人 阅读(870) | 评论 (0)编辑 收藏

    使用JMeter创建数据库(Mysql)测试

    1.首先我们要有一个可以做测试的数据库,当然,里面要有数据,不然怎么测呢?我的上一篇文章《Eclipse连接MySQL数据库(傻瓜篇)》,里面教你如何通过程序批量插入数据。

    来看一下我的数据:

    我可能有点啰嗦 :)  不管你用什么方式,你的数据库里要有点数据。

    2.

    打开JMeter,点击测试计划,

    点击“浏览...”按钮,将你的JDBC驱动添加进来。

    3.

    添加一个线程组,

    右键点击“线程组”,在下面添加一个“JDBC Connection Configuration”

    来配置一下JDBC Connection Configuration页面。

    4.

    右键点击“线程组”,在下面添加一个“JDBC request”

    5.

    添加断言。

    右键点击线程组---->添加--->断言---->响应断言。

    6.

    我们来添加一些监听器来行查看

    添加一个断言结果:

    右键点击线程组---->添加--->监听器---->结果断言。

    添加一个图形结果:

    右键点击线程组---->添加--->监听器---->图形结果。

    添加一个查看结果树:

    右键点击线程组---->添加--->监听器---->查看结果树。

    下面是添加所有东东的列表:

    7.

    在线程组页面设置用户数、启动时间、循环次数

    点击菜单栏“运行”----“启动”

    下面是结果:

     

    其它的结果图片就不贴了。嘻嘻!!用图片说话,看上去简单,但比较长。。

    posted @ 2012-08-09 14:14 奋斗成就男人 阅读(185) | 评论 (0)编辑 收藏

    添加sql server约束

    ---添加主键约束
    alter table 表名
    add constraint 约束名 primary key (主键)
    ---添加唯一约束
    alter table 表名
    add constraint 约束名 unique (字段)
    ---添加默认约束
    alter table 表名
    add constraint 约束名 default ('默认内容') for 字段
    --添加检查check约束,要求字段只能在1到100之间
    alter table 表名
    add constraint 约束名 check (字段 between 1 and 100 )
    ---添加外键约束(主表stuInfo和从表stuMarks建立关系,关联字段为stuNo)
    alter table 从表
    add constraint 约束名
    foreign key(关联字段) references 主表(关联字段)
    GO
    sql server中删除约束的语句是:
    alter table 表名 drop constraint 约束名
    sp_helpconstraint 表名 找到数据表中的所有列的约束

    -----------在创建表时创建约束------------
    7.2.1 主关键字约束
    主关键字约束指定表的一列或几列的组合的值在表中具有惟一性,即能惟一地指定一行记录。每个表中只能有一列被指定为主关键字,且IMAGE 和TEXT 类型的列不能被指定为主关键字,也不允许指定主关键字列有NULL 属性。
    定义主关键字约束的语法如下:
    CONSTRAINT constraint_name
    PRIMARY KEY [CLUSTERED | NONCLUSTERED]
    (column_name1[, column_name2,…,column_name16])
    各参数说明如下:


    constraint_name
    指定约束的名称约束的名称。在数据库中应是惟一的。如果不指定,则系统会自动生成一个约束名。
    CLUSTERED | NONCLUSTERED
    指定索引类别,CLUSTERED 为缺省值。其具体信息请参见下一章。
    column_name
    指定组成主关键字的列名。主关键字最多由16 个列组成。

    例7-3: 创建一个产品信息表,以产品编号和名称为主关键字
    create table products (
    p_id char(8) not null,
    p_name char(10) not null ,
    price money default 0.01 ,
    quantity smallint null ,
    constraint pk_p_id primary key (p_id, p_name)
    ) on [primary]

    7.2.2 外关键字约束
    外关键字约束定义了表之间的关系。当一个表中的一个列或多个列的组合和其它表中的主关键字定义相同时,就可以将这些列或列的组合定义为外关键字,并设定它适合哪个表中哪些列相关联。这样,当在定义主关键字约束的表中更新列值,时其它表中有与之相关联的外关键字约束的表中的外关键字列也将被相应地做相同的更新。外关键字约束的作用还体现在,当向含有外关键字的表插入数据时,如果与之相关联的表的列中无与插入的外关键字列值相同的值时,系统会拒绝插入数据。与主关键字相同,不能使用一个定义为 TEXT 或IMAGE 数据类型的列创建外关键字。外关键字最多由16 个列组成。
    定义外关键字约束的语法如下:
    CONSTRAINT constraint_name
    FOREIGN KEY (column_name1[, column_name2,…,column_name16])
    REFERENCES ref_table [ (ref_column1[,ref_column2,…, ref_column16] )]
    [ ON DELETE { CASCADE | NO ACTION } ]
    [ ON UPDATE { CASCADE | NO ACTION } ] ]
    [ NOT FOR REPLICATION ]
    各参数说明如下:

    REFERENCES
    指定要建立关联的表的信息。
    ref_table
    指定要建立关联的表的名称。
    ref_column
    指定要建立关联的表中的相关列的名称。
    ON DELETE {CASCADE | NO ACTION}
    指定在删除表中数据时,对关联表所做的相关操作。在子表中有数据行与父表中的对应数据行相关联的情况下,如果指定了值CASCADE,则在删除父表数据行时会将子表中对应的数据行删除;如果指定的是NO ACTION,则SQL Server 会产生一个错误,并将父表中的删除操作回滚。NO ACTION 是缺省值。
    ON UPDATE {CASCADE | NO ACTION}
    指定在更新表中数据时,对关联表所做的相关操作。在子表中有数据行与父表中的对应数据行相关联的情况下,如果指定了值CASCADE,则在更新父表数据行时会将子表中对应的数据行更新;如果指定的是NO ACTION,则SQL Server 会产生一个错误,并将父表中的更新操作回滚。NO ACTION 是缺省值。
    NOT FOR REPLICATION
    指定列的外关键字约束在把从其它表中复制的数据插入到表中时不发生作用。
    例7-4:创建一个订货表,与前面创建的产品表相关联
    create table   orders(
    order_id char(8),
    p_id char(8),
    p_name char(10) ,
    constraint pk_order_id primary key (order_id) ,
    foreign key(p_id, p_name) references products(p_id, p_name)
    ) on [primary]
    注意:临时表不能指定外关键字约束。
    7.2.3 惟一性约束
    惟一性约束指定一个或多个列的组合的值具有惟一性,以防止在列中输入重复的值。惟一性约束指定的列可以有NULL 属性。由于主关键字值是具有惟一性的,因此主关键字列不能再设定惟一性约束。惟一性约束最多由16 个列组成。
    定义惟一性约束的语法如下:
    CONSTRAINT constraint_name
    UNIQUE [CLUSTERED | NONCLUSTERED]
    (column_name1[, column_name2,…,column_name16])

    例7-5:定义一个员工信息表,其中员工的身份证号具有惟一性。

    create table employees (
    emp_id char(8),
    emp_name char(10) ,
    emp_cardid char(18),
    constraint pk_emp_id primary key (emp_id),
    constraint uk_emp_cardid unique (emp_cardid)
    ) on [primary]

    7.2.4 检查约束
    检查约束对输入列或整个表中的值设置检查条件,以限制输入值,保证数据库的数据完整性。可以对每个列设置符合检查。
    定义检查约束的语法如下:
    CONSTRAINT constraint_name
    CHECK [NOT FOR REPLICATION]
    (logical_expression)
    各参数说明如下:
    NOT FOR REPLICATION
    指定检查约束在把从其它表中复制的数据插入到表中时不发生作用。
    logical_expression
    指定逻辑条件表达式返回值为TRUE 或FALSE。
    例7-6: 创建一个订货表其中定货量必须不小于10。
    create table   orders(
    order_id char(8),
    p_id char(8),
    p_name char(10) ,
    quantity smallint,
    constraint pk_order_id primary key (order_id),
    constraint chk_quantity check (quantity>=10) ,
    ) on [primary]
    注意:对计算列不能作除检查约束外的任何约束。

    7.2.5 缺省约束
    缺省约束通过定义列的缺省值或使用数据库的缺省值对象绑定表的列,来指定列的缺省值。SQL Server 推荐使用缺省约束,而不使用定义缺省值的方式来指定列的缺省值。有关绑定缺省约束的方法请参见“数据完整性”章节。
    定义缺省约束的语法如下:
    CONSTRAINT constraint_name
    DEFAULT constant_expression [FOR column_name]
    例7-7:
    constraint de_order_quantity default 100 for   order_quantity
    注意:不能在创建表时定义缺省约束,只能向已经创建好的表中添加缺省约束。


    7.2.6 列约束和表约束
    对于数据库来说,约束又分为列约束(Column Constraint)和表约束(Table Constraint)。
    列约束作为列定义的一部分只作用于此列本身。表约束作为表定义的一部分,可以作用于
    多个列。
    下面举例说明列约束与表约束的区别。
    例7-8:
    create table products (
    p_id char(8) ,
    p_name char(10) ,
    price money default 0.01 ,
    quantity smallint check (quantity>=10) , /* 列约束 */
    constraint pk_p_id primary key (p_id, p_name) /* 表约束 */

    posted @ 2012-08-08 11:02 奋斗成就男人 阅读(782) | 评论 (0)编辑 收藏

    sql server中利用sql语句如何创建角色和用户

    /*--示例说明
            示例在数据库pubs中创建一个拥有表jobs的所有权限、拥有表titles的SELECT权限的角色r_test
        随后创建了一个登录l_test,然后在数据库pubs中为登录l_test创建了用户账户u_test
        同时将用户账户u_test添加到角色r_test中,使其通过权限继承获取了与角色r_test一样的权限
        最后使用DENY语句拒绝了用户账户u_test对表titles的SELECT权限。
        经过这样的处理,使用l_test登录SQL Server实例后,它只具有表jobs的所有权限。
    --
    */

    USE pubs

    --创建角色 r_test
    EXEC sp_addrole 'r_test'

    --授予 r_test 对 jobs 表的所有权限
    GRANT ALL ON jobs TO r_test
    --授予角色 r_test 对 titles 表的 SELECT 权限
    GRANT SELECT ON titles TO r_test

    --添加登录 l_test,设置密码为pwd,默认数据库为pubs
    EXEC sp_addlogin 'l_test','pwd','pubs'

    --为登录 l_test 在数据库 pubs 中添加安全账户 u_test
    EXEC sp_grantdbaccess 'l_test','u_test'

    --添加 u_test 为角色 r_test 的成员
    EXEC sp_addrolemember 'r_test','u_test'

    --拒绝安全账户 u_test 对 titles 表的 SELECT 权限
    DENY SELECT ON titles TO u_test

    /*--完成上述步骤后,用 l_test 登录,可以对jobs表进行所有操作,但无法对titles表查询,虽然角色 r_test 有titles表的select权限,但已经在安全账户中明确拒绝了对titles的select权限,所以l_test无titles表的select权限--*/

    --从数据库 pubs 中删除安全账户
    EXEC sp_revokedbaccess 'u_test'

    --删除登录 l_test
    EXEC sp_droplogin 'l_test'

    --删除角色 r_test
    EXEC sp_droprole 'r_test'
    SQL code
    --1. 创建示例环境。 首先使用下面的代码创建一个登录l_test,并且为登录在数据库pubs中创建关联的用户账户u_test,并且授予用户账户u_test对表titles的SELECT权限,用以实现登录l_test连接到SQL Server实例后,可以访问表titles。然后创建了一个应用程序角色r_p_test,授予该角色对表jobs的SELECT权限,用以实现激活r_p_test时,允许访问特定的表jobs。 USE pubs --创建一个登录 l_test, 密码 pwd, 默认数据库 pubs EXEC sp_addlogin 'l_test','pwd','pubs' --为登录 l_test 在数据库 pubs 中添加安全账户 u_test EXEC sp_grantdbaccess 'l_test','u_test' --授予安全账户 u_test 对 titles 表的 SELECT 权限 GRANT SELECT ON titles TO u_test --创建一个应用程序角色 r_p_test, 密码 abc EXEC sp_addapprole 'r_p_test','abc' --授予角色 r_p_test 对 jobs 表的 SELECT 权限 GRANT SELECT ON jobs TO r_p_test GO --2. 激活应用程序角色。 /*--激活说明 示例环境创建完成后,在任何地方(比如查询分析器、应用程序) 使用登录l_test连接SQL Server实例,均只能访问表titles,或者是guest用户 和public角色允许访问的对象。 如果要在某些特定的应用程序中,允许登录访问表jobs,那么, 可以激活应用程序角色r_p_test,激活应用程序角色后,登录本身的权限会消失。 下面在查询分析器中登录,演示激活应用程序角色r_p_test前后对数据访问的区别。 --*/ --激活应用程序角色 r_p_test 前,登录具有表 titles 的访问权,但无表 jobs 的访问权 SELECT titles_count=COUNT(*) FROM titles SELECT jobs_count=COUNT(*) FROM jobs /*--结果: titles_count ------------ 18 (所影响的行数为 1 行) 服务器: 消息 229,级别 14,状态 5,行 2 拒绝了对对象 'jobs'(数据库 'pubs',所有者 'dbo')的 SELECT 权限。 --*/ GO --用密码 abc 激活 r_p_test 应用程序角色,并且在将此密码发送到SQL Server之前对其加密 EXEC sp_setapprole 'r_p_test',{Encrypt N'abc'},'ODBC' GO --激活应用程序角色 r_p_test 后,登录失去表 titles 的访问权,获取表 jobs 的访问权 SELECT titles_count=COUNT(*) FROM titles SELECT jobs_count=COUNT(*) FROM jobs /*--结果 服务器: 消息 229,级别 14,状态 5,行 2 拒绝了对对象 'titles'(数据库 'pubs',所有者 'dbo')的 SELECT 权限。 jobs_count ----------- 14 (所影响的行数为 1 行) --*/
    SQL code
    exec sp_dropsrvrolemember N'aa', sysadmin go exec sp_addsrvrolemember N'aa', securityadmin go --作好SQL的安全管理 --作者:邹建 首先,做好用户安全: --简单的,只允许sql的用户访问sql(防止利用administrator组用户访问) 1.企业管理器--右键SQL实例--属性--安全性--身份验证--选择"sql server和windows"--确定 2.企业管理器--安全性--登陆--右键sa--设置密码--其他用户也设置密码 3.删除用户: BUILTIN\Administrators <机器名>\Administrator --这个用户不一定有 这样可以防止用windows身份登陆SQL 4.设置进入企业管理器需要输入密码 在企业管理器中 --右键你的服务器实例(就是那个有绿色图标的) --编辑SQL Server注册属性 --选择"使用 SQL Server 身份验证" --并勾选"总是提示输入登录名和密码" --确定 --经过上面的设置,你的SQL Server基本上算是安全了. ------------------------------------------------------------------------ 其次,改默认端口,隐藏服务器,减少被攻击的可能性 SQL Server服务器 --开始 --程序 --Microsoft SQL Server --服务器网络实用工具 --启用的协议中"TCP/IP" --属性 --默认端口,输入一个自已定义的端口,比如2433 --勾选隐藏服务器 ---------------------------------------------------------------------------- --管好sql的用户,防止访问他不该访问的数据库(总控制,明细还可以控制他对于某个数据库的具体对象具有的权限) --切换到你新增的用户要控制的数据库 use 你的库名 go --新增用户 exec sp_addlogin 'test' --添加登录 exec sp_grantdbaccess N'test' --使其成为当前数据库的合法用户 exec sp_addrolemember N'db_owner', N'test' --授予对自己数据库的所有权限 --这样创建的用户就只能访问自己的数据库,及数据库中包含了guest用户的公共表 go --删除测试用户 exec sp_revokedbaccess N'test' --移除对数据库的访问权限 exec sp_droplogin N'test' --删除登录 如果在企业管理器中创建的话,就用: 企业管理器--安全性--右键登录--新建登录 常规项 --名称中输入用户名 --身份验证方式根据你的需要选择(如果是使用windows身份验证,则要先在操作系统的用户中新建用户) --默认设置中,选择你新建的用户要访问的数据库名 服务器角色项 这个里面不要选择任何东西 数据库访问项 勾选你创建的用户需要访问的数据库名 数据库角色中允许,勾选"public","db_ownew" 确定,这样建好的用户与上面语句建立的用户一样 --------------------------------------------------------------------------- 最后一步,为具体的用户设置具体的访问权限,这个可以参考下面的最简示例: --添加只允许访问指定表的用户: exec sp_addlogin '用户名','密码','默认数据库名' --添加到数据库 exec sp_grantdbaccess '用户名' --分配整表权限 GRANT SELECT , INSERT , UPDATE , DELETE ON table1 TO [用户名] --分配权限到具体的列 GRANT SELECT , UPDATE ON table1(id,AA) TO [用户名] ------------------------------------------------------------------- 至于具体的安全设置和理论知道,参考SQL联机帮助
    SQL code
    /*--创建一个只允许特定程序使用的数据库用户 创建一个用户,这个用户只有用我们特定的应用程序登录 才具有访问数据库的权限,用其他工具登录没有任何权限 在下面的示例中,演示了如何控制登录l_test 使其登录后只允许访问pubs数据库的titles表 而对jobs表的访问权限,只允许在某些许可的应用程序中访问。 --邹建 2004.09(引用请保留此信息)--*/ --创建测试环境 USE pubs --创建一个登录 l_test, 密码 pwd, 默认数据库 pubs EXEC sp_addlogin 'l_test','pwd','pubs' --为登录 l_test 在数据库 pubs 中添加安全帐户 u_test EXEC sp_grantdbaccess 'l_test','u_test' --授予安全帐户 u_test 对 titles 表的 SELECT 权限 GRANT SELECT ON titles TO u_test --创建一个应用程序角色 r_p_test, 密码 abc EXEC sp_addapprole 'r_p_test','abc' --授予角色 r_p_test 对 jobs 表的 SELECT 权限 GRANT SELECT ON jobs TO r_p_test GO --创建好上面的测试后,现在来测试如何使用应用程序角色 --我们把用户及密码告诉使用者,即告诉使用者,用户是: l_test,密码是: pwd --使用者可以用我们这个用户在任何地方登录,包含查询分析器 --但是,用户只能访问 titles 表,不能访问其他对象,如果建立用户时不授予它任何权限,则它不访问除guest用户和public角色允许访问外的任何对象 --OK,到这里,我们是把用户控制住了 --下面我们再来说在程序中的处理,因为用户在程序中登录后,需要对jobs表有访问权限的 --我们只需要在用户登录后,执行一句 EXEC sp_setapprole 'r_p_test',{Encrypt N'abc'},'ODBC' --这样,我们登录的用户就转变为 r_p_test 角色的权限,而它自身的权限丢失 --只要这个用户不退出应用程序,他的权限就会保持 --如果用户退出了当前应用程序,则他的权限自动收回 --同时,这个用户即使没有退出应用程序,他也是只在我们的应用程序中有权限,在其他地方登录,也不会有权限 --因为这个密码我们是不用给用户的,所以,用户没有这个角色的密码,也就限制了他只能在程序中使用我们的数据 --激活应用程序角色 r_p_test 前,登录具有表 titles 的访问权,但无表 jobs 的访问权 SELECT titles_count=COUNT(*) FROM titles SELECT jobs_count=COUNT(*) FROM jobs /*--结果: titles_count ------------ 18 (所影响的行数为 1 行) 服务器: 消息 229,级别 14,状态 5,行 2 拒绝了对对象 'jobs'(数据库 'pubs',所有者 'dbo')的 SELECT 权限。 --*/ GO --用密码 abc 激活 r_p_test 应用程序角色,并且在将此密码发送到SQL Server之前对其加密 EXEC sp_setapprole 'r_p_test',{Encrypt N'abc'},'ODBC' GO --激活应用程序角色 r_p_test 后,登录失去表 titles 的访问权,获取表 jobs 的访问权 SELECT titles_count=COUNT(*) FROM titles SELECT jobs_count=COUNT(*) FROM jobs /*--结果 服务器: 消息 229,级别 14,状态 5,行 2 拒绝了对对象 'titles'(数据库 'pubs',所有者 'dbo')的 SELECT 权限。 jobs_count ----------- 14 (所影响的行数为 1 行) --*/ go --删除测试 EXEC sp_dropapprole 'r_p_test' EXEC sp_revokedbaccess 'u_test' EXEC sp_droplogin 'l_test'

    posted @ 2012-08-08 10:47 奋斗成就男人 阅读(3428) | 评论 (0)编辑 收藏

    PHP高效率写法(详解原因)

    1.尽量静态化:

       如果一个方法能被静态,那就声明它为静态的,速度可提高1/4,甚至我测试的时候,这个提高了近三倍。
       当然了,这个测试方法需要在十万级以上次执行,效果才明显。
       其实静态方法和非静态方法的效率主要区别在内存:静态方法在程序开始时生成内存,实例方法在程序运行中生成内存,所以静态方法可以直接调用,实例方法要先成生实例,通过实例调用方法,静态速度很快,但是多了会占内存。
      任何语言都是对内存和磁盘的操作,至于是否面向对象,只是软件层的问题,底层都是一样的,只是实现方法不同。静态内存是连续的,因为是在程序开始时就生成了,而实例申请的是离散的空间,所以当然没有静态方法快。
       静态方法始终调用同一块内存,其缺点就是不能自动进行销毁,而是实例化可以销毁。

    2.echo的效率高于print,因为echo没有返回值,print返回一个整型;

      测试:
      Echo
      0.000929 - 0.001255 s (平均 0.001092 seconds)
      Print
      0.000980 - 0.001396 seconds (平均 0.001188 seconds)
      相差8%左右,总体上echo是比较快的。
      注意,echo大字符串的时候,如果没有做调整就严重影响性能。使用打开apached的mod_deflate进行压缩或者打开ob_start先将内容放进缓冲区。

    3.在循环之前设置循环的最大次数,而非在在循环中;

        傻子都明白的道理。

    4.销毁变量去释放内存,特别是大的数组;

      数组和对象在php特别占内存的,这个由于php的底层的zend引擎引起的,
      一般来说,PHP数组的内存利用率只有 1/10, 也就是说,一个在C语言里面100M 内存的数组,在PHP里面就要1G。
      特别是在PHP作为后台服务器的系统中,经常会出现内存耗费太大的问题。

    5.避免使用像__get, __set, __autoload等魔术方法;

      对于__开头的函数就命名为魔术函数,此类函数都在特定的条件下初访的。总得来说,有下面几个魔术函数
      __construct(),__destruct(),__get(),__set(),__unset(),__call(),__callStatic(),__sleep(),__wakeup(),__toString(),__set_state(),__clone(),__autoload()

         其实,如果__autoload不能高效的将类名与实际的磁盘文件(注意,这里指实际的磁盘文件,而不仅仅是文件名)对应起来,系统将不得不做大量的文件是 否存在(需要在每个include path中包含的路径中去寻找)的判断,而判断文件是否存在需要做磁盘I/O操作,众所周知磁盘I/O操作的效率很低,因此这才是使得autoload机制效率降低的原因。

      因此,我们在系统设计时,需要定义一套清晰的将类名与实际磁盘文件映射的机制。这个规则越简单越明确,autoload机制的效率就越高。
      结论:autoload机制并不是天然的效率低下,只有滥用autoload,设计不好的自动装载函数才会导致其效率的降低.

      所以说尽量避免使用__autoload魔术方法,有待商榷。

    6.requiere_once()比较耗资源;

      这是因为requiere_once需要判断该文件是否被引用过),所以能不用尽量不用。常用require/include方法避免。

    7.在includes和requires中使用绝对路径。

      如果包含相对路径,PHP会在include_path里面遍历查找文件。
      用绝对路径就会避免此类问题,因此解析操作系统路径所需的时间会更少。

    8.如果你需要得到脚本执行时的时间,$_SERVER['REQUSET_TIME']优于time();

      可以想象。一个是现成就可以直接用,一个还需要函数得出的结果。

    9.能用PHP内部字符串操作函数的情况下,尽量用他们,不要用正则表达式; 因为其效率高于正则;

     没得说,正则最耗性能。
     有没有你漏掉的好用的函数?例如:strpbrk()strncasecmp()strpos()/strrpos()/stripos()/strripos()加速 strtr如果需要转换的全是单个字符的时候,
    用字符串而不是数组来做 strtr:
    <?php
    $addr = strtr($addr, "abcd", "efgh"); // good
    $addr = strtr($addr, array('a' => 'e', )); // bad
    ?>
    效率提升:10 倍。

    10.str_replace字符替换比正则替换preg_replace快,但strtr比str_replace又快1/4;

      另外不要做无谓的替换即使没有替换,str_replace 也会为其参数分配内存。很慢!解决办法:
      用 strpos 先查找(非常快),看是否需要替换,如果需要,再替换效率:- 如果需要替换:效率几乎相等,差别在 0.1% 左右。
      如果不需要替换:用 strpos 快 200%。

    11.参数为字符串

      如果一个函数既能接受数组又能接受简单字符做为参数,例如字符替换函数,并且参数列表不是太长,可以考虑额外写一段替换代码,使得每次传递参数都是一   个字符,而不是接受数组做为查找和替换参数。大事化小,1+1>2;

    12.最好不用@,用@掩盖错误会降低脚本运行速度;

       用@实际上后台有很多操作。用@比起不用@,效率差距:3 倍。特别不要在循环中使用@,在 5 次循环的测试中,即使是先用 error_reporting(0) 关掉错误,在循环完成后再打开,都比用@快。

    13.$row['id']比$row[id]速度快7倍

        建议养成数组键加引号的习惯;

    14.在循环里别用函数

       例如For($x=0; $x < count($array); $x), count()函数在外面先计算;原因你懂的。

    16.在类的方法里建立局部变量速度最快,几乎和在方法里调用局部变量一样快;

    17.建立一个全局变量要比局部变量要慢2倍;

      由于局部变量是存在栈中的,当一个函数占用的栈空间不是很大的时候,这部分内存很有可能全部命中cache,这时候CPU访问的效率是很高的。
      相反,如果一个函数里既使用了全局变量又使用了局部变量,那么当这两段地址相差较大时,cpu cache需要来回切换,那么效率会下降。
      (我理解啊)

    18.建立一个对象属性(类里面的变量)例如($this->prop++)比局部变量要慢3倍;

    19.建立一个未声明的局部变量要比一个已经定义过的局部变量慢9-10倍

    20.声明一个未被任何一个函数使用过的全局变量也会使性能降低(和声明相同数量的局部变量一样)。

        PHP可能去检查这个全局变量是否存在;

    21.方法的性能和在一个类里面定义的方法的数目没有关系

      因为我添加10个或多个方法到测试的类里面(这些方法在测试方法的前后)后性能没什么差异;

    22.在子类里方法的性能优于在基类中;

    23.只调用一个参数并且函数体为空的函数运行花费的时间等于7-8次$localvar++运算,而一个类似的方法(类里的函数)运行等于大约15次$localvar++运算;

    24 用单引号代替双引号来包含字符串,这样做会更快一些。

       因为PHP会在双引号包围的字符串中搜寻变量,单引号则不会。

       PHP 引擎允许使用单引号和双引号来封装字符串变量,但是这个是有很大的差别的!使用双引号的字符串告诉 PHP 引擎首先去读取字符串内容,查找其中的变    量,并改为变量对应的值。一般来说字符串是没有变量的,所以使用双引号会导致性能不佳。最好是使用字
      符串连接而不是双引号字符串。
    BAD:
    $output = "This is a plain string";
    GOOD:
    $output = 'This is a plain string';
    BAD: 
    $type = "mixed";
    $output = "This is a $type string";
    GOOD:
    $type = 'mixed';
    $output = 'This is a ' . $type .' string';

    25.当echo字符串时用逗号代替点连接符更快些。

      echo一种可以把多个字符串当作参数的“函数”(译注:PHP手册中说echo是语言结构,不是真正的函数,故把函数加上了双引号)。

      例如echo $str1,$str2。

    26.Apache解析一个PHP脚本的时间要比解析一个静态HTML页面慢2至10倍。

         尽量多用静态HTML页面,少用脚本。

    28.尽量使用缓存,建议用memcached。

       高性能的分布式内存对象缓存系统,提高动态网络应用程序性能,减轻数据库的负担;

       也对运算码 (OP code)的缓存很有用,使得脚本不必为每个请求做重新编译。

    29.使用ip2long()和long2ip()函数把IP地址转成整型存放进数据库而非字符型。

         这几乎能降低1/4的存储空间。同时可以很容易对地址进行排序和快速查找;

    30.使用checkdnsrr()通过域名存在性来确认部分email地址的有效性

        这个内置函数能保证每一个的域名对应一个IP地址;

    31.使用mysql_*的改良函数mysqli_*;

    32.试着喜欢使用三元运算符(?:);

    33.是否需要PEAR

    在你想在彻底重做你的项目前,看看PEAR有没有你需要的。PEAR是个巨大的资源库,很多php开发者都知道;


    35.使用error_reporting(0)函数来预防潜在的敏感信息显示给用户。

      理想的错误报告应该被完全禁用在php.ini文件里。可是如果你在用一个共享的虚拟主机,php.ini你不能修改,那么你最好添加error_reporting(0)函数,放在每个脚本文件的第一行(或用

    require_once()来加载)这能有效的保护敏感的SQL查询和路径在出错时不被显示;

    36.使用 gzcompress() 和gzuncompress()对容量大的字符串进行压缩(解压)在存进(取出)数据库时。

        这种内置的函数使用gzip算法能压缩到90%;

    37.通过参数变量地址得引用来使一个函数有多个返回值。

       你可以在变量前加个“&”来表示按地址传递而非按值传递;

    38. 完全理解魔术引用和SQL注入的危险。

        Fully understand “magic quotes” and the dangers of SQL injection. I’m hoping that most developers reading this are already familiar with SQL injection. However, I list it here because it’s absolutely critical to understand. If you’ve never heard the term before, spend the entire rest of the day googling and reading.

    39.某些地方使用isset代替strlen

      当操作字符串并需要检验其长度是否满足某种要求时,你想当然地会使用strlen()函数。此函数执行起来相当快,因为它不做任何计算,只返回在zval 结构(C的内置数据结构,用于存储PHP变量)中存储的已知字符串长度。但是,由于strlen()是函数,多多少少会有些慢,因为函数调用会经过诸多步骤,如字母小写化(译注:指函数名小写化,PHP不区分函数名大小写)、哈希查找,会跟随被调用的函数一起执行。在某些情况下,你可以使用isset() 技巧加速执行你的代码。

    (举例如下)
    if (strlen($foo) < 5) { echo “Foo is too short”$$ }
    (与下面的技巧做比较)
    if (!isset($foo{5})) { echo “Foo is too short”$$ }
    调用isset()恰巧比strlen()快,因为与后者不同的是,isset()作为一种语言结构,意味着它的执行不需要函数查找和字母小写化。也就是说,实际上在检验字符串长度的顶层代码中你没有花太多开销。

    40.使用++$i递增

    When incrementing or decrementing the value of the variable $i++ happens to be a tad slower then ++$i. This is something PHP specific and does not apply to other languages, so don’t go modifying your C or Java code thinking it’ll suddenly become faster, it won’t. ++$i happens to be faster in PHP because instead of 4 opcodes used for $i++ you only need 3. Post incrementation actually causes in the creation of a temporary var that is then incremented. While preincrementation increases the original value directly. This is one of the optimization that opcode optimized like Zend’s PHP optimizer. It is a still a good idea to keep in mind since not all opcode optimizers perform this optimization and there are plenty of ISPs and servers running without an opcode optimizer.

       当执行变量$i的递增或递减时,$i++会比++$i慢一些。这种差异是PHP特有的,并不适用于其他语言,所以请不要修改你的C或Java代码并指望它们能立即变快,没用的。++$i更快是因为它只需要3条指令(opcodes),$i++则需要4条指令。后置递增实际上会产生一个临时变量,这个临时变量随后被递增。而前置递增直接在原值上递增。这是最优化处理的一种,正如Zend的PHP优化器所作的那样。牢记这个优化处理不失为一个好主意,因为并不是所有的指令优化器都会做同样的优化处理,并且存在大量没有装配指令优化器的互联网服务
    提供商(ISPs)和服务器。

    40. 不要随便就复制变量

    有时候为了使 PHP 代码更加整洁,一些 PHP 新手(包括我)会把预定义好的变量复制到一个名字更简短的变量中,其实这样做的结果是增加了一倍的内存消耗,只会使程序更加慢。试想一下,在下面的例子中,如果用户恶意插入 512KB 字节的文字到文本输入框中,这样就会导致 1MB 的内存被消耗!
    BAD:
    $description = $_POST['description'];
    echo $description;
    GOOD:
    echo $_POST['description'];

    41 使用选择分支语句

         switch case好于使用多个if,else if语句,并且代码更加容易阅读和维护。

    42.在可以用file_get_contents替代file、fopen、feof、fgets

        在可以用file_get_contents替代file、fopen、feof、fgets等系列方法的情况下,尽量用 file_get_contents,因为他的效率高得多!但是要注意file_get_contents在打开一个URL文件时候的PHP版本问题;

    43.尽量的少进行文件操作,虽然PHP的文件操作效率也不低的;

    44.优化Select SQL语句,在可能的情况下尽量少的进行Insert、Update操作(在update上,我被恶批过);

    45.尽可能的使用PHP内部函数

    46.循环内部不要声明变量,尤其是大变量:对象

       (这好像不只是PHP里面要注意的问题吧?);

    47.多维数组尽量不要循环嵌套赋值;

    48.foreach效率更高,尽量用foreach代替while和for循环;

    49.“用i+=1代替i=i+1。符合c/c++的习惯,效率还高”;

    50.对global变量,应该用完就unset()掉;

    51 并不是事必面向对象(OOP),面向对象往往开销很大,每个方法和对象调用都会消耗很多内存。

    52 不要把方法细分得过多,仔细想想你真正打算重用的是哪些代码?

    53 如果在代码中存在大量耗时的函数,你可以考虑用C扩展的方式实现它们。

    54、打开apache的mod_deflate模块,可以提高网页的浏览速度。

       (提到过echo 大变量的问题)

    55、数据库连接当使用完毕时应关掉,不要用长连接。

    56、split比exploade快

    posted @ 2012-08-04 12:25 奋斗成就男人 阅读(297) | 评论 (0)编辑 收藏

    java程序员必知的8大排序

         摘要: 8种排序之间的关系:   1, 直接插入排序    (1)基本思想:在要排序的一组数中,假设前面(n-1)[n>=2] 个数已经是排 好顺序的,现在要把第n个数插到前面的有序数中,使得这n个数 也是排好顺序的。如此反复循环,直到全部排好顺序。  (2)实例 (3)用java实现 01 ...  阅读全文

    posted @ 2012-08-04 12:24 奋斗成就男人 阅读(161) | 评论 (0)编辑 收藏

    301跳转详细说明

        
        说明:A网站--->B网站--->C网站--->D网站,其中A为提交网站,可以通过get或者post表单传值,然后在B网站做301跳转,跳转到C网站。然后在从C网站跳转到网关D。

        具体代码实现步骤如下:
       (1):A网站:只是一个简单的form表单提交:
            <form action="B网站地址" id="pay" mothod="post">
                <input type="hidden" value="abc" name="param">
                <input type="submit"/>
           </form>

      (2):B网站:首先在B网站目录中写一个重写文件.htaccess。具体如下:
                RewriteEngine On         //开始重写引擎
                // .htaccess放到B网站/test2/目录下,表示该301跳转只在/test2/起作用,其他的目录则不起作用。
                RewriteBase /test2/                         
                // http://192.168.5.17:8090/test2/index.php 为B网站目录地址
                RewriteCond %{HTTP_HOST} !http://192.168.5.17:8090/test2/index.php [NC] 
                // http://192.168.5.17:8080/servlet01/dispatcher.jsp 为C网站地址
                RewriteRule ^(.*)$ http://192.168.5.17:8080/servlet01/dispatcher.jsp [L,R=301]      
      
      (3):C网站:首先获取A网站提交的参数:
                String param = request.getParameter("param");
                然后再组装form表单:
                    <form action="D网站地址" id="pay" mothod="post">
                         <input type="hidden" value="<%=param %>" name="TradeInfo">
                         <input type="submit"/>
                    </form>
        (4): D网站:获取从C网站提交过来的参数。

        重点:做了301跳转后,从C网站中可以获取到A提交过来的参数,而且C网站获取的来源网站居然是A网站,而不是B网站地址。经过测试发现:在B网站301跳转时,已经把从A网站提交的参数,组装成get方式提交方式(而不管你在A采用的是post还是get提交方式),
    即:<a href="http://192.168.5.17:8080/servlet01/dispatcher.jsp?param=123456789">here</a> 然后会自动跳转到C网站。


             

    posted @ 2012-08-03 18:17 奋斗成就男人 阅读(627) | 评论 (0)编辑 收藏

    MYSQL数据库导入导出

    导入:mysql -h hostname -u root -p databasename<test.sql
    导出:mysqldump -h hostname  -u root -p databasename>test.sql

    其中 -u root 表示用户名

       -p tian  表示密码

        test    表示数据库名(已存在的)

        test.sql  表示外部的脚本文件(文件名字、格式随便,例如:a.sql,a.abc......)
    注意:-p后面不用填写密码,密码再执行了上面的语句后再输入

    posted @ 2012-08-01 18:42 奋斗成就男人 阅读(105) | 评论 (0)编辑 收藏

    java中的日期和sql中的日期转换以及java.util.Date, java.util.Calendar, java.sql.Date, java.sql.Time, java.sql.Timestamp区别和联系

    将"yyyy-mm-dd"格式的字符串转换为java.sql.Date:

    SimpleDateFormat bartDateFormat =   new SimpleDateFormat("yyyy-MM-dd");  
    String dateStringToParse = "2007-7-12";  
    try{  
           java.util.Date date = bartDateFormat.parse(dateStringToParse);  
           java.sql.Date sqlDate = new java.sql.Date(date.getTime());
           System.out.println(sqlDate.getTime());  
     
    catch (Exception ex) {  
         System.out.println(ex.getMessage());  
    }

     

    java.util.Date, java.util.Calendar, java.sql.Date, java.sql.Time, java.sql.Timestamp区别和联系:

     

    在java有关的项目开发工作中,我们常常要java.util.Date,  java.util.Calendar,   java.sql.Date,    java.sql.Time,   java.sql.Timestamp等几个类进行日期的处理和分析,那么这几个函数之间有什么样的联系,它们又有什么区别呢?

    首先来说说它们之间的关系,java.util.Date这个类是java.sql.Date,  java.sql.Time,  java.slq.Timestamp这三个类的父类。这三个类对java.util.Date类进行了包装。

    java.sql.Date类屏蔽了java.util.Date类的时间有关的方法(形如:hh:mm:ss),因此,不可以通过这个类访问时间有关的信息,比如,如果你通过sqlDate.getHour()方法去访问小时信息,此方法会抛出一个IllegalArgumentException异常。这是因为java.sql.Date在继承java.util.Date类的时候对父类进行了重写,禁用了时间访问的方法。之所以这么处理,是为了和数据库的Date数据类型相匹配,数据库的Date数据类行只是保存日期有关的字段。

    Java.sql.Time类屏蔽了java.util.Date的日期有关的字段(形如:yyyy-MM-dd),因此,不能通过这个类访问日期有关的信息,比如:如果你通过sqlTime.getYear()方法去获取年有关的信息,此方法会抛出一个IllegalArgumentException异常。这是因为java.sql.Time在继承java.util.Date类的时候对父类进行了重写,禁用了日期访问的方法。之所以这么处理,是为了和数据库的Time数据类型相匹配,数据库的Time数据类行只是保存时间有关的字段。

    Java.sql.Timestamp字段则对java.util.Date这个类进行了扩充,它在java.util.Date类的基础上增加了毫秒的时间访问控制,因此,你可以通过getNanos()方法去获取时间的毫微秒数(注意此处获取的时间是以毫微秒为单位的,1秒等于十亿毫微秒),同样的,这也是为了和数据库中的Timestamp数据类型进行匹配。

    理清了上述四个类的关系,那么java.util.Date和java.util.Calendar类有什么关系呢?

    Java.util.Calendar类是java.util.Date类的一个更加深入,更加全面的替代。Java.util.Calendar类支持java.util.Date的所有功能,此外,Calendar还引入了多语言,多区域的特性,可以根据需要获取不同区域,不同时区的时间,Calendar还增加了比Date更加方便和快捷的许多操作,如获取一年当中的第几个星期,各个月的天数等便捷的方法。

    Java.util.Calendar区别与java.util.Date的几个地方也需要注意一下:首先,Calendar增加了毫秒的时间段,通过它可以获取时间点的毫秒值,而java.util.Date只是精确到秒。其次,Calendar过去年的时候是当前年份比如:2010,而Date获取年份的时获取到的是当前年份-1900的一个值(2010-1900=110,因此,你调用getYear后过去的值就是110)。最后Calendar是一个抽象类,之所以能够实例化,是因为此处的Calendar充当了一个类似于工厂的作用,在getInstance方法中实例化了Calendar子类GregorianCalendar,并把它返回给客户使用。

    posted @ 2012-08-01 18:33 奋斗成就男人 阅读(519) | 评论 (0)编辑 收藏

    execute、executeUpdate、executeQuery三者的区别(及返回值)

    一、boolean execute(String sql)
    允许执行查询语句、更新语句、DDL语句。
    返回值为true时,表示执行的是查询语句,可以通过getResultSet方法获取结果;返回值为false时,执行的是更新语句或DDL语句,getUpdateCount方法获取更新的记录数量。
    例子:
    public static void main(String[] args) {

      Connection conn 
    = null;
      Statement stm 
    = null;
      ResultSet rs 
    = null;
      
    try {
       Class.forName(
    "com.microsoft.sqlserver.jdbc.SQLServerDriver");
       conn 
    = DriverManager.getConnection("jdbc:sqlserver://localhost:1433;databaseName=Test;user=sa;password=sasa");
       stm 
    = conn.createStatement();
       
    boolean ret = stm.execute("select * from stuinfo");
       
    if(ret){
        rs 
    = stm.getResultSet();
        
    while(rs.next()){
         System.out.println(
    "姓名:"+rs.getString("stuName")+"\t年龄:"+rs.getString("stuScore"));
        }

       }

       ret 
    = stm.execute("update stuinfo set stuScore=62 where stuname='张三'");
       
    int count = stm.getUpdateCount();
       
    if(!ret){
        System.out.println(count
    +"条数据修改成功!");
       }

      }
     catch (ClassNotFoundException e) {
       e.printStackTrace();
      }
     catch (SQLException e) {
       e.printStackTrace();
      }
      
     }

    二、
    int executeUpdate(String sql)
    执行给定 SQL 语句,该语句可能为 INSERT、UPDATE 或 DELETE 语句,或者不返回任何内容的 SQL 语句(如 SQL DDL 语句)。
    返回值是更新的记录数量
    三、ResultSet executeQuery(String sql)
    执行给定的 SQL 语句,该语句返回单个 ResultSet 对象。

    posted @ 2012-08-01 18:31 奋斗成就男人 阅读(4544) | 评论 (0)编辑 收藏

    struts2.0工作原理

    最近学习struts2,其实它就是webwork2.2的升级版,现附上原理图 

    struts2.0工作原理 - caoyanhua_05 - caoyanhua_05的博客

    上图来源于Struts2官方站点,是Struts 2 的整体结构。

    一个请求在Struts2框架中的处理大概分为以下几个步骤

    1 客户端初始化一个指向Servlet容器(例如Tomcat)的请求

    2 这个请求经过一系列的过滤器(Filter)(这些过滤器中有一个叫做ActionContextCleanUp的可选过滤器,这个过滤器对于Struts2和其他框架的集成很有帮助,例如:SiteMesh Plugin)

    3 接着FilterDispatcher被调用,FilterDispatcher询问ActionMapper来决定这个请是否需要调用某个Action

    4 如果ActionMapper决定需要调用某个Action,FilterDispatcher把请求的处理交给ActionProxy

    5 ActionProxy通过Configuration Manager询问框架的配置文件,找到需要调用的Action类

    6 ActionProxy创建一个ActionInvocation的实例。

    7 ActionInvocation实例使用命名模式来调用,在调用Action的过程前后,涉及到相关拦截器(Intercepter)的调用。

    8 一旦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果。返回结果通常是(但不总是,也可 能是另外的一个Action链)一个需要被表示的JSP或者FreeMarker的模版。在表示的过程中可以使用Struts2 框架中继承的标签。在这个过程中需要涉及到ActionMapper

     

    在上述过程中所有的对象(Action,Results,Interceptors,等)都是通过ObjectFactory来创建的。

    posted @ 2012-08-01 17:46 奋斗成就男人 阅读(166) | 评论 (0)编辑 收藏

    Struts2拦截器(Interceptor)

         摘要: 1.    理解拦截器 1.1.    什么是拦截器: 拦截器,在AOP(Aspect-Oriented Programming)中用于在某个方法或字段被访问之前,进行拦截然后在之前或之后加入某些操作。拦截是AOP的一种实现策略。 在Webwork的中文文档的解释为——拦截器是动态拦截Action调用的对象。...  阅读全文

    posted @ 2012-08-01 17:44 奋斗成就男人 阅读(173) | 评论 (0)编辑 收藏

    Struts2文件的上传和下载

         摘要: Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->1.    文件上传的原理:表单元素的enctype属性指定的是表单数据的编码方式,该属性有3个值:1)     ...  阅读全文

    posted @ 2012-08-01 17:41 奋斗成就男人 阅读(573) | 评论 (0)编辑 收藏

    Java中定时器

    对于开发游戏项目的同胞来说,Timer 这个东西肯定不会陌生,今天放假闲来无事,对以前自己经常使用的定时进行了一番小小的总结!没有写具体实现的原理,只是列举出了其中的四种比较常见的使用方法,相对而言,所以只要按照其所列举的例子仿照即可!

    import java.util.Calendar;
    import java.util.Date;
    import java.util.Timer;
    import java.util.TimerTask;

    public class TimeTest {
        
    public static void main(String[] args) {
            timer1();
            
    //timer2();
            
    //timer3();
            
    //timer4();
        }


        
    // 第一种方法:设定指定任务task在指定时间time执行 schedule(TimerTask task, Date time)
        public static void timer1() {
            Timer timer 
    = new Timer();
            timer.schedule(
    new TimerTask() {
                
    public void run() {
                    System.out.println(
    "-------设定要指定任务--------");
                }

            }
    2000);// 设定指定的时间time,此处为2000毫秒
        }


        
    // 第二种方法:设定指定任务task在指定延迟delay后进行固定延迟peroid的执行
        
    // schedule(TimerTask task, long delay, long period)
        public static void timer2() {
            Timer timer 
    = new Timer();
            timer.schedule(
    new TimerTask() {
                
    public void run() {
                    System.out.println(
    "-------设定要指定任务--------");
                }

            }
    10005000);
        }


        
    // 第三种方法:设定指定任务task在指定延迟delay后进行固定频率peroid的执行。
        
    // scheduleAtFixedRate(TimerTask task, long delay, long period)
        public static void timer3() {
            Timer timer 
    = new Timer();
            timer.scheduleAtFixedRate(
    new TimerTask() {
                
    public void run() {
                    System.out.println(
    "-------设定要指定任务--------");
                }

            }
    10002000);
        }

        
        
    // 第四种方法:安排指定的任务task在指定的时间firstTime开始进行重复的固定速率period执行.
        
    // Timer.scheduleAtFixedRate(TimerTask task,Date firstTime,long period)
        public static void timer4() {
            Calendar calendar 
    = Calendar.getInstance();
            calendar.set(Calendar.HOUR_OF_DAY, 
    12); // 控制时
            calendar.set(Calendar.MINUTE, 0);       // 控制分
            calendar.set(Calendar.SECOND, 0);       // 控制秒

            Date time 
    = calendar.getTime();         // 得出执行任务的时间,此处为今天的12:00:00

            Timer timer 
    = new Timer();
            timer.scheduleAtFixedRate(
    new TimerTask() {
                
    public void run() {
                    System.out.println(
    "-------设定要指定任务--------");
                }

            }
    , time, 1000 * 60 * 60 * 24);// 这里设定将延时每天固定执行
        }

    }

    posted @ 2012-08-01 17:36 奋斗成就男人 阅读(1010) | 评论 (1)编辑 收藏

    Javascript 常用验证

         摘要: Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->javascript常用验证:(1):验证IP地址:function checkIP(){  var ipArray,ip,j;  ip&nbs...  阅读全文

    posted @ 2012-07-24 12:34 奋斗成就男人 阅读(241) | 评论 (0)编辑 收藏

    oracle数据库分配表空间、创建用户、分配用户权限操作

    1、创建临时表空间
    /* create temporary tablespace*/
    create temporary tablespace student_temp 
    tempfile 'D:\oracle\product\10.2.0\oradata\Student\student_temp.dbf'
    size 50m 
    autoextend on 
    next 50m maxsize 20480m 
    extent management local; 

     

    2、创建数据表空间
    /* create data tablespace*/
    create tablespace student_data 
    logging 
    datafile 'D:\oracle\product\10.2.0\oradata\Student\student_data.dbf'
    size 50m 
    autoextend on 
    next 50m maxsize 20480m 
    extent management local;

     

    3、创建用户并分配权限
    /* create user and distribute tablespace */
    create user student identified by cxhuan 
    default tablespace student_data 
    temporary tablespace student_temp;

     

    4、给用户授权
    /* authorize role to user */
    grant connect,resource,dba to student;  

    posted @ 2012-07-19 16:12 奋斗成就男人 阅读(1043) | 评论 (0)编辑 收藏

    使用POI读取EXCEL中的所有Sheet表

    使用POI,通过多个循环读取EXCEL中的所有Sheet表内容。

    package poitest;
    import java.io.File;
    import java.io.FileInputStream;
    import org.apache.poi.hssf.usermodel.HSSFRow;
    import org.apache.poi.hssf.usermodel.HSSFSheet;
    import org.apache.poi.hssf.usermodel.HSSFWorkbook;

    public class getAllExcelData {

        
    public static void main(String[] args) {
                
    try {
                    showExcel();
                }
     catch (Exception e) {
                    
    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

        }

        
    public static  void showExcel() throws Exception {
            HSSFWorkbook workbook
    =new HSSFWorkbook(new FileInputStream(new File("/file/student.xls")));
            HSSFSheet sheet
    =null;
            
    for (int i = 0; i < workbook.getNumberOfSheets(); i++{//获取每个Sheet表
                 sheet=workbook.getSheetAt(i);
                 
    for (int j = 0; j < sheet.getPhysicalNumberOfRows(); j++{//获取每行
                    HSSFRow row=sheet.getRow(j);
                    
    for (int k = 0; k < row.getPhysicalNumberOfCells(); k++{//获取每个单元格
                        System.out.print(row.getCell(k)+"\t");
                    }

                    System.out.println(
    "---Sheet表"+i+"处理完毕---");
                }

        }

        }

    }

    posted @ 2012-07-19 16:08 奋斗成就男人 阅读(25848) | 评论 (1)编辑 收藏

    最简单的Java处理事务

    用一个简单的例子来说明Java处理事务:
    我们用银行转账的时候可以简单的看成是两步操作--将钱从A账户转出和将钱转到B账户。问题来了,如果我从A账户转出之后,突然无法连接数据库了,这样钱就不能转到B账户了,可是A的钱已经没了。所以我们应该把这两步看成是一个整体,要么同时成功,要么什么都不做。这就是事务了。
     
    Java中是如何处理事务的呢?
    我们从java.sql.Connection说起,Connection表示了一个和数据库的链接,可以通过Connection来对数据库操作。在通常情况是Connection的属性是自动提交的,也就是说每次的操作真的更新了数据库,真的无法回退了。针对上述的例子,一旦A账户的钱转出了,即对数据库进行了更新操作了,但是钱并没有转到B的账户,这笔钱就白白“不见”了。这并不是我们希望的。 
        我们希望的是:看起来成功了,但是没有真的操作数据库,知道我想让他真的发生。可以通过Connection的setAutoCommit(false)让Connection不自动提交你的数据,除非你真的想提交。那么如何让操作真的发生呢?可以使用Connection的commit方法。如何让操作回退呢?使用rollback方法。
    例如: 
      try{ 
      Connection conn = getConnection(); // 不管如何我们得到了链接 
      conn.setAutoCommit(false); 
      // A账户转出
      // B账户转入
      conn.commit(); // 成功的情况下,提交更新。 
      } catch(SQLException ex) { 
      conn.rollback(); // 失败的情况下,回滚所有的操作 
      } finally { 
      conn.close();
      } 
        这里有一点非常重要,事务是基于数据库链接的。所以在但数据库的情况下,事务操作很简单。 
      那么如果表分布在两个不同的数据库中呢? 
      例如订单表在订单库中,库存表在库存库中,那么我们如何处理这样的事务呢? 
      需要注意,提交也可以遇到错误呀! 
      try{ 
      Connection conn1 = getConnection1(); 
      Connection conn2 = getConnection2(); 
      // 基于conn1做更新操作 
      // 基于conn2做更新操作 
      try{ 
      conn1.commit() 
      } catch(SQLExcetion ) { 
      conn1.rollback(); 
      } 
      try { 
      conn2.commit(); 
      } catch(SQLException ) { 
      conn2.rollbakc(); 
      // 保证务必将刚才的更新还原回来。 
      } 
      } catch(SQLException ex) { 
      // 如果更新失败,conn1.rollback 
      // 如果更新失败,conn1.rollback && conn2.rollback 
      } finally { 
      conn1.close(); 
      conn2.close(); 
      } 
      看看上述的代码就知道,其实操作非常的复杂,甚至:保证肯定还原刚才更新的账户根本无法保证。
    在上述情况下的事务可以称之为分布式事务,通过上述的代码中事务同时提交处理的部分我们可以得出,要想处理分布式事务,必须有独立于数据库的第三方的事务处理组件。 
      幸运的是通常情况下,JavaEE兼容的应用服务器,例如:Weblogic,Websphere,JBoss,Glassfish等都有这种分布式事务处理的组件。 

    如何使用应用服务器的分布式事务管理器处理分布式事务? 
      以galssfish为例 
      1 建立对应两个数据库的XA(javax.sql.XADataSource)类型的数据源。 
      2 使用UserTransaction来保证分布式事务。 
      try{ 
      Connection conn1 = datasource1.getConnection(); 
      Connection conn2 = datasource2.getConnection(); 
      UserTransaction ut = getUserTransaction(); 
      ut.begin(); 
      // A账户转出
      // B账户转入
      ut.commit(); // 成功的情况下,提交更新。 
      } catch(SQLException ex) { 
      ut.rollback(); // 失败的情况下,回滚所有的操作 
      } finally { 
      conn.close(); 
      } 
      如何获取UserTransaction呢?可以使用如下方法 
      UserTransaction tx = (UserTransaction) ctx.lookup("jndi/UserTransaction"); 

    posted @ 2012-07-19 15:35 奋斗成就男人 阅读(177) | 评论 (0)编辑 收藏

    Java通过URL获取网站Html源代码

    package com.wsw.j2se.url;

    import java.io.ByteArrayOutputStream;
    import java.io.InputStream;
    import java.net.HttpURLConnection;
    import java.net.URL;

    /**
     * 通过网站域名URL获取该网站的源码
     * 
    @author Administrator
     *
     
    */

    public class HtmlRequest {
        
    /**
        * 
    @param args
        * 
    @throws MalformedURLException 
        
    */

        
    public static void main(String[] args) throws Exception    {
            URL url 
    = new URL("http://www.ifeng.com"); 
            String urlsource 
    = getURLSource(url);
            System.out.println(urlsource);
        }

        
        
    /**
         * 通过网站域名URL获取该网站的源码
         * 
    @param url
         * 
    @return String
         * 
    @throws Exception
         
    */

        
    public static String getURLSource(URL url) throws Exception    {
            HttpURLConnection conn 
    = (HttpURLConnection)url.openConnection();
            conn.setRequestMethod(
    "GET");
            conn.setConnectTimeout(
    5 * 1000);
            InputStream inStream 
    =  conn.getInputStream();  //通过输入流获取html二进制数据
            byte[] data = readInputStream(inStream);        //把二进制数据转化为byte字节数据
            String htmlSource = new String(data);
            
    return htmlSource;
        }

        
        
    /**
         * 把二进制流转化为byte字节数组
         * 
    @param instream
         * 
    @return byte[]
         * 
    @throws Exception
         
    */

        
    public static byte[] readInputStream(InputStream instream) throws Exception {
            ByteArrayOutputStream outStream 
    = new ByteArrayOutputStream();
            
    byte[]  buffer = new byte[1204];
            
    int len = 0;
            
    while ((len = instream.read(buffer)) != -1){
                outStream.write(buffer,
    0,len);
            }

            instream.close();
            
    return outStream.toByteArray();         
        }

    }

    posted @ 2012-07-19 12:40 奋斗成就男人 阅读(4491) | 评论 (3)编辑 收藏

    Oracle中把一个查询结果插入到一张表中

    一、Oracle数据库中,把一张表的查询结果直接生成并导入一张新表中。 

    例如:现有只有A表,查询A表,并且把结果导入B表中。使用如下SQL语句: 

    create table b as select 
    * from a 

    二、Oracle数据库中支持把查询结果导入到另外一张表中。 

    例如:有两个表A和B 

    1)如果两个表的表结构是否相同,但要插入的字段类型相同: 

    (
    1)把A表的全部字段数据插入到B表中: 
    insert into B select 
    * from A; 

    (
    2)把A表中某些字段的数据插入B表中: 
    insert into B(字段名)(select 字段名 from A) 

    2)如果不在同一个schema下请在表名前加上schema,例如有schema a和b: 

    insert into b.B select 
    * from a.A 

    三、在jdbc中,还可以把一个表部分字段插入到另一个表中。
        insert into p_person(name,age,job) select name,?,job from p_person1 where id = ?       
    -- 第一个?可以按照需要进行设值,而不是表示它是p_person1字段名

    posted @ 2012-07-17 15:21 奋斗成就男人 阅读(10998) | 评论 (0)编辑 收藏

    在JDBC一次插入多个表、多条记录

     

    在jdbc操作中,通过事务操作,一次可以插入多个表 ,多条记录:

    public static void insertBatch() {
      
    int count[];
      
    int count1[];
      Boolean isinsert 
    = false;
      Connection con 
    = null;
      PreparedStatement pst 
    = null;
      PreparedStatement pst1 
    = null;
      
    try {
       con 
    = getCon();
       con.setAutoCommit(
    false);                                   // 需要用到事务,不能让他自动提交,需要手动提交
       pst = con.prepareStatement(INSERT_SQL);          // INSERT_SQL表示对一张表的插入记录
       pst1 = con.prepareStatement(INSERT_SQL1);      // INSERT_SQL表示对另一张表的插入记录

       pst.setString(
    1"name1");
       pst.setInt(
    226);
       pst.setString(
    3"job1");
       pst.addBatch();
       
       pst.setString(
    1"name2");
       pst.setInt(
    212);
       pst.setString(
    3"job2");
       pst.addBatch();
       
    -------可以对pst进行更多的插入-----------
       pst1.setString(
    1"name--1");
       pst1.setInt(
    226);
       pst1.setString(
    3"job--1");
       pst1.addBatch();
       
       pst1.setString(
    1"name--2");
       pst1.setInt(
    226);
       pst1.setString(
    3"job--2");
       pst1.addBatch();
       
    -------可以对pst1进行更多的插入-----------
       count 
    = pst.executeBatch();
       count1 
    = pst1.executeBatch();
       con.commit();                 
    //提交事务,这个非常重要
       
       
    for(int i : count){
        
    if(i == 0{
         con.rollback();              
    // 回滚,非常重要
         System.out.println("======出现异常,回滚=========");
        }

       }

       
       
    for(int i : count1){
        
    if(i == 0{
         con.rollback();          
    // 回滚,非常重要
         System.out.println("==111====出现异常,回滚====111=====");
        }

       }

         
      }
     catch (SQLException e) {
       
    try {
        con.rollback();            
    // 回滚,非常重要
       }
     catch (SQLException e1) {
        e1.printStackTrace();
       }

       System.out.println(
    "------出现异常,回滚----------");
       e.printStackTrace();
      }
     finally {
       cloCon(con,pst);
      }

     }

     

    posted @ 2012-07-17 14:40 奋斗成就男人 阅读(2633) | 评论 (0)编辑 收藏

    存储过程的好处和一些注意事项!

    存储过程天天用,关于使用存储过程的sql语句的争论也一直在,个人觉得使用存储过程要好于用sql语句,整理了一些说明:

    存储过程是由一些SQL语句和控制语句组成的被封装起来的过程,它驻留在数据库中,可以被客户应用程序调用,也可以从另一个过程或触发器调用。它的参数可以被传递和返回。与应用程序中的函数过程类似,存储过程可以通过名字来调用,而且它们同样有输入参数和输出参数。

      根据返回值类型的不同,我们可以将存储过程分为三类:返回记录集的存储过程, 返回数值的存储过程(也可以称为标量存储过程),以及行为存储过程。顾名思义,返回记录集的存储过程的执行结果是一个记录集,典型的例子是从数据库中检索出符合某一个或几个条件的记录;返回数值的存储过程执行完以后返回一个值,例如在数据库中执行一个有返回值的函数或命令;最后,行为存储过程仅仅是用来实现数据库的某个功能,而没有返回值,例如在数据库中的更新和删除操作。

      使用存储过程的好处

      相对于直接使用SQL语句,在应用程序中直接调用存储过程有以下好处:

      (1)减少网络通信量。调用一个行数不多的存储过程与直接调用SQL语句的网络通信量可能不会有很大的差别,可是如果存储过程包含上百行SQL语句,那么其性能绝对比一条一条的调用SQL语句要高得多。

      (2)执行速度更快。有两个原因:首先,在存储过程创建的时候,数据库已经对其进行了一次解析和优化。其次,存储过程一旦执行,在内存中就会保留一份这个存储过程,这样下次再执行同样的存储过程时,可以从内存中直接调用。

      (3)更强的适应性:由于存储过程对数据库的访问是通过存储过程来进行的,因此数据库开发人员可以在不改动存储过程接口的情况下对数据库进行任何改动,而这些改动不会对应用程序造成影响。

      (4) 布式工作:应用程序和数据库的编码工作可以分别独立进行,而不会相互压制。

    msdn上面相关的说明

    考虑使用存储过程的理由

    也许您曾经在多处编写过使用 SqlCommand 对象的 T-SQL,但却从未考虑过是否有一个比将它并入数据访问代码更好的位置。由于应用程序随着时间的推移增添了一些功能,因此其内部可能包含一些复杂的 T-SQL 过程代码。存储过程为封装此代码提供了一个替换位置。

    大多数人可能对存储过程已有所了解,但对于那些不了解存储过程的人员而言,存储过程是指一组作为单个代码单元一起存储于数据库中的 T-SQL 语句。您可以使用输入参数传入运行时信息,并取回作为结果集或输出参数的数据。存储过程在首次运行时将被编译。这将产生一个执行计划 - 实际上是 Microsoft® SQL Server™ 为在存储过程中获取由 T-SQL 指定的结果而必须采取的步骤的记录。然后,执行计划在内存中得到缓存,以备以后使用。这样会改善存储过程的性能,因为 SQL Server 无需为确定如何处理代码而重新分析它,而只需引用缓存的计划即可。这个缓存的计划一直可用,直到 SQL Server 重新启动,或直到它由于使用率较低而溢出内存。

    性能

    缓存的执行计划曾使存储过程较之查询更有性能优势。但对于 SQL Server 的几个最新版本,执行计划已针对所有 T-SQL 批处理进行了缓存,而不管它们是否在存储过程中。因此,基于此功能的性能已不再是存储过程的卖点。任何使用静态语法,且提交频率足以阻止执行计划溢出内存的 T-SQL 批处理将会获得同样的性能好处。“静态”部分是关键;任何更改,即使像添加注释这样无关紧要的更改,也将导致无法与缓存的计划相匹配,从而将无法重复使用计划。

    但是,当存储过程可以用于降低网络流量时,它们仍然能够提供性能好处。您只需在网络中发送 EXECUTE stored_proc_name 语句,而非整个 T-SQL 例程,这可以在复杂操作中广泛使用。设计良好的存储过程可以将客户端与服务器之间的许多往返过程简化为单个调用。

    此外,使用存储过程使您能够增强对执行计划的重复使用,由此可以通过使用远程过程调用 (RPC) 处理服务器上的存储过程而提高性能。使用 StoredProcedure 的 SqlCommand.CommandType 时,存储过程通过 RPC 执行。RPC 封装参数和调用服务器端过程的方式使引擎能够轻松地找到匹配的执行计划,并只需插入更新的参数值。

    考虑使用存储过程提高性能时,最后要考虑是否要充分利用 T-SQL 的优点。请考虑要如何处理数据。

    是否要使用基于集合的操作,或执行 T-SQL 中完全支持的其他操作?那么存储过程就是一个选择,而内联查询也可以使用。

    是否尝试执行基于行的操作,或复杂的字符串处理?那么可能要重新考虑在 T-SQL 中进行这种处理,这不包括使用存储过程,至少要到 Yukon 发布并且公共语言运行库 (CLR) 集成可用后,才能使用存储过程。

    可维护性和抽象

    要考虑的另一个潜在优势是可维护性。理想情况下,数据库架构从不更改,业务规则不被修改,但在现实环境中,情况则完全不同。既然情况如此,那么如果可以修改存储过程以包括新 X、Y 和 Z 表(为支持新的销售活动而添加了这些表)中的数据,而不是在应用程序代码中的某个位置更改此信息,则维护对您来说可能比较容易。在存储过程中更改此信息使得更新对应用程序而言具有透明性 - 您仍然返回相同的销售信息,即使存储过程的内部实现已经更改。更新存储过程通常比更改、测试以及重新部署程序集需要较少的时间和精力。

    另外,通过抽象化实现并将此代码保存在存储过程中,任何需要访问数据的应用程序均可以获取一致的数据。您无需在多个位置维护相同的代码,用户便可获取一致的信息。

    在存储过程中存储 T-SQL 的另一个可维护性优点是更好的版本控制。您可以对创建和修改存储过程的脚本进行版本控制,就像可以对任何其他源代码模块进行版本控制一样。通过使用 Microsoft Visual SourceSafe® 或某个其他源代码控制工具,您可以轻松地恢复到或引用旧版本的存储过程。

    在使用存储过程提高可维护性时应值得注意的一点是,它们无法阻止您对架构和规则进行所有可能的更改。如果更改范围大到需要对输入存储过程的参数进行更改,或者要更改由其返回的数据,则您仍需要更新程序集中的代码以添加参数、更新 GetValue() 调用,等等。

    要注意的另一个问题是,由于存储过程将应用程序绑定到 SQL Server,因此使用存储过程封装业务逻辑将限制应用程序的可移植性。如果应用程序的可移植性在您的环境中非常重要,则将业务逻辑封装在不特定于 RDBMS 的中间层中可能是一个更佳的选择。

    安全性

    考虑使用存储过程的最终原因是它们可用于增强安全性。

    就管理用户对信息的访问而言,通过向用户授予对存储过程(而不是基础表)的访问权限,它们可以提供对特定数据的访问。您可以将存储过程看成是 SQL Server 视图(如果您对它们熟悉的话),除非存储过程接受用户的输入以动态更改显示的数据。

    存储过程还可以帮助您解决代码安全问题。它们可以防止某些类型的 SQL 插入攻击 - 主要是一些使用运算符(如 AND 或 OR)将命令附加到有效输入参数值的攻击。在应用程序受到攻击时,存储过程还可以隐藏业务规则的实现。这对于将此类信息视为知识产权的公司非常重要。

    另外,使用存储过程使您可以使用 ADO.NET 中提供的 SqlParameter 类指定存储过程参数的数据类型。这为验证用户提供的值类型(作为深层次防御性策略的一部分)提供了一个简单方法。在缩小可接受用户输入的范围方面,参数在内联查询中与在存储过程中一样有用。

    使用存储过程增强安全性时值得注意的是,糟糕的安全性或编码做法仍然会使您受到攻击。对 SQL Server 角色创建和分配如果不加注意将导致人们访问到不应看到的数据。同时,如果认为使用存储过程便可防止所有 SQL 插入代码攻击(例如,将数据操作语言 (DML) 附加到输入参数),后果将是一样的。

    另外,无论 T-SQL 位于代码还是位于存储过程中,使用参数进行数据类型验证都不是万无一失的。所有用户提供的数据(尤其是文本数据)在传递到数据库之前都应受到附加的验证。

    存储过程对我是否适用?

    或许适合吧。让我们概括一下它们的优点:

    通过降低网络流量提高性能

    提供单点维护

    抽象化业务规则,以确保一致性和安全性

    通过将某些形式的攻击降至最低,以增强安全性

    支持执行计划重复使用

    如果您的环境允许利用存储过程提供的好处(如上所述),强烈建议使用它们。对于改进数据在环境中的处理方式而言,它们提供了一个很好的工具。另一方面,如果您的环境中存在可移植性、大量使用非 T-SQL 友好的进程或者不稳定的数据库架构等削弱这些优点的因素,则您可能要考虑其他方法。

    另一个要注意的事项是机构内部所拥有的 T-SQL 专业人员的数量。您有足够的 T-SQL 知识吗?您愿意学习吗?或者,您有 DBA 或合适的人员帮您编写存储过程吗?掌握的 T-SQL 知识越多,存储过程就会越好,维护它们就会越容易。例如,T-SQL 主要用于基于集合的操作,而不是基于行的操作。依赖于光标(因为它们向您提示数据集)将导致性能降低。如果您不太了解 T-SQL,请将本文作为一次学习机会。无论您将它用在何处,本文介绍的知识都将改善您的代码。

    因此,如果您认为存储过程会为应用程序增添特殊的效果,请继续阅读本文。我们将回顾一些简化存储过程使用的工具,并了解一些创建存储过程的最佳做法。


     
    注意事项

    如果要开始创建与应用程序一起使用的存储过程,应记住下面这些提示,以便两者正常运行并良好地配合工作。

    使用 SET NOCOUNT ON

    默认情况下,存储过程将返回过程中每个语句影响的行数。如果不需要在应用程序中使用该信息(大多数应用程序并不需要),请在存储过程中使用 SET NOCOUNT ON 语句以终止该行为。根据存储过程中包含的影响行的语句的数量,这将删除客户端和服务器之间的一个或多个往返过程。尽管这不是大问题,但它可以为高流量应用程序的性能产生负面影响。

    create procedure test_MyStoredProc @param1 intasset nocount on

    不要使用 sp_ prefix

    sp_ prefix 是为系统存储过程保留的。数据库引擎将始终首先在主数据库中查找具有此前缀的存储过程。这意味着当引擎首先检查主数据库,然后检查存储过程实际所在的数据库时,将需要较长的时间才能完成检查过程。而且,如果碰巧存在一个名称相同的系统存储过程,则您的过程根本不会得到处理。

    尽量少用可选参数

    在频繁使用可选参数之前,请仔细考虑。通过执行额外的工作会很轻易地影响性能,而根据为任意指定执行输入的参数集合,这些工作时不需要的。您可以通过对每种可能的参数组合使用条件编码来解决此问题,但这相当费时并会增大出错的几率。

    在可能的情况下使用 OUTPUT 参数

    通过使用 OUTPUT 参数返回标量数据,可以略微提高速度并节省少量的处理功率。在应用程序需要返回单个值的情况下,请尝试此方法,而不要将结果集具体化。在适当的情况下,也可以使用 OUTPUT 参数返回光标,但是我们将在后续文章中介绍光标处理与基于集合的处理在理论上的分歧。

    提供返回值

    使用存储过程的返回值,将处理状态信息返回给进行调用的应用程序。在您的开发组中,将一组返回值及其含义标准化,并一致地使用这些值。这会使得处理调用应用程序中的错误更加容易,并向最终用户提供有关问题的有用信息。

    首先使用 DDL,然后使用 DML

    将 DML 语句放在数据定义语言 (DDL) 语句之后执行(此时 DML 将引用 DDL 修改的任意对象)时,SQL Server 将重新编译存储过程。出现这种情况,是由于为了给 DML 创建计划,SQL Server 需要考虑由 DDL 对该对象所作的更改。如果留意存储过程开头的所有 DDL,则它只需重新编译一次。如果将 DDL 和 DML 语句混合使用,则将强制存储过程多次进行重新编译,这将对性能造成负面影响。

    posted @ 2012-07-13 22:39 奋斗成就男人 阅读(187) | 评论 (0)编辑 收藏

    ssh中applicationContext.xml配置

        
        在ssh中,applicationContext.xml是默认是需要放到:WEB-INF 目录下的:
        
        

    <?xml version="1.0" encoding="UTF-8"?>
    <beans
     xmlns="http://www.springframework.org/schema/beans"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns:p="http://www.springframework.org/schema/p"
     xsi:schemaLocation="http://www.springframework.org/schema/beans
     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">


     <bean id="dataSource"
      class="org.apache.commons.dbcp.BasicDataSource">
      <property name="driverClassName"
       value="com.mysql.jdbc.Driver">
      </property>
      <property name="url" value="jdbc:mysql://localhost:3306/ssh"></property>
      <property name="username" value="root"></property>
      <property name="password" value="root"></property>
     </bean>
     <bean id="sessionFactory"
      class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
      <property name="dataSource">
       <ref bean="dataSource" />
      </property>
      <property name="hibernateProperties">
       <props>
        <prop key="hibernate.dialect">
         org.hibernate.dialect.MySQLDialect
        </prop>
       </props>
      </property>
      <property name="mappingResources">
       <list>
        <value>com/wsw/ssh/model/User.hbm.xml</value></list>
      </property>
     </bean>
     
     <bean id="userDAOImpl" class="com.wsw.ssh.dao.impl.UserDAOImpl">
      <property name="sessionFactory">
       <ref bean="sessionFactory" />
      </property>
     </bean>
     <bean id="userServiceImpl" class="com.wsw.ssh.service.impl.UserServiceImpl">
      <property name="userDAO">
       <ref bean="userDAOImpl"/>
      </property>
     </bean>
     
     <bean id="userAction" class="com.wsw.ssh.action.UserAction">
      <property name="userService">    <!--userService 表示在此类中使用userService 对象属性(还需要get和set方法),而不是userService 类-->
       <ref bean="userServiceImpl"/>
      </property>
     </bean>
     </beans>

    posted @ 2012-07-09 17:36 奋斗成就男人 阅读(1654) | 评论 (0)编辑 收藏

    ssh框架web.xml的基本配置

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
        http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
       
        <!-- 配置spring的监听器 -->
        <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/applicationContext*.xml</param-value>
        </context-param>
       
        <!-- 开启监听 -->
        <listener>
            <listener-class>
                org.springframework.web.context.ContextLoaderListener
            </listener-class>
        </listener>
       
        <!-- 配置OpenSessionInViewFilter,必须在struts2监听之前 -->
        <!--
        <filter>
            <filter-name>lazyLoadingFilter</filter-name>
            <filter-class>
                org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
            </filter-class>
        </filter>
        <filter-mapping>
         <filter-name>lazyLoadingFilter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
         -->
        <!-- 设置监听加载上下文 -->
        <filter>
            <filter-name>struts2</filter-name>
            <filter-class>
               org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
            </filter-class>
        </filter>
     <filter-mapping>
      <filter-name>struts2</filter-name>
      <url-pattern>/*</url-pattern>                         <!--注意:千万不能写成:*.action ,如果需要:*.action应该配置在struts.xml中-->
     </filter-mapping>
     
        <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
        </welcome-file-list>
    </web-app>

    posted @ 2012-07-09 17:28 奋斗成就男人 阅读(10960) | 评论 (0)编辑 收藏

    Hibernate实现CRUD操作

         摘要: Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->        最近学习hibernate有几天了,基本学会简单的增删改查,现在就把实现分享如下:  &...  阅读全文

    posted @ 2012-06-30 10:29 奋斗成就男人 阅读(2935) | 评论 (0)编辑 收藏

    Hibernate实现有两种配置,xml配置与注释配置

         摘要: hibernate实现有两种配置,xml配置与注释配置。 (1):xml配置:hibernate.cfg.xml (放到src目录下)和实体配置类:xxx.hbm.xml(与实体为同一目录中) <?xml version='1.0' encoding='utf-8'?> <!DOCTYPE hibernate-configuration PUBLIC  &nbs...  阅读全文

    posted @ 2012-06-30 10:00 奋斗成就男人 阅读(49823) | 评论 (4)编辑 收藏