2016年6月17日
2015年12月3日
过页头生成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,在需要的地方加上,或者直接设为全局拦截器都是可以的,简单,快捷;
2015年11月19日
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
(建议在凯发k8网页登录官网上下载,在安装目录下有jython.jar, 这里也有,但是这个包里没有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运行时处理的内容)
2015年10月30日
这两天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
[: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引用不对。后来就没有具体找原因了。
2015年8月9日
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';
2015年6月13日
做为一名程序员,如果你只顾得写代码,那是不行的,要抽出一下时间来丰富自己的知识,多看看书,在这里我将为程序员们推荐一些不错的书。能够给程序员们带来帮助。
大数据时代
《大数据时代》是国外大数据研究的先河之作,本书作者维克托•迈尔•舍恩伯格被誉为"大数据商业应用第一人",拥有在哈佛大学、牛津大学、耶鲁大学和新加坡国立大学等多个互联网研究重镇任教的经历,早在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章从培养程序员思维的角度,进行了总结和概括,告诉读者如何才能像程序员一样思考。
编写可读代码的艺术
细节决定成败,思路清晰、言简意赅的代码让程序员一目了然;而格式凌乱、拖沓冗长的代码让程序员一头雾水。除了可以正确运行以外,优秀的代码必须具备良好的可读性,编写的代码要使其他人能在最短的时间内理解才行。本书旨在强调代码对人的友好性和可读性。
本书关注编码的细节,总结了很多提高代码可读性的小技巧,看似都微不足道,但是对于整个软件系统的开发而言,它们与宏观的架构决策、设计思想、指导原则同样重要。编码不仅仅只是一种技术,也是一门艺术,编写可读性高的代码尤其如此。如果你要成为一位优秀的程序员,要想开发出高质量的软件系统,必须从细处着手,做到内外兼修,本书将为你提供有效的指导。
2015年5月13日
分析函数是什么?
分析函数是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 选项在此函数中禁用。
----------------------------------------------------------------------------------------------
2015年4月22日
在使用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来测试。