javascript代码

var area={11:"北京",12:"天津",13:"河北",14:"山西",15:"内蒙古",21:"辽宁",22:"吉林",23:"黑龙江",31:"上海",32:"江苏",33:"浙江",34:"安徽",35:"福建",36:"江西",37:"山东",41:"河南",42:"湖北",43:"湖南",44:"广东",45:"广西",46:"海南",50:"重庆",51:"四川",52:"贵州",53:"云南",54:"西藏",61:"陕西",62:"甘肃",63:"青海",64:"宁夏",65:"新疆",71:"台湾",81:"香港",82:"澳门",91:"国外"}

checkCard = function(){
    var card = document.getElementById('card_no').value;
    //是否为空
    if(card === ''){
        alert('请输入身份证号,身份证号不能为空');
        return false;
    }
    //校验长度,类型
    if(isCardNo(card) === false){
        alert('您输入的身份证号码不正确,请重新输入');
        return false;
    }
    //检查省份
    if(checkProvince(card) === false){
        alert('您输入的身份证号码不正确,请重新输入');
        return false;
    }
    //校验生日
    if(checkBirthday(card) === false){
        alert('您输入的身份证号码生日不正确,请重新输入');
        return false;
    }
    //检验位的检测
    if(checkParity(card) === false){
        alert('您的身份证校验位不正确,请重新输入');
        return false;
    }
    return true;//正确的身份证号
};

//检查号码是否符合规范,包括长度,类型
isCardNo = function(card){
    //身份证号码为15位或者18位,15位时全为数字,18位前17位为数字,最后一位是校验位,可能为数字或字符X
    var reg = /(^\d{15}$)|(^\d{17}(\d|X)$)/;
    if(reg.test(card) === false){
        return false;
    }
    return true;
};
//取身份证前两位,校验省份
checkProvince = function(card){
    var province = card.substr(0,2);
    if(area[province] == undefined){
        return false;
    }
    return true;
};
//检查生日是否正确
checkBirthday = function(card){
    var len = card.length;
    //身份证15位时,次序为省(3位)市(3位)年(2位)月(2位)日(2位)校验位(3位),皆为数字
    if(len == '15'){
        var re_fifteen = /^(\d{6})(\d{2})(\d{2})(\d{2})(\d{3})$/;
        var arr_data = card.match(re_fifteen);
        var year = arr_data[2];
        var month = arr_data[3];
        var day = arr_data[4];
        return verifyBirthday(len,'19'+year,month,day);
    }
    //身份证18位时,次序为省(3位)市(3位)年(4位)月(2位)日(2位)校验位(4位),校验位末尾可能为X
    if(len == '18'){
        var re_eighteen = /^(\d{6})(\d{4})(\d{2})(\d{2})(\d{3})([0-9]|X)$/;
        var arr_data = card.match(re_eighteen);
        var year = arr_data[2];
        var month = arr_data[3];
        var day = arr_data[4];
        return verifyBirthday(len,year,month,day);
    }
    return false;
};

//检查出生日期
verifyBirthday = function(idLen,year,month,day){
    var curr_year = new Date().getFullYear();
    var ereg='/^((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|1[0-9]|2[0-8]))$/';//平年出生月日的格式;

    if (parseInt(year) % 4 == 0 || (parseInt(year) % 100 == 0 && parseInt(year)% 4 == 0 )){
        ereg='/^((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))$/';//闰年出生月日的格式;
    }

    var time = curr_year - year;
    if(time > 0 && time <= 200){//合理的年龄范围
        var patt=new RegExp(ereg);
        return patt.test(month+day); //检查闰年和非闰年的日期是否正确
    }
    return false;
};

//校验位的检查
checkParity = function(card){
    var cardTemp = 0;
    var len = card.length;
    var arrInt = new Array(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2);
    var arrCh = new Array('1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2');
    if(len == '15'){
        card = card.substr(0, 6) + '19' + card.substr(6, card.length - 6);
    }
    for(var i = 0; i < 17; i ++){
        cardTemp += card.substr(i, 1) * arrInt[i];
    }
    var valnum = arrCh[cardTemp % 11];
    if (valnum == card.substr(17, 1)){
        return true;
    }
    return false;
};

参考资料

  1. 身份证号码编码规则

  2. 比较严格的JS身份证校验

连接池存放多个连接,连接具有指向数据库的信息,这些信息需要通过连接池配置数据源来实现

Tomcat配置连接池的方式

  • 方法一:在tomcat的目录conf下面的context.xml中,添加数据源的内容,该方式可用于所有项目,如下:
<Context>
    <WatchedResource>WEB-INF/web.xml</WatchedResource>
