Monthly Archive: June, 2016

SQL SERVER 数据类型

数据类型 类型 描述
bit 整型 bit 数据类型是整型,其值只能是0、1或空值。这种数据类型用于存储只有两种可能值的数据,如Yes或No、True 或False 、On或Off
int 整型 int 数据类型可以存储从-231(-2147483648)到231(2147483647)之间的整数。存储到数据库的几乎所有数值型的数据都可以用这种数据类型。这种数据类型在数据库里占用4个字节
smallint 整型 smallint 数据类型可以存储从-215(-32768)到215(32767)之间的整数。这种数据类型对存储一些常限定在特定范围内的数值型数据非常有用。这种数据类型在数据库里占用2 字节空间
tinyint 整型 tinyint 数据类型能存储从0到255之间的整数。它在你只打算存储有限数目的数值时很有用。 这种数据类型在数据库中占用1个字节
numeric 精确数值型 numeric数据类型与decimal 型相同
decimal 精确数值型 decimal 数据类型能用来存储从-1038-1到1038
-1的固定精度和范围的数值型数据。使用这种数据类型时,必须指定范围和精度。 范围是小数点左右所能存储的数字的总位数。精度是小数点右边存储的数字的位数
money 货币型 money 数据类型用来表示钱和货币值。这种数据类型能存储从-9220亿到9220亿之间的数据,精确到货币单位的万分之一
smallmoney 货币型 smallmoney 数据类型用来表示钱和货币值。这种数据类型能存储从-214748.3648 到214748.3647之间的数据,精确到货币单位的万分之一
float 近似数值型 float 数据类型是一种近似数值类型,供浮点数使用。说浮点数是近似的,是因为在其范围内不是所有的数都能精确表示。浮点数可以是从-1.79E+308到1.79E+308 之间的任意数
real 近似数值型 real 数据类型像浮点数一样,是近似数值类型。它可以表示数值在-3.40E+38到3.40E+38之间的浮点数
datetime 日期时间型 datetime数据类型用来表示日期和时间。这种数据类型存储从1753年1月1日到9999年12月3 1日间所有的日期和时间数据, 精确到三百分之一秒或3.33毫秒
Smalldatetime 日期时间型 smalldatetime 数据类型用来表示从1900年1月1日到2079年6月6日间的日期和时间,精确到一分钟
cursor 特殊数据型 cursor 数据类型是一种特殊的数据类型,它包含一个对游标的引用。这种数据类型用在存储过程中,而且创建表时不能用
timestamp 特殊数据型 timestamp 数据类型是一种特殊的数据类型,用来创建一个数据库范围内的唯一数码。 一个表中只能有一个timestamp列。每次插入或修改一行时,timestamp列的值都会改变。尽管它的名字中有“time”, 但timestamp列不是人们可识别的日期。在一个数据库里,timestamp值是唯一的
Uniqueidentifier 特殊数据型 Uniqueidentifier数据类型用来存储一个全局唯一标识符,即GUID。GUID确实是全局唯一的。这个数几乎没有机会在另一个系统中被重建。可以使用NEWID 函数或转换一个字符串为唯一标识符来初始化具有唯一标识符的列
char 字符型 char数据类型用来存储指定长度的定长非统一编码型的数据。当定义一列为此类型时,你必须指定列长。当你总能知道要存储的数据的长度时,此数据类型很有用。例如,当你按邮政编码加4个字符格式来存储数据时,你知道总要用到10个字符。此数据类型的列宽最大为8000个字符
varchar 字符型 varchar数据类型,同char类型一样,用来存储非统一编码型字符数据。与char 型不一样,此数据类型为变长。当定义一列为该数据类型时,你要指定该列的最大长度。 它与char数据类型最大的区别是,存储的长度不是列长,而是数据的长度
text 字符型 text 数据类型用来存储大量的非统一编码型字符数据。这种数据类型最多可以有231-1或20亿个字符
nchar 统一编码字符型 nchar 数据类型用来存储定长统一编码字符型数据。统一编码用双字节结构来存储每个字符,而不是用单字节(普通文本中的情况)。它允许大量的扩展字符。此数据类型能存储4000种字符,使用的字节空间上增加了一倍
nvarchar 统一编码字符型 nvarchar 数据类型用作变长的统一编码字符型数据。此数据类型能存储4000种字符,使用的字节空间增加了一倍
ntext 统一编码字符型 ntext 数据类型用来存储大量的统一编码字符型数据。这种数据类型能存储230-1或将近10亿个字符,且使用的字节空间增加了一倍
binary 二进制数据类型 binary数据类型用来存储可达8000 字节长的定长的二进制数据。当输入表的内容接近相同的长度时,你应该使用这种数据类型
varbinary 二进制数据类型 varbinary 数据类型用来存储可达8000 字节长的变长的二进制数据。当输入表的内容大小可变时,你应该使用这种数据类型
image 二进制数据类型 image 数据类型用来存储变长的二进制数据,最大可达231-1或大约20亿字节

