2015年4月4日
#
项目中有时会用到自动补全查询,就像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> </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) {
//如选择后给其他控件赋值,触发别的事件等等
});
过页头生成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,在需要的地方加上,或者直接设为全局拦截器都是可以的,简单,快捷;
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代码:
- ScriptEngineManager factory = new ScriptEngineManager();
- ScriptEngineManager scriptEngine = factory.getEngineByName("javascript");//或者"js"
- 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)
- ScriptEngineManager factory = new ScriptEngineManager();
- ScriptEngineManager scriptEngine = factory.getEngineByName("python");//或者"jython"
- scriptEngine.eval(code);
使用PythonInterpreter,可以调用exec(String code)方法:
- PythonInterpreter interpreter = new PythonInterpreter();
- interpreter.exec(code);
访问数据库
使用jdbc:
- from oracle.jdbc.driver import OracleDriver
- from java.sql import DriverManager
-
- username = 'hr'
- password = '123456'
- url = 'jdbc:oracle:thin:@localhost:1521:XE'
- driver = OracleDriver()
- DriverManager.registerDriver(driver)
- conn = DriverManager.getConnection(url, username, password)
- stmt = conn.createStatement()
- sql = "select salary from EMPLOYEES t where t.salary<2300"
- rs = stmt.executeQuery(sql)
- while (rs.next()):
- print rs.getInt('salary')
- rs.close()
- stmt.close()
结果:
2200
2100
2200
使用zxJDBC :
- from com.ziclix.python.sql import zxJDBC
-
- url = 'jdbc:oracle:thin:@localhost:1521:XE'
- username = 'hr'
- password = '123456'
- driverName = 'oracle.jdbc.driver.OracleDriver'
- mysqlConn = zxJDBC.connect(url,username, password,driverName)
- cursor = mysqlConn.cursor()
- cursor.execute("select last_name from EMPLOYEES t where t.salary<2300");
- #print cursor.fetchone()
- list = cursor.fetchall()
- for record in list:
- print "name:"+record[0]
- #print cursor.description[0]
- #print cursor.description[1]
结果:
name:麦克
name:Olson
name:Philtanker
从数据库中查出的中文内容正常的。
而在代码里面的中文全部是乱码或抛异常,未解决。
与jruby集成
使用jsr223:Java代码
- ScriptEngineManager factory = new ScriptEngineManager();
- ScriptEngineManager scriptEngine = factory.getEngineByName("jruby");//或者"ruby"
- scriptEngine.eval(code);
访问数据库
Ruby代码
- require 'java'
-
- module JavaLang
- include_package "java.lang"
- end
-
- module JavaSql
- include_package 'java.sql'
- end
-
- begin
- username = 'hr'
- password = '123456'
- url = 'jdbc:oracle:thin:@localhost:1521:XE'
- driverName = 'oracle.jdbc.driver.OracleDriver'
- JavaLang::Class.forName(driverName).newInstance
- conn = JavaSql::DriverManager.getConnection(url, username, password)
- stmt = conn.createStatement
- sql = "select last_name from EMPLOYEES t where t.salary<2300"
- rs = stmt.executeQuery(sql)
- while (rs.next) do
- puts "名字:"+rs.getString("last_name")
- end
- rs.close
- stmt.close
- conn.close()
- rescue JavaLang::ClassNotFoundException
- puts "ClassNotFoundException"
- rescue JavaSql::SQLException
- puts "SQLException"
- end
结果:
名字:楹﹀厠
名字:Olson
名字:Philtanker
从数据库中查出的中文内容为乱码的。
而在代码里面的中文正常。
与groovy集成
使用jsr223:
Java代码
- ScriptEngineManager factory = new ScriptEngineManager();
- ScriptEngineManager scriptEngine = factory.getEngineByName("groovy");//或者"Groovy"
- scriptEngine.eval(code);
使用GroovyShell:
Java代码
- GroovyShell shell = new GroovyShell();
- Script script = shell.parse(code);
- Object result = script.run();
访问数据库
- import groovy.sql.Sql
-
- def username = 'hr'
- def password = '123456'
- def url = 'jdbc:oracle:thin:@localhost:1521:XE'
- def driverName = 'oracle.jdbc.driver.OracleDriver'
- def sql = Sql.newInstance(url, username, password, driverName)
-
- sql.eachRow("select last_name from EMPLOYEES t where t.salary<2300") {
- println "名字:${it.last_name}"
- }
结果:
名字:麦克
名字: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运行时处理的内容)
这两天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(
null,
new 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引用不对。后来就没有具体找原因了。
MySQL的SQL语句写法,除了那些基本的之外,还有一些也算比较常用的,这里记录下来,以便以后查找。
好记性不如烂笔头,这话说的太有道理了,一段时间不写它,还真容易忘记。大家不要纠结这些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, 1, 6) 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, 1, 6) = B.ORG_CODE
两表关联删除,将删除两表中有关联ID并且T2表NAME为空的两表记录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(8) DEFAULT 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';
做为一名程序员,如果你只顾得写代码,那是不行的,要抽出一下时间来丰富自己的知识,多看看书,在这里我将为程序员们推荐一些不错的书。能够给程序员们带来帮助。
大数据时代
《大数据时代》是国外大数据研究的先河之作,本书作者维克托•迈尔•舍恩伯格被誉为"大数据商业应用第一人",拥有在哈佛大学、牛津大学、耶鲁大学和新加坡国立大学等多个互联网研究重镇任教的经历,早在2010年就在《经济学人》上发布了长达14页对大数据应用的前瞻性研究。
维克托•迈尔•舍恩伯格在书中前瞻性地指出,大数据带来的信息风暴正在变革我们的生活、工作和思维,大数据开启了一次重大的时代转型,并用三个部分讲述了大数据时代的思维变革、商业变革和管理变革。
维克托最具洞见之处在于,他明确指出,大数据时代最大的转变就是,放弃对因果关系的渴求,而取而代之关注相关关系。也就是说只要知道"是什么",而不需要知道"为什么"。这就颠覆了千百年来人类的思维惯例,对人类的认知和与世界交流的方式提出了全新的挑战。
淘宝技术这十年
《淘宝技术这十年》内容简介:任何网站的发展都不是一蹴而就的。它在发展过程中会遇到各种各样的问题和业务带来的压力。正是这些问题和压力推动着技术的进步和发展,而技术的发展反过来又会促进业务的更大提升。如今淘宝网的流量排名已是全球前15名、国内前3名,其系统服务器也从一台发展到万台以上。
《淘宝技术这十年》从工程师的角度讲述淘宝这个超大规模互联网系统的成长历程,及其所有主动和被动的技术变革的前因后果。书中有幕后故事、产品经验、架构演进、技术启蒙,也有大牛成长、业内八卦、失败案例、励志故事。《淘宝技术这十年》文风流畅,有技术人员特有的幽默感;内容积极正面,有现场感,全部是作者亲身经历。
白帽子讲Web安全
《白帽子讲Web安全》内容简介:在互联网时代,数据安全与个人隐私受到了前所未有的挑战,各种新奇的攻击技术层出不穷。如何才能更好地保护我们的数据?《白帽子讲Web安全》将带你走进Web安全的世界,让你了解Web安全的方方面面。黑客不再变得神秘,攻击技术原来我也可以会,小网站主自己也能找到正确的安全道路。大公司是怎么做安全的,为什么要选择这样的方案呢?你能在《白帽子讲Web安全》中找到答案。详细的剖析,让你不仅能"知其然",更能"知其所以然"。
重构:改善既有代码的设计
《重构:改善既有代码的设计》清晰地揭示了重构的过程,解释了重构的原理和最佳实践方式,并给出了何时以及何地应该开始挖掘代码以求改善。书中给出了70多个可行的重构,每个重构都介绍了一种经过验证的代码变换手法的动机和技术。《重构:改善既有代码的设计》提出的重构准则将帮助你一次一小步地修改你的代码,从而减少了开发过程中的风险。
《重构:改善既有代码的设计》适合软件开发人员、项目管理人员等阅读,也可作为高等院校计算机及相关专业师生的参考读物。
代码整洁之道
软件质量,不但依赖于架构及项目管理,而且与代码质量紧密相关。这一点,无论是敏捷开发流派还是传统开发流派,都不得不承认。《代码整洁之道》提出一种观念:代码质量与其整洁度成正比。干净的代码,既在质量上较为可靠,也为后期维护、升级奠定了良好基础。
作为编程领域的佼佼者,《代码整洁之道》作者给出了一系列行之有效的整洁代码操作实践。这些实践在《代码整洁之道》中体现为一条条规则(或称"启示"),并辅以来自现实项目的正、反两面的范例。只要遵循这些规则,就能编写出干净的代码,从而有效提升代码质量。
《代码整洁之道》阅读对象为一切有志于改善代码质量的程序员及技术经理。书中介绍的规则均来自作者多年的实践经验,涵盖从命名到重构的多个编程方面,虽为一"家"之言,然诚有可资借鉴的价值。
设计模式之禅 (第2版)
本书是设计模式领域公认的3本经典著作之一,"极具趣味,容易理解,但讲解又极为严谨和透彻"是本书的写作风格和方法的最大特点。第1版2010年出版,畅销至今,广受好评,是该领域的里程碑著作。深刻解读6大设计原则和28种设计模式的准确定义、应用方法和最佳实践,全方位比较各种同类模式之间的异同,详细讲解将不同的模式组合使用的方法。第2版在第1版的基础上有两方面的改进,一方面结合读者的意见和建议对原有内容中的瑕疵进行了修正和完善,另一方面增加了4种新的设计模式,希望这一版能为广大程序员们奉上一场更加完美的设计模式盛宴!
程序员修炼之道
《程序员修炼之道》由一系列的独立的部分组成,涵盖的主题从个人责任、职业发展,直到用于使代码保持灵活、并且易于改编和复用的各种架构技术。利用许多富有娱乐性的奇闻轶事、有思想性的例子以及有趣的类比,全面阐释了软件开发的许多不同方面的最佳实践和重大陷阱。无论你是初学者,是有经验的程序员,还是软件项目经理,本书都适合你阅读。
平台战略:正在席卷全球的商业模式革命
《平台战略:正在席卷全球的商业模式革命》内容简介:平台商业模式的精髓,在于打造一个完善的、成长潜能强大的"生态圈"。它拥有独树一帜的精密规范和机制系统,能有效激励多方群体之间互动,达成平台企业的愿景。纵观全球许多重新定义产业架构的企业,我们往往就会发现它们成功的关键——建立起良好的"平台生态圈",连接两个以上群体,弯曲、打碎了既有的产业链。
平台生态圈里的一方群体,一旦因为需求增加而壮大,另一方群体的需求也会随之增长。如此一来,一个良性循环机制便建立了,通过此平台交流的各方也会促进对方无限增长。而通过平台模式达到战略目的,包括规模的壮大和生态圈的完善,乃至对抗竞争者,甚至是拆解产业现状、重塑市场格局。
互联网创业启示录
《互联网创业启示录》是一部互联网公司的创业指南,内容涉及网站创业的现状和机遇、创业公司价值、平台选择、工具和群组、资金的筹集、管理和盈利、社会化媒体环境、行动执行管理、开发人员方法论和工作效率、创始人的角色等方面,既有纲领和指导性理论,又有具体操作方法。书中大量对互联网创业成功人士的访谈介绍,以及创业公司的成功案例,更可以作为初次创业者的良好借鉴。
《互联网创业启示录》主要写给想自己创业的程序员,但同样适合非技术人员,适合网络创业者、大学生创业者、网络营销人员及一切有志创业者。做网络不一定要懂技术,互联网的成功是可以借鉴和延伸的!
程序员健康指南
本书是为程序员量身制作的健康指南,针对头痛、眼部疲劳、背部疼痛和手腕疼痛等常见的问题,简要介绍了其成因、测试方法,并列出了每天的行动计划,从运动、饮食等方面给出详细指导,帮助程序员在不改变工作方式的情况下轻松拥有健康。
本书适合程序员、长期伏案工作的其他人群以及所有关心健康的人士阅读。
结网@改变世界的互联网产品经理
本书以如何创建、发布、推广互联网产品为主线,介绍了互联网产品经理的工作内容以及应对每一部分工作所需的方法和工具。为用户创造价值是产品经理的第一要务,产品经理的工作是围绕用户及具体任务展开的,本书丰富的案例和透彻的分析道出了从发现用户到最终满足用户这一过程背后的玄机。
本书面向现在正在从事及未来将要从事互联网相关工作的创业者和产品经理,也可以作为互联网产品策划人员或相关专业学生的参考书。新版完善了各章节,增加了优雅降级等内容,读者也可从中更深地去感受一名产品经理的感悟。
程序员面试逻辑题解析
程序员面试逻辑题解析》共分为3个部分。第一部分从有趣且锻炼头脑的谜题入手,继而给出解题思路和详细答案,更有"热身问题"给大家提供充分的思考空间。第二部分综合了不同类型的谜题,如数独、调度问题及概率题等。神秘的第三部分带领大家不断历险,开动脑筋,解决大量密码及银行账户等方面的问题。几十道简洁的小谜题不仅充分锻炼了我们的思维方式,更为提高面试成功率奠定了基础。
《程序员面试逻辑题解析》不仅适合程序员阅读,更是谜题爱好者的饕餮盛宴。
程序员,你伤不起
本书是作者博客文章的精选集。是作者作为老牌程序员、现在的IT 创业者15 年软件开发生涯的心路历程和经验总结。涉及程序人生、开发经验、职业规划、创业心得。对任何的软件开发者和IT 从业人员都有借鉴价值。作者语言风趣幽默,读起来津津有味。字里行间充满了不屈不挠的码农正能量。
像程序员一样思考
编程的真正挑战不是学习一种语言的语法,而是学习创造性地解决问题,从而构建美妙的应用。《像程序员一样思考》分析了程序员解决问题的方法,并且教授你其他图书所忽略的一种能力,即如何像程序员一样思考。
全书分为8章。第1章通对几个经典的算法问题切入,概括了问题解决的基本技巧和步骤。第2章通过实际编写C++代码来解决几个简单的问题,从而让读者进一步体会到问题解决的思路和应用。第3到7章是书中的主体部分,分别探讨了用数组、指针和动态内存、类、递归和代码复用来解决问题的途径和实际应用。最后,第8章从培养程序员思维的角度,进行了总结和概括,告诉读者如何才能像程序员一样思考。
编写可读代码的艺术
细节决定成败,思路清晰、言简意赅的代码让程序员一目了然;而格式凌乱、拖沓冗长的代码让程序员一头雾水。除了可以正确运行以外,优秀的代码必须具备良好的可读性,编写的代码要使其他人能在最短的时间内理解才行。本书旨在强调代码对人的友好性和可读性。
本书关注编码的细节,总结了很多提高代码可读性的小技巧,看似都微不足道,但是对于整个软件系统的开发而言,它们与宏观的架构决策、设计思想、指导原则同样重要。编码不仅仅只是一种技术,也是一门艺术,编写可读性高的代码尤其如此。如果你要成为一位优秀的程序员,要想开发出高质量的软件系统,必须从细处着手,做到内外兼修,本书将为你提供有效的指导。
分析函数是什么?
分析函数是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;
运行结果:
摘要: 三、常见分析函数详解为了方便进行实践,特将演示表和数据罗列如下:一、创建表create table t( bill_month varchar2(12) , area_code number, net_type varchar(2), local_fare number ); 二、插入数据insert i...
阅读全文
这个系列我将整理一些日常我们经常使用到的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 选项在此函数中禁用。
----------------------------------------------------------------------------------------------
在使用PHP时,我们需要将自己写好的php文件上传到已申请的php空间。由于租用或申请的php空间是不允许用户进行配置的,那么对于php的一些功能是否开启,如curl, allow_url_fopen, gzip,就需要提前判断,而不是等写完代码后发现不能使用时,那样改动就大了。
方法/步骤
其实判断功能是否开启,很简单,我们只需要写一个php文件上传之php空间服务器中。v.php的源代码如图。
其含义很简单,就是传入一个函数的名字,服务器判断是否存在这个函数,如果存在则表示支持该函数对应的功能,输出“支持”,反之输出“不支持”。将文件上传至php空间中。
再通过访问空间,地址+v.php?f=+要测试的功能所包括的函数,比如curl功能可以是v.php?f=curl_init,allow_url_fopen功能可以用v.php?f=fopen来测试。
在技术方面无论我们怎么学习,总感觉需要提升自已不知道自己处于什么水平了。但如果有清晰的指示图供参考还是非常不错的,这样我们清楚的知道我们大概处于那个阶段和水平。
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
摘要: ajax+json+Struts2实现list传递(转载)一、首先需要下载JSON依赖的jar包。它主要是依赖如下: json-lib-2.2.2-jdk15 ezmorph-1.0.4 commons-logging-1.0.4&nbs...
阅读全文
摘要: Batis 简介:iBatis 是apache 的一个开源项目,一个O/R Mapping 解决方案,iBatis 最大的特点就是小巧,上手很快。如果不需要太多复杂的功能,iBatis 是能够满足你的要求又足够灵活的最简单的解决方案,现在的iBatis 已经改名为Mybatis 了。官网为:http://www.myb...
阅读全文