<!-- 添加数据源 -->
    <Resource name="jdbc/test" auth="Container" type="javax.sql.DataSource"
    maxActive="50" maxIdle="30" maxWait="10000" logAbandoned="true"
    username="root" password="111111" driverClassName="com.mysql.jdbc.Driver"
    url="jdbc:mysql://localhost:3306/testdb" />
</Context>
  • 方法二:在tomcat的目录conf下面的server.xml时,在context标签内添加数据源,该方式可用于指定项目,如下:
<Context path="/WebRoot" reloadable="true" docBase="E:/workspace/DataSource/WebRoot" >
    <Resource name="jdbc/test" auth="Container" type="javax.sql.DataSource"
    maxActive="50" maxIdle="30" maxWait="10000" logAbandoned="true"
    username="root" password="111111" driverClassName="com.mysql.jdbc.Driver"
    url="jdbc:mysql://localhost:3306/testdb" />
</Context>
  • 配置文件中Resource标签中各属性的含义:

driverClassName - JDBC 所用到的数据库驱动的类全名.

maxActive - 连接池在同一时刻内所提供的最大活动连接数。

maxIdle - 连接池在空闲时刻保持的最大连接数.

maxWait - 当发生异常时数据库等待的最大毫秒数 (当没有可用的连接时).

password - 连接数据库的密码.

url - 连接至驱动的URL. (为了向后兼容, DRIVERNAME也被允许.)

user - 数据库用户名.

各种配置方式的范围也应该是不一样的。我在这就不细说了,总之就是在Context标签下面配置个Resource标签即可。

  • 测试代码(java):
Context initContext = new InitialContext();
Context envContext  = (Context)initContext.lookup("Java:/comp/env");
DataSource ds = (DataSource)envContext.lookup("jdbc/test");
System.out.println(ds.getConnection());

打印出来的结果不是null应该就成功了。

注意,测试的时候要在tomcat内测试,也就是要在TOMCAT这个容器内(不要闲麻烦,写个简单的JSP页面测下,用个<%…%>就可以了,相当简单的)。不在tomcat这个容器里面测,会抛异常:

... javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file:  java.naming.factory.initial

Weblogic配置连接池的方式

Weblogic 10.3 控制台方式配置Oracle连接池

hibernate配置连接池的方式

  • 方式一:使用Hibernate自带的连接池(官方也只是建议仅在开发环境下使用),需要配置数据源
<hibernate-configuration>
<session-factory >
<!--JDBC驱动程序-->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<!-- 连接数据库的URL-->
<property name="connection.url">
jdbc:mysql://localhost:3306/feifei
</property>
<!--连接的登录名-->
<property name="connection.username">root</property>
<!--登录密码-->
<property name="connection.password"></property>
<!--是否将运行期生成的SQL输出到日志以供调试-->
<property name="show_sql">true</property>
<!--指定连接的语言-->
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<!--映射资源-->
<mapping resource="/xx/xx.hbm.xml" />
</session-factory>
</hibernate-configuration>
  • 方式二: 使用配置文件指定的数据库连接池。

连接池现在有dbcp、c3p0、proxool。但Hibernate3.0中,已经不再支持dbcp了,c3p0占用内存大且效率不高,proxool是目前比较好的方式

1.hibernate.cfg.xml中配置dbcp:

<!-- dbcp conf -->
<property name="dbcp.maxActive">100</property>
<property name="dbcp.whenExhaustedAction">1</property>
<property name="dbcp.maxWait">60000</property>
<property name="dbcp.maxIdle">10</property>
<property name="dbcp.ps.maxActive">100</property>
<property name="dbcp.ps.whenExhaustedAction">1</property>
<property name="dbcp.ps.maxWait">60000</property>
<property name="dbcp.ps.maxIdle">10</property>

2.hibernate.cfg.xml中配置c3p0:

<!-- c3p0 conf -->
<property name="c3p0.min_size">5</property>
<property name="c3p0.max_size">30</property>
<property name="c3p0.time_out">1800</property>
<property name="c3p0.max_statement">50</property>

3.配置Proxool:

添加配置文件ProxoolConf.xml,路径为根目录src下即与hibernate.cfg.xml同目录,配置如下:

<?xml version="1.0" encoding="utf-8"?>
<something-else-entirely>
<proxool>
<alias>dbpool</alias>
<!--proxool只能管理由自己产生的连接-->
<driver-url>
jdbc:mysql://localhost:3306/WebShop?user=root&amp;password=&amp;useUnicode=true&amp;characterEncoding=GB2312
</driver-url>
<driver-class>com.informix.jdbc.IfxDriver</driver-class>
<driver-properties>
<property name="user" value="informix" />
<property name="password" value="informix" />
</driver-properties>
<!-- proxool自动侦察各个连接状态的时间间隔(毫秒),侦察到空闲的连接就马上回收,超时的销毁-->
<house-keeping-sleep-time>90000</house-keeping-sleep-time>
<!-- 指因未有空闲连接可以分配而在队列中等候的最大请求数,超过这个请求数的用户连接就不会被接受-->
<maximum-new-connections>20</maximum-new-connections>
<!-- 最少保持的空闲连接数-->
<prototype-count>5</prototype-count>
<!-- 允许最大连接数,超过了这个连接,再有请求时,就排在队列中等候,最大的等待请求数由maximum-new-connections决定-->
<maximum-connection-count>100</maximum-connection-count>
<!-- 最小连接数-->
<minimum-connection-count>10</minimum-connection-count>
</proxool>
</something-else-entirely>

hibernate.cfg.xml中添加对proxool的支持的配置如下:

<property name="proxool.pool_alias">dbpool</property>
<property name="proxool.xml">ProxoolConf.xml</property>
<property name="connection.provider_class">org.hibernate.connection.ProxoolConnectionProvider</property>
  • 方式三: 从容器中获取得到连接池(如:Tomcat)

用服务器本身的连接池:如Tomcat、resin、weblogic等

hibernate.cfg.xml配置如下: jndi使用的是第一种Tomcat的配置方式,其中java:comp/env/jdbc/test的jdbc/test是对应的服务器中数据库连接池名字

<property name="hibernate.connection.datasource">
java:comp/env/jdbc/test
</property>
<property name="show_sql">true</property>
<property name="dialect">
org.hibernate.dialect.MySQLDialect
</property>
<property name="hibernate.generate_statistics">true</property>

spring配置连接池的方式

以下仅介绍了dbcp的配置方式,在spring配置文件中配置:

<bean id="dataSource"  class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
  <property name="driverClassName">
    <value>com.mysql.jdbc.Driver</value>
  </property>
  <property name="url">
    <value>jdbc:mysql://localhost:3306/dbname</value>
  </property>
  <property name="username">
     <value>root</value>
  </property>
  <property name="password">
     <value>******</value>
  </property>
  <property name="maxActive">
     <value>100</value>
  </property>
  <property name="maxWait">
     <value>1000</value>
  </property>
  <property name="maxIdle">
     <value>30</value>
  </property>
  <property name="defaultAutoCommit">
     <value>true</value>
  </property>
  <property name="removeAbandoned"> //自动回收连接池,避免连接池泄露
     <value>true</value>
  </property>
  <property name="removeAbandonedTimeout">
     <value>60</value>
  </property>
</bean>

侵入式代码配置连接池的方式

import  java.sql.*;
import  java.sql.DataSource;
import  org.apache.commons.dbcp.BasicDataSource;
public class ConnectionPool{
    private static BasicDataSource dbs = null;
    public static DataSource setupDataSource(){
        bds = new BasicDataSource();
        //设置驱动程序
        bds.sestDriverClassName("com.mysql.jdbc.Driver");
        //设置连接用户名
        bds.setUsername("root");
        //设置连接密码
        bds.setPassword("root");
        //设置连接地址
        bds.setUrl("jdbc:mysql://localhost:3306/databasename");
        //设置初始化连接总数
        bds.setInitialSize(50);
        //设置同时应用的连接总数
        bds.setMaxActive(-1);
        //设置在缓冲池的最大连接数
        bds.setMaxIdle(-1);
        //设置在缓冲池的最小连接数
        bds.setMinIdle(0);
        //设置最长的等待时间
        bds.setMaxWait(-1);
        return (DataSource)bds;
    }
    //显示连接池的连接个数的方法
    public static void printDataSourceStats(DataSource ds) throws SQLException{
        bds = (BasicDataSource)ds;
        System.out.println();
        System.out.println();
    }
     //关闭连接池的方法
     public static void shutdownDataSource(DataSource ds) throws SQLException{
         bds = (BasicDataSource)ds;
         bds.close();
     }
}

要获得连接池只许使用该类的静态方法setupDataSource()即可

参考资料

  1. Oracle WebLogic 10.3 连接池参数配置详解

  2. java数据库连接池配置的几种方法

  3. hibernate中配置proxool

浏览器缓存的基础

浏览器缓存会根据进来的请求保存输出内容的副本,例如html页面, 图片,文件(统称为副本),然后,当下一个请求来到的时候:如果是相同的URL,缓存直接使用副本响应访问请求,而不是向源服务器再次发送请求。一般都能在浏览器的设置对话框中发现关于缓存的设置,通过在你的电脑上僻处一块硬盘空间用于存储你已经看过的网站的副本。

  • 使用缓存主要有2大理由:
  1. 减少相应延迟:因为请求从缓存服务器(离客户端更近)而不是源服务器被相应,这个过程耗时更少,让web服务器看上去相应更快;
  2. 减少网络带宽消耗:当副本被重用时会减低客户端的带宽消耗;客户可以节省带宽费用,控制带宽的需求的增长并更易于管理。