PowerDesigner 设计数据库表

软件

第一步:概念数据模型

打开PowerDesigner 软件,设计“概念数据模型”(Conceptual Data Model),它通常用在概要设计阶段。

设计表结构

注意:如果Palette(工具面板)没有显示,可以在工具栏 --> 右键 --> 选择“Palette”(打勾选中)

设计结果如下:

在设计属性(字段)的时候,三个字母(M、P、D)分别表示:

  • M:是否为空;(√表示不允许为空)
  • P:是否为主键;
  • D:是否在该软件的视图中显示;

添加 “Relationship” 关系时,请注意:

  1. 在所有实体对象中,属性的取名不能重复。
  2.  当添加引用完整性时,外键表不必添加主键表的主键字段作为外键。因为,在添加“Relationship”关系 之后,再转换为物理模型以后,外键表将自动添加外键字段列。
  3. 在添加 “Relationship” 关系时,起始点实体默认为主键表,结束点实体默认为外键表。当然,可以在 “Relationship” 中改变。

Read more

Win10 Hyper-V 内部网络联网设置

windows的Hyper-V简直就是操蛋中的极品。网络设置超级不人性化。

如果计算机没有连接路由器的情况下,使用默认的任何一种设置都无法正常与虚拟机连接。

这个问题折腾了好久。记录一下。

1.在Hyper-v管理器中,新建“虚拟交换机”,类型选“内部网络”

2.打开“网络和共享中心”,选中刚才建立的虚拟网卡及WIFI,右击,点“桥接”

3.等待生效

4.设置虚拟机网卡

这种方法好处在于没有网络的情况下也能与虚拟机互通,在有网络的情况下也是一样的!!!!!!

结束!

建行在线支付开发 ——服务端验签

package util.payment;
 
import java.io.IOException;
import java.sql.Date;
import java.text.ParseException;
import java.text.SimpleDateFormat;
 
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
 
import CCBSign.RSASig;
import domain.PayInfor;
import service.IPayInfoService;
import service.impl.PayInfoServiceImpl;
 
/**
 * 缴费处理 服务器端
 * 
 * @author jalena
 */
@WebServlet(urlPatterns = "/confirm/service")
public class PaymentServiceServlet extends HttpServlet {
 
	private static final long serialVersionUID = 578565845005319427L;
	private static RSASig rsaSig = new RSASig();
	private IPayInfoService service = new PayInfoServiceImpl();
	private Logger logger = LogManager.getLogger(this.getClass().getName());
	private SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
	private PayInfor payInfor = null;
 
	static {
		// 设置验签程序公钥
		rsaSig.setPublicKey("银行提供的公钥");
	}
 
	public PaymentServiceServlet() {
		super();
	}
 
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		this.doPost(request, response);
	}
 
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
 
		// 以下为建行返回字串
		String posid = request.getParameter("POSID"); // 商户柜台代码
		String branchid = request.getParameter("BRANCHID"); // 分行代码
		String orderid = request.getParameter("ORDERID"); // 定单号
		String payment = request.getParameter("PAYMENT"); // 付款金额
		String curcode = request.getParameter("CURCODE"); // 币种
		String remark1 = request.getParameter("REMARK1"); // 备注一
		String remark2 = request.getParameter("REMARK2"); // 备注二
		String success = request.getParameter("SUCCESS");	 // 成功标志 成功-Y,失败-N
		String type = request.getParameter("TYPE"); 		// 接口类型 1- 防钓鱼接口
		String referer = request.getParameter("REFERER"); // Referer信息
		String clientip = request.getParameter("CLIENTIP"); // 客户端IP
		String accdate = request.getParameter("ACCDATE"); // 系统记账日期 20160801
		String sign = request.getParameter("SIGN"); // 数字签名
		String acc_type = request.getParameter("ACC_TYPE"); // 账户类型 仅服务器通知中有此字段,页面通知无此字段
		// String usrmsg = request.getParameter("USRMSG"); // 支付账户信息 暂不返回内容
 
		// POSID=000000000&BRANCHID=110000000&ORDERID=19991101234&PAYMENT=500.00&CURCODE=01&REMARK1=&REMARK2=&ACC_TYPE=12&SUCCESS=Y&TYPE=1&REFERER=http://www.ccb.com/index.jsp&CLIENTIP=172.0.0.1&ACCDATE=20100907
 
		String src = "POSID=" + posid + "&BRANCHID=" + branchid + "&ORDERID=" + orderid + "&PAYMENT=" + payment + "&CURCODE=" + curcode + "&REMARK1=" + remark1 + "&REMARK2=" + remark2 + "&ACC_TYPE=" + acc_type
				+ "&SUCCESS=" + success + "&TYPE=" + type + "&REFERER=" + referer + "&CLIENTIP=" + clientip + "&ACCDATE=" + accdate;
 
		// 验签
		boolean signResulet = rsaSig.verifySigature(sign, src);
 
		// 时间格式转换
		java.util.Date date = null;
 
		try {
			if (accdate != null && !accdate.isEmpty()) {
				date = sdf.parse(accdate);
			}
		} catch (ParseException e) {
			e.printStackTrace();
		}
 
		if (signResulet) {
 
			payInfor = service.findBySerialNumber(orderid);
 
			// 修改数据库
			if (success.equals("Y") || payment.equals(String.valueOf(payInfor.getTotalPayable())) || orderid.equals(payInfor.getSerialNumber())) {
				service.update(orderid, new Date(date.getTime()), Double.parseDouble(payment));
			}
		} else {
			logger.warn("非法请求:" + orderid);
		}
 
	}
 
}

验签DEMO

/**
 * 接下来是一些成功的签名验证  
 */
//1 
strSrc="POSID=000000000&BRANCHID=330000000&ORDERID=2004010061&PAYMENT=0.01&CURCODE=01&REMARK1=&REMARK2=&SUCCESS=N"; 
strSign="5bf88c409a13963286904e8954a4d825108f9b5bb60a8c8e5cfc05355fe4e247c777b521c7d68b8d51968285d51d1a0da0c5bd55e19268949a20dd7bd14f17422e41f3e6f7446d2136e10e796abc8b8a6f752bed5091374551d84d02f185aa3f9b516ac77ca319b06a8269389de6d7f677c619bfc0c89ccbcb125ae6dd7cc646"; 
strPubKey="30819c300d06092a864886f70d010101050003818a003081860281807d1e98e9c10625239ad9116488accf18a95125c83f5ac52f055be47614087b1bc55f1d475ddb0516b6339f7c2a8fd4def86519087cc6ecd8ea4657a5cef26d84890d00772d216e95d0aba1ea9fd39fb02202c82b71333b104e715da5de65be4cf5b83e3c0ba459777fe83a39485f145fccc94b471981348db5beab735c5889f1020111"; 
rsa.setPublicKey(strPubKey); 
if( rsa.verifySigature( strSign,strSrc) ){ 
		System.out.println("Sign OK"); 
} 
else{ 
		System.out.println("Sign failed"); 
} 
 