浏览器缓存如何工作

所有的缓存都用一套规则来帮助他们决定什么时候使用缓存中的副本提供服务(假设有副本可用的情况下);一些规则在协议中有定义(HTTP协议1.0和1.1),一些规则由缓存的管理员设置(浏览器的用户或者代理服务器的管理员);

一般的规则如下:

  1. 如果响应头信息:告诉缓存器不要保留缓存,缓存器就不会缓存相应内容;

  2. 如果请求信息是需要认证或者安全加密的,相应内容也不会被缓存;

  3. 如果在响应中不存在校验器(ETag或者Last-Modified头信息),缓存服务器会认为缺乏直接的更新度信息,内容将会被认为不可缓存。

  4. 一个缓存的副本如果含有以下信息,则内容将会被认为是足够新的,不会请求服务器:

  • 含有完整的过期时间和寿命控制头信息,并且内容仍在保鲜期内;

  • 浏览器已经使用过缓存副本,并且在一个会话中已经检查过内容的新鲜度;

  • 缓存代理服务器近期内已经使用过缓存副本,并且内容的最后更新时间在上次使用期之前;

  • 够新的副本将直接从缓存中送出,而不会向源服务器发送请求;

5.如果缓存的副本已经太旧了,缓存服务器将向源服务器发出请求校验服务端原件的请求,用于确定是否可以继续使用当前拷贝继续服务;

浏览器请求与缓存的关系流程图

浏览器第一次请求:

浏览器第一次请求

浏览器再次请求时:

浏览器第二次请求

控制缓存方式

1.添加meta元信息

<META HTTP-EQUIV="Pragma" CONTENT="no-cache">
<META HTTP-EQUIV="Cache-Control" CONTENT="no-cache">
<META HTTP-EQUIV="Expires" CONTENT="0">

以上方式效率并不高,因为只有几种浏览器会遵循这个标记(那些真正会”读懂”HTML的浏览器),没有一种缓存代理服务器能遵循这个 规则(因为它们几乎完全不解析文档中HTML内容)

2.HTTP协议定义的缓存机制

  • Expires策略

Expires是Web服务器响应消息头字段,在响应http请求时告诉浏览器在过期时间前浏览器可以直接从浏览器缓存取数据,而无需再次请求。不过Expires 是HTTP 1.0的东西,现在默认浏览器均默认使用HTTP1.1,所以它的作用基本忽略。

  • Cache-control策略

Cache-Control与Expires的作用一致,都是指明当前资源的有效期,控制浏览器是否直接从浏览器缓存取数据还是重新发请求到服务器取数据。只不过Cache-Control的选择更多,设置更细致,如果同时设置的话,其优先级高于Expires。

3.HTML5的LocalStorage和sessionStorage

LocalStorage在PC上的兼容性不太好,而且当网络速度快、协商缓存响应快时使用localStorage的速度比不上304。并且不能缓存css文件。而移动端由于网速慢,使用localStorage要快于304

4.浏览器缓存的使用

  • ajax

方式一:用POST替代GET(不推荐):POST模式的返回内容不会被大部分缓存服务器保存,如果你发送内容通过URL和查询(通过GET模式)的内容可以缓存下来供以后使用;

方式二:使用HTTP协议定义的缓存机制

1、在ajax发送请求前加上

xmlHttpRequest.setRequestHeader("Cache-Control","no-cache");

或者

xmlHttpRequest.setRequestHeader("If-Modified-Since","0″);

2.jQuery里设置禁止缓存的方法:

<script type="text/javascript" language="JavaScript">
     $.ajaxSetup ({
           cache: false //close AJAX cache
      });
</script>

方式三:添加时间戳

URL 参数后加上 "?timestamp=" + new Date().getTime();

  • js文件

1.添加时间戳

<script type="text/javascript" src="/js/common.js" ></script>

在后面加一个时间戳来解决。这样url地址每次变化,浏览器就会请求服务端的js,而不会使用缓存

2.添加版本号

 <script type="text/javascript" src="js/common.js?t=20150622" ></script>

如果下一次修改了这个js文件,那么发布的时候,就修改日期,这样做到了程序员自己控制的办法

<script type="text/javascript" src="js/common.js?t=20150628" ></script>

参考资料

  1. 浏览器缓存机制

  2. Ajax页面缓存问题分析与解决办法