//2 
strSrc="POSID=000000000&BRANCHID=110000000&ORDERID=20041031&PAYMENT=0.01&CURCODE=01&REMARK1=ccb&REMARK2=test&SUCCESS=Y"; 
strSign="43680d00f5097caae18b7af3fc936cc79feb621fb166e25affbb52721e2c5c1e656f030dff46e6f0298ef82cf2fd10b6cef34fb2aa270716c30708aeb1abf0520418449614562e891cd5aede8f83b1dd65f76cc81ad5aabfd4aba409da3523ef8e82a7d19055dbb6d9241171893bf282bf64f239677ecd84abbe55fd855f48f3"; 
strPubKey="30819f300d06092a864886f70d010101050003818d0030818902818100b466e3a0fa097b57a1bc63c1fd5d97d4ef8d270d538a5aee3d1061f579f02a19cf1543701d94d81f46ce56adb84dca440a7e8f5af40538bb7a88efaf9991ead0fabc63d48fd1f12de658229e30e38ccbd9a631ec9c2d95b8590ea1a01d0931221e062544023a1ed2eb7050853fe56bf8cfd0f18243192d38855a36a87badba790203010001"; 
rsa.setPublicKey(strPubKey); 
if( rsa.verifySigature( strSign,strSrc) ){ 
		System.out.println("Sign OK"); 
} 
else{ 
		System.out.println("Sign failed"); 
} 
 
//3 
strSrc="POSID=000000000&BRANCHID=110000000&ORDERID=20041031&PAYMENT=0.01&CURCODE=01&REMARK1=ccb&REMARK2=test&SUCCESS=Y"; 
strSign="3183a60f887937846008f4ecfea725af5d65ecaefebea828459193343df7d0943f0fa9e44a298cc9a8e335bece72f8bfce8da3975e21fe4ce4d6c96894d5428e05e896b7da03f7519551b8a09bf1286ea48975b3cd49978eefbb628cc98f4f064feb898518dfb783acdd25eb6f5507fc00c16d1ae69d801a8cb970c4b7e0959b"; 
strPubKey="30819f300d06092a864886f70d010101050003818d0030818902818100d0e57a2ebbc82801980de2ad7101c67dc137432bb6ced45882b8d41cbfec7519ae8bf18b2584ae460d7d437aec069ec907935e4b39c72a6291e43a6a88c3405565357dc23c46b7072e6e50b1da4cd9cfdec616cb6ad43f0b013040307973d63b889e78fdd1389714adec663acefe5c974e513a063ba9acb96f590139b0fc571b0203010001"; 
rsa.setPublicKey(strPubKey); 
if( rsa.verifySigature( strSign,strSrc) ){ 
		System.out.println("Sign OK"); 
} 
else{ 
		System.out.println("Sign failed"); 
} 
 
/**
 * 接下来是一些错误的验签 
 */
//1 
strSrc="POSID=000000000&BRANCHID=330000000&ORDERID=120040915091516271800047&PAYMENT=0.01&CURCODE=01&REMARK1=&REMARK2=&SUCCESS=Y"; 
strSign="2732e323aa1d4f460bed516a79944001fbad2c93bbdb0d22c71066f4a69528c8699da27c13893bfcefea14dabb6f3cfa93e1414e8782124c99ffc8b059aad5f7f543993f28d262147b5206aea8d2b72aa34a256a4a5bb9c90c9aa8d2897eae90b581e7e6091fcfbb7f4885711b75b95ba7982f7519dc166e20d8b8294e4af2ad"; 
strPubKey="30819c300d06092a864886f70d010101050003818a003081860281807e4caba7c0ff9f593bb03ac8e64fcc76ebdf728b3b54493c3f62c7c94e8663d8505da39b08b00df4320c5a49d54c7774044fcc42937a0fb6a3706f724f872fe5f998cc48eb20875902b4b935e14df77b7aeb9224a5cf2db765b20fe56d8f4d5a9e03ab7943a41a179f8240e5311b3957971921fe9ccb9c24c828e99f91cc33f1020111"; 
rsa.setPublicKey(strPubKey); 
if( rsa.verifySigature( strSign,strSrc) ){ 
		System.out.println("Sign OK"); 
} 
else{ 
		System.out.println("Sign failed"); 
}

 

java读写Properties属性文件

Java中有个比较重要的类Properties(Java.util.Properties),主要用于读取Java的配置文件,各种语言都有自己所支持的配置文件,配置文件中很多变量是经常改变的,这样做也是为了方便用户,让用户能够脱离程序本身去修改相关的变量设置。像Python支持的配置文件是.ini文件,同样,它也有自己读取配置文件的类ConfigParse,方便程序员或用户通过该类的方法来修改.ini配置文件。在Java中,其配置文件常为.properties文件,格式为文本文件,文件的内容的格式是“键=值”的格式,文本注释信息可以用"#"来注释。

它提供了几个主要的方法:

  1. getProperty ( String key),用指定的键在此属性列表中搜索属性。也就是通过参数 key ,得到 key 所对应的 value。
  2. load ( InputStream inStream),从输入流中读取属性列表(键和元素对)。通过对指定的文件(比如说上面的 test.properties 文件)进行装载来获取该文件中的所有键 - 值对。以供 getProperty ( String key) 来搜索。
  3. setProperty ( String key, String value) ,调用 Hashtable 的方法 put 。他通过调用基类的put方法来设置 键 - 值对。
  4. store ( OutputStream out, String comments),以适合使用 load 方法加载到 Properties 表中的格式,将此 Properties 表中的属性列表(键和元素对)写入输出流。与 load 方法相反,该方法将键 - 值对写入到指定的文件中去。
  5. clear (),清除所有装载的 键 - 值对。该方法在基类中提供。
package clibrary;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

public class PropertiesUtil {
	private static Logger logger = LoggerFactory.getLogger(PropertiesUtil.class);

	/**
	 * 读取配置文件某属性
	 */
	public String readValue(String filePath, String key) {
		Properties props = new Properties();

		if (!filePath.startsWith("/")) {
			filePath = "/" + filePath;
		}

		try {
			InputStream inputStream = this.getClass().getResourceAsStream(filePath);
			props.load(inputStream);
		} catch (NullPointerException e) {
			logger.warn("文件不存在!");
		} catch (IOException e) {
			logger.warn(e.getMessage() + "文件流错误");
		}

		return props.getProperty(key);

	}

	/**
	 * 打印配置文件全部内容(filePath,配置文件名,如果有路径,props/test.properties)
	 */
	public void readProperties(String filePath) {
		Properties props = new Properties();
		try {
			// 注意路径以 / 开始,没有则处理
			if (!filePath.startsWith("/"))
				filePath = "/" + filePath;
			InputStream in = this.getClass().getResourceAsStream(filePath);
			props.load(in);

			props.forEach((key, value) -> logger.debug("Key = {}, Value = {}", key, value));

		} catch (Exception e) {
			logger.error(e.getMessage());
		}
	}

	/**
	 * 将值写入配置文件
	 */
	public void writeProperties(String fileName, String parameterName, String parameterValue) {
		if (!fileName.startsWith("/"))
			fileName = "/" + fileName;
		FileOutputStream outputStream = null;
		Properties pps = new Properties();

		try {
			pps.load(this.getClass().getResourceAsStream(fileName));

			pps.setProperty(parameterName, parameterValue);
			outputStream = new FileOutputStream("src/main/resources/jdbc.properties");
			pps.store(outputStream, null);
		} catch (IOException e) {
			logger.warn(e.getMessage());
		} finally {
			if (outputStream != null) {
				try {
					outputStream.close();
				} catch (IOException e) {
					e.getMessage();
				}
			}
		}
	}
}

测试类

package clibrary;

import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.time.LocalDateTime;
import java.time.LocalTime;

import static org.junit.Assert.*;

public class PropertiesUtilTest {

	private Logger logger = LoggerFactory.getLogger(getClass());
	PropertiesUtil propertiesUtil = null;

	@Before
	public void init(){
		propertiesUtil = new PropertiesUtil();
	}

	@Test
	public void testReadValue(){
		String minIdle = propertiesUtil.readValue("jdbc.properties", "minIdle");
		assertEquals("5",minIdle);
		logger.debug(minIdle);
	}

	@Test
	public void testReadProperties(){
		propertiesUtil.readProperties("jdbc.properties");
	}

	@Test
	public void testWriteProperties(){
		propertiesUtil.writeProperties("jdbc.properties","Jalena","19");
	}

	@Test
	public void showTime(){
		logger.debug(LocalTime.now().toString());
		logger.debug(LocalDateTime.now().toString());
	}

}