临时的实验课记录+研究的代码+计算机文档目录管理

 

http://yananay.iteye.com/blog/2220729  2017-12-6

 

教师ftp地址, 打开“计算机”,输入地址 ftp:/10.10.2.10 ,即可登录。


http://blog.csdn.net/lifetragedy/article/details/7698555

 

ftp://10.10.8.10


http://www.cnblogs.com/xuehanlee/p/4609519.html


http://blog.csdn.net/caolaosanahnu/article/details/21528173

<role rolename="admin"/>

  <role rolename="manager"/>

  <user username="admin" password="admin" roles="admin,manager"/>

3:启动tomat6,输入:用户名:admin 密码:admin 登陆到管理员界面。

 


<!--新添加的内容:
-->
<role rolename="manager-gui"/>  
<role rolename="manager-script"/>  
<role rolename="manager-jmx"/>
<role rolename="manager-status"/>
<user username="admin" password="123" roles="manager-gui,manager-script,manager-jmx,manager-status"/>


 在web.xml中,我们可以通过 <security-role>把我们定义的角色告诉web应用。
    <security-role> 
        <role-name>member</role-name> 
      </security-role> 
       
     <security-role> 
         <role-name>guest</role-name> 
     </security-role> 


例如现在我们要对url为/TestSafeLogin的servlet进行认证和授权,可以这么声明
<security-constraint> 
      <web-resource-collection> 
         <web-resource-name>demo</web-resource-name> 
         <url-pattern>/TestSafeLogin</url-pattern> 
         <http-method>GET</http-method> 
          <http-method>POST</http-method> 
      </web-resource-collection> 
      <auth-constraint> 
        <role-name>member</role-name> 
      </auth-constraint> 
      <user-data-constraint> 
          <transport-guarantee>CONFIDENTIAL</transport-guarantee> 
      </user-data-constraint> 
  </security-constraint>

 

 

<auth-constraint>
             <role-name>member</role-name>
      </auth-constraint> 表示只有会员这个角色才能查看。

       <user-data-constraint>
            <transport-guarantee>CONFIDENTIAL</transport-guarantee>
      </user-data-constraint>表示传输用户名和密码的时候,利用https协议进行加密传输。


 可是当我们访问了这个资源后,容器利用什么方式要求用户输入用户名和密码呢?

    这里有四种认证方式:

    1:基本认证(采用base64编码)

    2:摘要(digest)认证

    3:客户证书(client-cert)是以一种非常安全的形式进行传输登录信息,使用了公共密钥证书,缺点是客户必须有证书才能登录你的系统。

    4:表单认证(form),可以根据合法的html建立登录表单,四种认证中,表单认证是最不安全的。

    下面我们以表单认证来演示我们的例子。在web.xml中配置
<login-config> 
    <auth-method>FORM</auth-method> 
    <form-login-config> 
       <form-login-page>/login.html</form-login-page> 
       <form-error-page>/loginerror.html</form-error-page> 
    </form-login-config> 
</login-config>

 表示需要客户输入用户名和密码的时候,跳转到login.html,当输入错误的时候跳转到loginerror.html,并且以表单的方式提交。

 

 


http://developer.51cto.com/art/200907/133827.htm
http://www.cnblogs.com/gw811/archive/2012/09/07/2674859.html

使用 synchronized 保证Servlet的同步。

12345678910111213141516171819202122232425262728293031323334353637 public class HelloServlet extends HttpServlet {
          
    int i = 0;
    int ticket = 2;
          
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
              
        //i++;
        //out.println("jump to others " + "i = " + i);
              
        //模拟卖票
        synchronized (this) {
            if(ticket > 0){
                System.out.println("你买到票");
                out.println("you get it!");
                //休眠
                try {
                    Thread.sleep(10 * 1000);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                ticket--;
            }else{
                System.out.println("你没有买到票");
                out.print("you do not get it!");
            }
    }
}
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
    }
}

在Serlet中避免使用实例变量是保证Servlet线程安全的最佳选择。
从Java 内存模型也可以知道,方法中的临时变量是在栈上分配空间,而且每个线程都有自己私有的栈空间,所以它们不会影响线程的安全。


我们知道,一个 Servlet 对应一个 Servlet 实例,也就是说 Servlet 是单例的,
那么就有可能会出现一个 Servlet 同时处理多个不同的请求,
这时就可能会出现线程不安全问题。
如何防止出现线程安全问题,有以下三种方法:
? 不要在 Servlet 中创建成员变量,可以创建局部变量;
? 如果要创建成员变量,必须保证是无状态的成员变量;
? 如果创建的有状态的成员变量,状态必须是只读的。

 

http://bbs.51cto.com/thread-1011408-1.html  好的
http://bbs.51cto.com/thread-1011408-1.html

http://blog.csdn.net/superbeck/article/details/4292969   牛逼  jsP性能优化
http://jishu.admin5.com/jishu/150406/6969.html

最小化servlet中的java 同步。

不要用servlet的单线程模式。

使用servlet的init()方法进行一些昂贵的一次性的初始化。

避免使用system.out.pintln()调用。

避免使用共享的可修改的类变量

在servlet的多线程模式中(缺省情况下),一个应用服务器实例只有一个的servlet实例,这个servlet的所有请求都共享同一个 servlet实例,如果在servlet内有同步代码块的话会造成线程争夺,因为servlet的类变量创建需要同步,所以要避免使用共享的可修改的类 变量。

http session处理

使用http session的时候请遵守一下规则:

不要随意创建session, session的创建不是免费的。如果不需要就不要创建

如果session不需要了请使用javax.servlet.http.httpsession.invalidate()来释放session

保证session小型化可以减少反应时间,如果可能的话,请保证session小于7k。

在jsp里面使用<%page session=”false”%>指令来避免应用服务器自动在不需要的时候创建session.

避免session中存放大的对象,这样会强制序列化和增加过度计算,通常情况下不要存放大的对象到session里面。

不要缓存事务数据到httpsession里面,访问httpsession里面的数据是非事务的,最好把这些数据存放在数据库或者用实体 bean访问,事务如果失败会恢复到它原来的状态,不过,这些失效的或者不再精确的数据会继续存放在session里面。应用服务器提供了只读的bean 管理器去缓存这些只读的数据。

配置和部署技巧

为了提高类的载入时间,避免在服务器的classpath里面使用过多的目录,把跟应用有关的类发放到jar文件里面。

http反应时间跟http server调整有很大关系。

如果可能,请缓存servlet的结果。

如果一个应用不含任何jeb,把应用部署成war文件,不要部署成ear文件。

禁用security manager

security manager是非常昂贵的,因为在调用需要的资源的时候必须要调用doprivileged()方法而且还必须要检测server.policy里面的 资源。如果你确信你的服务器没有恶意的代码而且你也不使用用户认证,你就可以禁用secrity manager.

 

 


http://www.panduoduo.net/s/name/java%20web%20%E5%AE%89%E5%85%A8


http://www.panduoduo.net/s/name/servlet%20%20%E5%AE%89%E5%85%A8      servlet  安全

 

http://down.51cto.com/search.php?q=servlet%E8%A7%84%E8%8C%83&m=&f=_all&s=&t=&c=&p=2


http://blog.csdn.net/dyllove98/article/details/9795723

 

http://bbs.csdn.net/topics/390541172


http://blog.knowsky.com/192148.htm

https://zhidao.baidu.com/question/555076936.html

 

http://www.cnblogs.com/tobecrazy/p/3486347.html


http://www.cnblogs.com/hsapphire/archive/2010/05/21/1740942.html


http://blog.sina.com.cn/s/blog_6a14f6ac0100lu1e.html


http://blog.sina.com.cn/s/blog_a4aae83a01014cw9.html


http://blog.csdn.net/u014482758/article/details/40453623  限制访问web


http://developer.51cto.com/art/201411/456219.htm java 缓存cache

http://blog.csdn.net/tianyijavaoracle/article/details/41808077
http://www.cnblogs.com/wang-meng/p/6130471.html
http://blog.csdn.net/u012104435/article/details/50973918
http://www.open-open.com/lib/view/open1382318768355.html servlet缓存好的
http://www.open-open.com/lib/list/287
http://www.cnblogs.com/xiaoliao/p/5927536.html
http://blog.csdn.net/naruto_ahu/article/details/9007583
http://blog.csdn.net/naruto_ahu/article/details/9007583
http://www.jb51.net/article/104595.htm
http://blog.csdn.net/zhangpengju999/article/details/11603419
http://blog.csdn.net/l271640625/article/details/20528573  好的
http://happyqing.iteye.com/blog/1825478  好的
http://blog.csdn.net/houfeng30920/article/details/51435340
http://blog.csdn.net/ouyida3/article/details/44874051
http://blog.csdn.net/frankcheng5143/article/details/50776542
http://337027773.blog.163.com/blog/static/54376980201483105435711/
http://www.cnblogs.com/javaeye235/p/4569361.html  ehcache配置文档的说明
http://blog.csdn.net/frankcheng5143/article/details/50776542
http://blog.csdn.net/canot/article/details/51692293

 

 

http://blog.csdn.net/hezhipin610039/article/details/48299865
http://blog.csdn.net/luoyemyy/article/details/38297433
http://www.cnblogs.com/signheart/p/6595586.html
http://www.2cto.com/kf/201611/560922.html
http://blog.sina.com.cn/s/blog_46d5caa40100ka9z.html
http://www.cnblogs.com/fsjin/articles/3521261.html
http://www.cnblogs.com/alfily/p/4657226.html  缓存数据库案例
http://www.cnblogs.com/vigarbuaa/archive/2012/11/25/2788305.html  极好的
http://www.cnblogs.com/vigarbuaa/archive/2012/11/25/2788305.html
http://www.cnblogs.com/vigarbuaa/archive/2012/09/03/2668595.html
http://www.cnblogs.com/signheart/p/6595586.html

============
临时用的代码:cache

 

 

 

 

 


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

 

动态加载jar包
http://blog.csdn.net/wawmg/article/details/17961815

 

 

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

 

 

 

 


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

 

 

 

 


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

C:\Program Files\Java\jdk1.8.0_91\bin;C:\ProgramData\Oracle\Java\javapath;C:\Program Files\AMD APP\bin\x86;%SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem;%SYSTEMROOT%\System32\WindowsPowerShell\v1.0\;C:\Program Files\Intel\OpenCL SDK\2.0\bin\x86;C:\Program Files\ATI Technologies\ATI.ACE\Core-Static;c:\Program Files\Microsoft SQL Server\90\Tools\binn\;C:\Program Files\Autodesk\Backburner\;C:\Program Files\Common Files\Autodesk Shared\;C:\strawberry\c\bin;C:\strawberry\perl\bin;C:\Program Files\MySQL\MySQL Server 5.0\bin;%MAVEN_HOME\bin;%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin;%MAVEN_HOME%\bin;%CATALINA_HOME%\bin;
%CATALINA_HOME2%\bin

搭建集群系统:

简单的apache整合一个tomcat:
http://blog.csdn.net/lifuxiangcaohui/article/details/8558532
http://blog.csdn.net/stefyue/article/details/6918542

 


http://www.xuephp.com/main/detail.php?cid=40711
http://blog.csdn.net/zhanshenyn/article/details/6976861
http://blog.csdn.net/zhanshenyn/article/details/6955747
http://www.360doc.com/content/07/0316/10/7147_399333.shtml
http://michaelh0226.iteye.com/blog/1175561
http://www.sendong.com/news1663.html
http://michaelh0226.iteye.com/blog/1175561

http://blog.csdn.net/magang255/article/details/70171643
https://www.ibm.com/developerworks/cn/opensource/os-lo-apache-tomcat/
http://blog.csdn.net/johnstrive/article/details/4555198
http://blog.csdn.net/microsoft_love/article/details/52098213

E:\WebEvn\Apache\bin\httpd.exe" -k install -n apache


======================================
同一台电脑运行多个tomcat:  

指定2个tomcat服务器的环境变量(就是告诉系统他们的路径)
修改第2个服务器的配置文档中 新的路径
修改第2个服务器中的3个端口号,不要和前面的重复

http://blog.csdn.net/zyk906705975/article/details/8471475
http://blog.csdn.net/jiaotuwoaini/article/details/51455829
http://blog.csdn.net/qyf_5445/article/details/9042271
http://www.jb51.net/article/87449.htm

 

 

 

 

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

tomcat 服务器:性能学习

http://www.cnblogs.com/gugnv/archive/2012/02/01/2334187.html  servlet.xml配置文档说明 好的
http://blog.csdn.net/jinwanmeng/article/details/7756591
http://www.cnblogs.com/hyq0002013/p/6170074.html
http://www.importnew.com/17124.html
https://zhidao.baidu.com/question/1733110073200243267.html
http://blog.csdn.net/hll814/article/details/50935765


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

数据连接池


http://greemranqq.iteye.com/blog/1969273
http://blog.csdn.net/fangquan1980/article/details/52429903
http://blog.csdn.net/shijinupc/article/details/7836129
http://blog.csdn.net/tayanxunhua/article/details/10148983
http://blog.csdn.net/liminlimin_limin/article/details/41523117
http://blog.csdn.net/jrq/article/details/207579
http://www.cnblogs.com/xiaoduc-org/p/5371979.html
http://www.cnblogs.com/zydev/p/6114501.html
http://www.cnblogs.com/zydev/p/6114501.html
http://yaoy497.blog.sohu.com/54261944.html
http://www.cnblogs.com/shuaihua/p/3665840.html
http://greemranqq.iteye.com/blog/1969273

 


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

 


以下是  context对象的内容  cache的内容


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

 

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

import java.io.Serializable;

        import net.sf.ehcache.Cache;
        import net.sf.ehcache.CacheManager;
        import net.sf.ehcache.Element;

        public class Demo {
           
            static CacheManager manager= new CacheManager();

            /**
             *##############################################################################
             *
             * @DESCRIBE   
             * @param args
             * @throws InterruptedException
             *                        
             *##############################################################################
             */
            public static void main(String[] args) throws InterruptedException {
               
                String[] cacheNames = manager.getCacheNames();
                System.out.println("读取的缓存列表为:");
                for(int i=0;i<cacheNames.length;i++){
                    System.out.println("-- "+(i+1)+" "+cacheNames[i]);
                }
               
                Cache cache = manager.getCache("cache1");
                Element element = new Element("key1", "value1");
                cache.put(element);
               
                element = cache.get("key1");
                Serializable value = element.getValue();
                System.out.println("序列化后的值为:"+value.toString());

                element = cache.get("key1");
                Object value1 = element.getObjectValue();
                System.out.println("未序列化的值为:"+value1.toString());
               
                int elementsInMemory = cache.getSize();
                System.out.println("得到缓存的对象数量:"+elementsInMemory);
               
                long elementsInMemory1 = cache.getMemoryStoreSize();
                System.out.println("得到缓存对象占用内存的数量:"+elementsInMemory1);
               
                long elementsInMemory2 = cache.getDiskStoreSize();
                System.out.println("得到缓存对对象占用磁盘的数量:"+elementsInMemory2);       
               
                int hits = cache.getHitCount();
                System.out.println("得到缓存读取的命中次数:"+hits);       
               
                int hits1 = cache.getMemoryStoreHitCount();
                System.out.println("得到内存中缓存读取的命中次数:"+hits1);       
               
                int hits2 =cache.getDiskStoreHitCount();
                System.out.println("得到磁盘中缓存读取的命中次数:"+hits2);       
               
                int hits3 = cache.getMissCountNotFound();
                System.out.println("得到缓存读取的丢失次数:"+hits3);       
               
                int hits4 = cache.getMissCountExpired();
                System.out.println("得到缓存读取的已经被销毁的对象丢失次数:"+hits4);   
            }

        }

 

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


首先到ehcache官网下载:ehcache官网

下载完后解压。

打开Myeclipse 创建web项目,然后在项目classpath根目录下创建ehchache.xml

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
    updateCheck="true" monitoring="autodetect"
    dynamicConfig="true">

    <defaultCache
       maxElementsInMemory="20"
       eternal="false"
       overflowToDisk="false"
       timeToIdleSeconds="1800"
       timeToLiveSeconds="1800">
    </defaultCache>

    <cache name="data-cache"
      maxElementsInMemory="20"
      overflowToDisk="false"
      eternal="false"
      timeToIdleSeconds="1800"
      timeToLiveSeconds="1800"
      memoryStoreEvictionPolicy="LRU"
      transactionalMode="off"
       >
   <searchable keys="true"/> <!--可以根据Key进行查询,查询的Attribute就是keys-->
    </cache>
</ehcache>
参数含义:

name:Cache的唯一标识,程序中使用这个名字获得缓存实例

maxElementsInMemory:内存中最大缓存对象数 。

overflowToDisk:当overflowToDisk配置为true,当内存中Element数量达到maxElementsInMemory时,Ehcache将会Element写到磁盘中。

eternal:Element是否永久有效,一但设置了, timeToIdleSeconds和 timeToLiveSeconds 将不起作用

timeToIdleSeconds: Element在缓存中空闲的最大时间。也就是说,这个时间控制的是一个Element 在一直没有被访问的前提下,这个对象可以在cache中的存活时间。若是0,表示永远存活

timeToLiveSeconds: 设置对象在cache中的最大存活时间,就是 无论对象被访问或是闲置,这个对象在cache中总的存活时间。也就是说, timeToLiveSeconds的值得应该大于等于 timeToIdleSeconds, 若是0,表示永远存活。

memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内 存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)

maxElementsOnDisk:磁盘中最大缓存对象数,若是0表示无穷大。 该选项只有在overflowToDisk为true时有效

diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区

EhCache CRUD例子

package com.mayi.ehcache.demo;

import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;
import net.sf.ehcache.config.CacheConfiguration;
import net.sf.ehcache.search.Attribute;
import net.sf.ehcache.search.Query;
import net.sf.ehcache.search.Result;
import net.sf.ehcache.search.Results;
import org.junit.Assert;
import org.junit.Test;

import java.io.InputStream;
import java.util.List;
import java.util.Set;

public class EhcacheTest {

    @Test
    public void testCacheManager() {
  //加载EhCache配置文件
  InputStream in = EhcacheTest.class.getClassLoader().getResourceAsStream("ehcache.xml");
  CacheManager cm = CacheManager.create(in);

  //列出所有的缓存名称,不包括配置文件中的<defaultCache>
  String[] names = cm.getCacheNames();

  //只有一个名称为data-cache的cache
  Assert.assertEquals(1, names.length);
  Assert.assertEquals(names[0], "data-cache");

  //根据指定名称查找缓存对象
  Cache cache = cm.getCache("data-cache"); //根据缓存名称获取缓存
  Assert.assertNotNull(cache);

  //获取,更新Cache配置的接口
//  CacheConfiguration configuration = cache.getCacheConfiguration();
//  configuration.setTimeToIdleSeconds(3600);

  //缓存在内存中的配置信息,缓存配置动态修改也会体现出来,
  System.out.println(cm.getActiveConfigurationText());

  //清除所有缓存的数据,但是缓存本身仍然存在
//  cm.clearAll();

  //从内存中删除一个缓存以及所有的数据,Cache被销毁
//  cm.removeCache("data-cache");


    }

    @Test
    public void testCache() {
  //只有被有初始化生效的Cache允许改名字
  //cache.setName("data-cache-changed");
    }

    @Test
    public void testAddElementToCache() {
  //加载EhCache配置文件
  InputStream in = EhcacheTest.class.getClassLoader().getResourceAsStream("ehcache.xml");
  CacheManager cm = CacheManager.create(in);

  Cache cache = cm.getCache("data-cache");

  Person p1 = new Person(1, "Jack", 21);
  Person p2 = new Person(2, "Mike", 73);

  cache.putIfAbsent(new Element(p1,p1, 1));
  cache.put(new Element(p2,p2, 1));
  cache.putIfAbsent(new Element(p2, p1,1));//只有Key为p2的数据不存在才插入

  //得到的是p2,而不是p1
  Element e = cache.get(p2);
  Assert.assertEquals(p2, e.getObjectValue());

  //把数据从内存刷到DiskStore,从DiskStore刷新到Disk中
  cache.flush();

    }

    @Test
    public void testRemoveElementFromCache() {
  //加载EhCache配置文件
  InputStream in = EhcacheTest.class.getClassLoader().getResourceAsStream("ehcache.xml");
  CacheManager cm = CacheManager.create(in);

  Cache cache = cm.getCache("data-cache");

  Person p1 = new Person(1, "Jack", 21);
  Person p2 = new Person(2, "Mike", 73);

  Element e1  = new Element(p1,p1, 1);
  cache.putIfAbsent(e1);
  Element e2 = new Element(p2,p2, 1);
  cache.put(e2);

  cache.remove(p1);
  boolean isSucc = cache.removeElement(e1);
  //e1已经被删除,因此操作返回false
  Assert.assertFalse(isSucc);

  cache.put(e1);

  cache.removeAll();

  Assert.assertEquals(0, cache.getSize());
    }

    @Test
    public void testUpdateElementInCache() {
  //加载EhCache配置文件
  InputStream in = EhcacheTest.class.getClassLoader().getResourceAsStream("ehcache.xml");
  CacheManager cm = CacheManager.create(in);

  Cache cache = cm.getCache("data-cache");

  Person p1 = new Person(1, "Jack", 21);
  Person p2 = new Person(2, "Mike", 73);

  Element e1  = new Element(p1,p1, 1);
  cache.putIfAbsent(e1);
  Element e2 = new Element(p2,p2, 1);
  cache.put(e2);

  e2 = new Element(p2, p1, 1);
  cache.replace(e2);

  Assert.assertEquals(p1, e2.getObjectValue());

    }

    @Test
    public void testQueryElementsFromCache() {
  InputStream in = EhcacheTest.class.getClassLoader().getResourceAsStream("ehcache.xml");
  CacheManager cm = CacheManager.create(in);
  Cache cache = cm.getCache("data-cache");

  //EhCache中的数据类型是Element,它包含Key,Value和一个版本信息
  Element e = new Element(1000, 10000, 1);
  cache.put(e);

  //添加第二个数据
  e = new Element(2000, 20000, 1);
  cache.put(e);

  //缓存中有两条数据
  Assert.assertEquals(2, cache.getSize());

  //通过get方法获得key对应的数据
  e = cache.get(1000);
  Assert.assertEquals(10000, e.getObjectValue());

  //创建查询
  Query q = cache.createQuery();

  //Cache没有配置任何查询属性,这里察看下默认的查询属性有哪些
  //set中包含两个可查询元素:key和value
  Set<Attribute> set = cache.getSearchAttributes();

  //属性是范型类,得到key都应的查询属性对象
  Attribute<Integer> keyAttribute = cache.getSearchAttribute("key"); //根据默认提供的可查询属性key进行查询

  //构造查询条件,这是一个链式写法,一个Query对象可以写多个查询条件
  //创建查找key的值为2000的查询
  q = q.addCriteria(keyAttribute.eq(2000));

  //如果不includeKeys和q.includeValues();,则测试结果集中不包括Keys和Values信息
  q.includeKeys();
  q.includeValues();

  //执行查询
  Results results = q.execute();//执行查询
  Assert.assertNotNull(results);
  Assert.assertEquals(results.size(), 1);

  //列出所有结果
  List<Result> resultList = results.all();
  Result result = resultList.get(0);
  Assert.assertEquals(2000, result.getKey());

  Assert.assertEquals(20000, result.getValue());
    }

}

Person 类

package com.mayi.ehcache.demo;

public class Person {
    private int id;
    private String name;
    private int age;

    public Person(int id, String name, int age) {
  this.id = id;
  this.name = name;
  this.age = age;
    }

    @Override
    public boolean equals(Object o) {
  if (this == o) return true;
  if (o == null || getClass() != o.getClass()) return false;

  Person person = (Person) o;

  if (age != person.age) return false;
  if (id != person.id) return false;
  if (name != null ? !name.equals(person.name) : person.name != null) return false;

  return true;
    }

    @Override
    public int hashCode() {
  int result = id;
  result = 31 * result + (name != null ? name.hashCode() : 0);
  result = 31 * result + age;
  return result;
    }
}

最后运行junit即可

 


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

初始化
    CacheManager manager = new CacheManager(“src/config/ehcache.xml”);
    //获取指定Cache对象
    Cache configCache = manager.getCache(“configCache”);
    //创建节点对象
    Element element = new Element(“key1”,”value1”);
    //保存节点到configCache
    configCache.put(element);
    //从configCache获取节点
    Element element2 = configCache.getCache(“key1”);
    Object  value = element2.getValue();
    //更新节点
    configCache.put(new Element(“key1”,”value2”));
    //删除节点
    configCache.remove(“key1”);


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

Ehcache测试程序

package com.gwc.springlearn;

import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;
import org.junit.Test;

/**
 * Created by GWCheng on 2016/3/4.
 */
public class TestEhcache {
    @Test
    public void testEhcache() {
        // Creating a CacheManager based on a specified configuration file.
        CacheManager manager = CacheManager.newInstance("src/main/resources/ehcache.xml");
        // obtains a Cache called sampleCache1, which has been preconfigured in the configuration file
        Cache cache = manager.getCache("sampleCache1");
        // puts an element into a cache
        Element element = new Element("key1", "哈哈");
        cache.put(element);
        //The following gets a NonSerializable value from an element with a key of key1.
        Object value = element.getObjectValue();
        System.out.println(value.toString());
        manager.shutdown();
    }
}

 

 

============================
在简单研究了memcached和redis之后,又看了同样很流行的ehcache缓存。

在JavaWeb项目中加入ehcache缓存技术,所依赖的主要jar包: ehcache.jar   backport-util-concurrent.jar

免积分下载地址:http://download.csdn.net/detail/kkkder/9638071

Demo是从网上找的如下:


package com.ehcache;

import java.io.Serializable;

import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;

public class EhCache
{
 public static void main(String[] args) {
        //创建一个缓存管理器
        CacheManager singletonManager = CacheManager.create();
        //建立一个缓存实例
        Cache memoryOnlyCache = new Cache("testCache", 5000, false, false, 5, 2);
        //在内存管理器中添加缓存实例
        singletonManager.addCache(memoryOnlyCache);
        Cache cache = singletonManager.getCache("testCache");
        //使用缓存
        Element element = new Element("key1", "value1");
        cache.put(element);
        cache.put(new Element("key1", "value2"));

        element = cache.get("key1");
        Serializable value = element.getValue();
        System.out.println("value:"+value);

        int elementsInMemory = cache.getSize();
        System.out.println("elementsInMemory:"+elementsInMemory);

        long elementsInMemory2 = cache.getMemoryStoreSize();
        System.out.println("elementsInMemory2:"+elementsInMemory2);

        Object obj = element.getObjectValue();
        cache.remove("key1");
        System.out.println("obj:"+obj);
        singletonManager.shutdown();
    }
}


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

自己测试的 cache 的正确的代码, 注意 配置文档:

 <servlet>
    <servlet-name>servlet3</servlet-name>
    <servlet-class>com.servlet3</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>servlet3</servlet-name>
    <url-pattern>/servlet/servlet3</url-pattern>
  </servlet-mapping>


------------------------------

 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

 
   ServletContext servletContext = this.getServletContext();
  
  // CacheManager cacheManager = new CacheManager();
   CacheManager manager = CacheManager.create("C:/Users/Administrator/workspace/AppServlet/src/com/ehcache.xml");
         //初始化 defaultCache Cache
   String names[]= manager.getCacheNames();
  
   System.out.println("----all cache names----");    
   for (int i = 0; i < names.length; i++) {      
    System.out.println(names[i]);        }  
   System.out.println("----------------------");       
  
   // 得到一个cache对象       
   Cache cache1 = manager.getCache(names[0]);       
   // 向cache1对象里添加缓存      
   cache1.put(new Element("key1", "第一个ehcache,哈哈哈。"));       
   Element element = cache1.get("key1");       
   // 读取缓存      
   System.out.println("key1 \t= " + element.getObjectValue());
  
  
 //      Cache cache = manager.getCache("sampleCache1");
         //新建一个cache节点,并赋值"value1"
  //       Element element = new Element("key1","value1");
         //把cache节点存储到默认的cache
    //     cache.put(element);
         //将cahe存储到全局变量(servletContext)
         servletContext.setAttribute("Cache",cache1);
 
 
 }
----------------------------------


<?xml version="1.0" encoding="UTF-8"?>
<ehcache>

    <diskStore path="java.io.tmpdir"/>

    <defaultCache
            maxEntriesLocalHeap="10000"
            eternal="false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            diskSpoolBufferSizeMB="30"
            maxEntriesLocalDisk="10000000"
            diskExpiryThreadIntervalSeconds="120"
            memoryStoreEvictionPolicy="LRU">
        <persistence strategy="localTempSwap"/>
    </defaultCache>

    <cache name="sampleCache1"
           maxEntriesLocalHeap="10000"
           maxEntriesLocalDisk="1000"
           eternal="false"
           diskSpoolBufferSizeMB="20"
           timeToIdleSeconds="300"
           timeToLiveSeconds="600"
           memoryStoreEvictionPolicy="LFU"
           transactionalMode="off">
        <persistence strategy="localTempSwap"/>
    </cache>

</ehcache>

 

 

 

 

 

 


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


本文主要介绍 在纯servlet应用中 整合 EhCache 缓存的使用

1.整合EhCache首先我们要下载EhCache的架包
下载地址:http://ehcache.org/downloads/catalog
直接下载 hcache-2.7.4-distribution.tar.gz

下载后,我们解压出来到lib文件夹里找到架包,总共有3个文件
ehcache-2.7.4.jar
slf4j-api-1.6.6.jar
slf4j-jdk14-1.6.6.jar
这3个文件我们都是需要的,直接导入到项目里
在 servlet 中使用 EhCache 缓存

2.导入架包之后,我们要考虑怎么和servlet容器进行整合
在上一篇文章中 我介绍了 怎么在 servlet 中使用和初始化 ServletContext 也就是全局变量

那我们整合EhCache 是否就可以 把 EhCache 放到 ServletContext 里去?

照例,先实现一个ServletContext的监听器并且在ServletContext初始化的时候初始化我们的EhCache

public class ContextLoaderListener implements ServletContextListener{

    //实现全局上下文初始化方法
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        //获得全局变量
        ServletContext servletContext = servletContextEvent.getServletContext();
        //初始化 EhCache 管理器
        CacheManager cacheManager = new CacheManager();
        //初始化 defaultCache Cache
        Cache cache = cacheManager.getCache("defaultCache");
        //新建一个cache节点,并赋值"value1"
        Element element = new Element("key1","value1");
        //把cache节点存储到默认的cache
        cache.put(element);
        //将cahe存储到全局变量(servletContext)
        servletContext.setAttribute("Cache",cache);
    }


    //实现全局上下文销毁函数
    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        //实现
    }
}

在 web.xml 里配置 contextInitialized 监听器

<listener>
    <listener-class>listener.ContextLoaderListener</listener-class>
</listener>

3.整合完毕,然后我们就可以测试是否整合成功

因为前面我们初始化的时候已经给cache存储了一个key为“key1”的cache节点
所以我们在helloOut这个servlet中直接查看是否可以取到"key1"节点


public class HelloOut extends HttpServlet {
    public void service(HttpServletRequest request,HttpServletResponse response) throws IOException {
        PrintWriter writer = response.getWriter();
        writer.println("Hello Word For BAE3");
        //获取全局变量
        ServletContext servletContext = getServletContext();
        //从全局变量获取 cache
        Cache cache = (Cache) servletContext.getAttribute("Cache");
        //输出cache中key为"key1"节点的value
        writer.println(cache.get("key1").getObjectValue());
        writer.close();

    }
}

打开 http://localhost:8080/EhCacheTest_war_exploded/hello

 

 

 


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


本文介绍 怎么在Servlet Web应用 中 初始化 全局变量(ServletContext)

ServletContext 也就是 java Servlet Web应用 里面的全局变量,当我们有时要做一些初始化配置是通常也是存在ServletContext里面

怎么初始化呢?有2个办法,一是监听器(listener)来初始化,二是通过设置servlet的load-on-startup=1,让servlert在web应用在启动时就加载这servlert来实现

我们这里主要讲第一个,也就是通过监听器(listener)来实现

首先我们要准备一个实现了ServletContextListener监听器接口的类


public class ContextLoaderListener implements ServletContextListener{

    //实现全局上下文初始化方法
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        //获得全局变量
        ServletContext servletContext = servletContextEvent.getServletContext();
        //设置全局变量属性
        servletContext.setAttribute("test","test1");
    }

    //实现全局上下文销毁函数
    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        //实现
    }
}接下来在web.xml里面配置监听器的配置,在web.xml添加以下配置

<listener>
    <listener-class>listener.ContextLoaderListener</listener-class>
</listener>接下来你就可以在 servlet中取到 全局变量里面test变量的值,代码如下

public class HelloOut extends HttpServlet {
    public void service(HttpServletRequest request,HttpServletResponse response) throws IOException {
        PrintWriter writer = response.getWriter();
        writer.println("Hello Word For Test");
        //获取全局变量
        ServletContext servletContext = getServletContext();
        //输出test变量
        writer.println(servletContext.getAttribute("test"));
        writer.close();
    }
}PS:扩展,你还可以在listener实现一个计数器,每次运行contextInitialized方法计数+1,然后存到全局变量里去,在servlet中查看计数的值,你就验证contextInitialized 这个方法是否只运行了一次


下一篇文章是在servlet中使用EhCache

 

 

 


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

多用户并发访问Servlet与线程同步(2013-02-07 11:37:45)转载▼标签: it 分类: java tomcat 
    Servlet容器为了响应多个用户同时访问一个Servlet的HTTP请求,通常会为每个请求分配一个工作线程,这些工作线程并发执行同一个Servlet的service()方法。此时可能发生多线程对同一数据进行访问的情况。
public class Hello extends HttpServlet{
    private String name;
  
    public void doPost(HttpServletRequest request,HttpServletResponse response)
        throws ServletException,java.io.IOException{
      
        response.setContentType("text/html;charset=UTF-8");
      
        name = (String)request.getParameter("name");    //接收参数
      
        PrintWriter out = response.getWriter();
        out.println("");
        out.println("你好"+name);
        out.println("");
              
        out.close();
    }
}
如果多线程并发访问,会访问同一个实例变量,则会共用name,而出现用户得到数据不一致的现象。

解决办法:
1.将name设置为局部变量
  
public class Hello extends HttpServlet{
  
    public void doPost(HttpServletRequest request,HttpServletResponse response)
        throws ServletException,java.io.IOException{
      
        response.setContentType("text/html;charset=UTF-8");
      
        String name = (String)request.getParameter("name");    //接收参数
      
        ...
    }
}
每当一个线程执行doPost()时,在线程的堆栈中就会创建name这个局部变量,当线程执行完该方法,局部变量就结束生命周期。如果多个线程同时执行该方法,那么每个线程都拥有自己的局部变量。

2.使用Java同步机制对多线程同步
public class Hello extends HttpServlet{
    private String name;
  
    public void doPost(HttpServletRequest request,HttpServletResponse response)
        throws ServletException,java.io.IOException{
      
        response.setContentType("text/html;charset=UTF-8");
      
        synchronized(this){
            name = (String)request.getParameter("name");    //接收参数
            ...
        }
        ...
    }
}
这样可确保在任意一时刻,只允许有一个工作线程执行doPost()中的同步代码块。只有当这个工作线程退出同步代码块时,其他工作线程才允许执行同步代码块。这使得任意时刻不会有两个线程同时操纵同一个实例变量,从而避免并发问题。

3.实现被废弃的SingleThreadModel接口
public class Hello extends HttpServlet implements SingleThreadModel{
  ...
}
如果实现此接口,则Servlet容器实现可以采用以下两种方式之一来运行Servlet:
1)在任意一时刻,只允许有一个工作线程执行Servlet的service()方法。如果有多个用户同时请求访问该Servlet,那么这些客户请求被放入等待队列,容器会依次响应等待队列中的每个客户请求。这种实现方式实际上禁止了多个客户端对同一个Servlet的并发访问。
2)Servlet容器为每个Servlet创建一个对象池,在这个池中存放了同一个Servlet类的多个实例。如果有多个用户同时请求访问该 Servlet,Servlet容器会为每个请求分配一个工作线程,并且从对象池中取出一个空闲的Servlet实例,把它分配给工作线程。每个工作线程执行自己的Servlet实例的service()方法。这种实现方式表面上允许客户端对同一个Servlet并发访问,但实际上不同客户端访问的是同一个Servlet类的不同实例。
如果实例变量需要共享,用以进行计算,这种方法并不能有效的避免并发问题。

 

 

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

使用ServletContext实现数据共享和获得web.xml中的参数 //适用于:很多文件需要初始化参数时,例如数据库账号和密码,不可能使用config这个对象,因为如果使用config对象去配置的话,那么每个servlet类都必须写一个参数,这时候就必须采用context这个对象去实现一个数据的共享

 

//servlet

response.setContentType("text/html");
  request.setCharacterEncoding("utf-8");
  response.setCharacterEncoding("utf-8");
  PrintWriter out = response.getWriter();
  //实例化ServletContext对象
  ServletContext servletContext=this.getServletContext();
  /*************************达到数据共享*********************************/
  //设置servletContext保存的值
//  servletContext.setAttribute("name", "张三");
 
  //内部跳转,注意:不应该使用servletContext进行传递数据,应该使用Request.getRequestDispatcher("/index.jsp").forward(request, response);进行内部跳转
  //数据共享一般都有他自己使用的范围
//  servletContext.getRequestDispatcher("/index.jsp").forward(request, response);
 
  /**************************获取web.xml配置的参数****************************************/
  //获取初始化指定参数
//  String name=(String) servletContext.getInitParameter("name");
//  out.println(name);
 
  //获取所有参数
  Enumeration enumeration=servletContext.getInitParameterNames();
  while (enumeration.hasMoreElements()) {
   String name=servletContext.getInitParameter((String)enumeration.nextElement());
   out.println(name+"<br/>");
  }

 

//web.xml

<context-param>
   <param-name>name</param-name>
   <param-value>张三</param-value>
  </context-param>
  <context-param>
   <param-name>name1</param-name>
   <param-value>李四</param-value>
  </context-param>
  <context-param>
   <param-name>name2</param-name>
   <param-value>王五</param-value>
  </context-param>

分类: j2ee

 


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


通过ServletContext实现Servlet之间共享数据

ServletContext 是应用级域对象。

web.xml文件:

 

 

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
  <servlet>
   <!-- 定义Sevlet:给Servlet取个名字 -->
    <servlet-name>ServletDemo</servlet-name>
    <servlet-class>com.neu.ServletDemo</servlet-class>
  </servlet>
  <servlet>
    <servlet-name>ServletDemo2</servlet-name>
    <servlet-class>com.neu.ServletDemo2</servlet-class>
  </servlet>


  <servlet-mapping>
   <!-- 映射Servlet:给Servlet一个访问地址 -->
    <servlet-name>ServletDemo</servlet-name>
    <url-pattern>/hello</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>ServletDemo2</servlet-name>
    <url-pattern>/servlet/ServletDemo2</url-pattern>
  </servlet-mapping>

</web-app>
ServletDemo.java文件:

 


package com.neu;

import java.io.IOException;
import java.util.Enumeration;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ServletDemo extends HttpServlet {

 public void doGet(HttpServletRequest request, HttpServletResponse response)
   throws ServletException, IOException {
  
  ServletContext sc = getServletContext();
  sc.setAttribute("p", "ppp");
  response.getWriter().write("OK");
 }

 public void doPost(HttpServletRequest request, HttpServletResponse response)
   throws ServletException, IOException {
  doGet(request, response);
 }
 
}
ServletDemo2.java文件:

 


package com.neu;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ServletDemo2 extends HttpServlet {

 
 public void doGet(HttpServletRequest request, HttpServletResponse response)
   throws ServletException, IOException {

  ServletContext sc = getServletContext();
  String value = (String)sc.getAttribute("p");
  response.getWriter().write(value);
 }


 public void doPost(HttpServletRequest request, HttpServletResponse response)
   throws ServletException, IOException {

  
 }

}
运行及结果:

运行:http://localhost:8080/ServletDemo/hello


结果:OK

运行:http://localhost:8080/ServletDemo/servlet/ServletDemo2

结果:ppp

 

 

 

 

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

CREATE TABLE TEST (
    TEST_ID         bigint(20)  ,
    TEST_NAME         varchar(50),
    TEST_TIME       timestamp default CURRENT_TIMESTAMP,
    TEST_VALUE      decimal(10,3) 
)

建java工程,建立与TEST表对应bean,

import java.io.Serializable;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.*;

public class TEST implements Serializable {
    private static final long serialVersionUID = 1L;
    public Long TEST_ID;
    public String TEST_NAME;
    public Timestamp TEST_TIME;
    public BigDecimal TEST_VALUE;
    @Override
    public String toString() {
        return String.format("ID:%s,,,NAME:%s", TEST_ID, TEST_NAME);
    }
}


Util类代码如下:

import java.util.Random;

public class Util{

    public static Random rand = new Random();
    public static String atoz = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

    public static String genString(int length) {
        StringBuilder re = new StringBuilder(length);
        re.append(atoz.charAt(rand.nextInt(52)));
        for (int i = 0; i < length; i++) {
            re.append(atoz.charAt(rand.nextInt(62)));
        }
        return re.toString();
    }

    public static double genDouble() {
        double d1 = 5120 * rand.nextDouble();
        double d2 = 1024000 * rand.nextDouble();
        return d1 + d2;
    }
}

主程序:

import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.HashMap;

import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;


public class Main {

  private static String dbURL="jdbc:mysql://localhost/test?useUnicode=true&characterEncoding=GBK";
    private static String user="root";
    private static String pass="beautiful_mm";
    private static String dbDriver="com.mysql.jdbc.Driver";
    private static String FORMAT="yyyy-MM-dd HH:mm:ss";
    private static SimpleDateFormat dateFormat=new SimpleDateFormat(FORMAT);
    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        CacheManager manager = CacheManager.create("./src/main/resources/ehcache.xml");
        Cache demo = manager.getCache("demoCache");
        if(null==manager)
        {System.out.println("manager is null? can not get ehcache manager");}
        else
        {System.out.println("get ehcache manager succeed!");}
        try {
        // 插入10W数据,以备测试         
                traditionalInsert(100000);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
       
        try {
            ehcache();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
       
        Cache cid = manager.getCache("TEST_ID.TEST");
         long begin = System.currentTimeMillis();
         for(int i=1;i<10001;i++)
         {
             Element e5120 = cid.get(new Long(i));
         }
         long end1 = System.currentTimeMillis();
         System.out.println("从cache中查询10000条数据消耗时间: " + (end1-begin));
         for(int i=1;i<10001;i++)
         {
             try {
                getRecord(i);
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
         }
         long end2 = System.currentTimeMillis();
         System.out.println("用sql查询10000条数据消耗时间: " + (end2-end1));
    }
   
    public static HashMap<Long, TEST> simpleCache() throws Exception {
        HashMap<Long, TEST> cacheid = new HashMap<Long, TEST>();
        Class.forName(dbDriver);
        Connection conn = DriverManager.getConnection(dbURL, user, pass);
        try {
            long begin = System.currentTimeMillis();
            Statement s = conn.createStatement();
            String sql = "SELECT TEST_ID,TEST_NAME,TEST_TIME,TEST_VALUE FROM TEST";
            ResultSet querySet = s.executeQuery(sql);
            for (int i = 1; querySet.next(); i++) {
                TEST curr = new TEST();
                curr.TEST_ID = querySet.getLong(1);
                curr.TEST_NAME = querySet.getString(2);
                curr.TEST_TIME = querySet.getTimestamp(3);
                curr.TEST_VALUE = querySet.getBigDecimal(4);
                cacheid.put(curr.TEST_ID, curr);
            }
            long end = System.currentTimeMillis();
            System.out.printf("Time:%d\n", (end - begin));
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            conn.close();
        }
        return cacheid;
    }
   
   
    public static void traditionalInsert(int total) throws Exception {
        Thread.sleep(3000);
        Timestamp current = new Timestamp(System.currentTimeMillis());
        String currentStr = dateFormat.format(current);
        System.out.println(currentStr);
        Connection conn = DriverManager.getConnection(dbURL, user, pass);
        try {
            long begin = System.currentTimeMillis();
            conn.setAutoCommit(false);
            String sql = "INSERT INTO TEST (TEST_ID,TEST_NAME,TEST_TIME,TEST_VALUE) VALUES (?, ?, ?, ?)";
            PreparedStatement ps = conn.prepareStatement(sql);
            for (int i = 1; i <= total; i++) {
                ps.setLong(1, i);
                ps.setString(2, Util.genString(33));
                ps.setTimestamp(3, current);
                ps.setBigDecimal(4, new BigDecimal(Util.genDouble()));
                ps.addBatch();
                if ((i % 500) == 0) {
                    ps.executeBatch();
                }
            }
            ps.executeBatch();
            System.out.println("insert !! done");
            conn.commit();
            long end = System.currentTimeMillis();
            System.out.printf("Count:%d Time:%d\n", total, (end - begin));
        } catch (Exception ex) {
            ex.printStackTrace();
            conn.rollback();
        } finally {
            conn.close();
        }
    }
   
    public static void ehcache() throws Exception {
        CacheManager manager = CacheManager.create("./src/main/resources/ehcache.xml");
        manager.addCache("TEST_ID.TEST");
        Cache cid = manager.getCache("TEST_ID.TEST");
        Class.forName(dbDriver);
        Connection conn = DriverManager.getConnection(dbURL, user, pass);
        try {
            long begin = System.currentTimeMillis();
            Statement s = conn.createStatement();
            String sql = "SELECT TEST_ID,TEST_NAME,TEST_TIME,TEST_VALUE FROM TEST";
            ResultSet querySet = s.executeQuery(sql);
            for (int i = 1; querySet.next(); i++) {
                TEST curr = new TEST();
                curr.TEST_ID = querySet.getLong(1);
                curr.TEST_NAME = querySet.getString(2);
                curr.TEST_TIME = querySet.getTimestamp(3);
                curr.TEST_VALUE = querySet.getBigDecimal(4);
                cid.put(new Element(curr.TEST_ID, curr));
            }
            long end = System.currentTimeMillis();
            System.out.printf("ehcache cost Time:%d\n", (end - begin));
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            conn.close();
        }
    }
   
    public static TEST getRecord(int id) throws Exception {
        TEST ret = null;
        Class.forName(dbDriver);
        Connection conn = DriverManager.getConnection(dbURL, user, pass);
        try {
            long begin = System.currentTimeMillis();
            Statement s = conn.createStatement();
            String sql = "SELECT TEST_ID,TEST_NAME,TEST_TIME,TEST_VALUE from TEST where TEST_ID="+id;
            ResultSet querySet = s.executeQuery(sql);
            for (int i = 1; querySet.next(); i++) {
                TEST curr = new TEST();
                curr.TEST_ID = querySet.getLong(1);;
                curr.TEST_NAME = querySet.getString(2);
                curr.TEST_TIME = querySet.getTimestamp(3);
                curr.TEST_VALUE = querySet.getBigDecimal(4);
                return curr;
               // cid.put(new Element(curr.TEST_ID, curr));
            }
            long end = System.currentTimeMillis();
            System.out.printf("ehcache cost Time:%d\n", (end - begin));
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            conn.close();
        }
        return ret;
    }
}


----------------
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
get ehcache manager succeed!
2012-11-25 22:28:41
insert !! done
Count:100000 Time:14980
ehcache cost Time:5881
从cache中查询10000条数据消耗时间: 71
用sql查询10000条数据消耗时间: 500620


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

2017-11-6

session   servlet线程安全文章

http://blog.csdn.net/zavens/article/details/1759786  过了

http://blog.csdn.net/gavin_john/article/details/51355292

http://blog.csdn.net/gavin_john/article/details/51374799


http://blog.csdn.net/gavin_john/article/details/51376364

 

http://blog.csdn.net/qq_28385797/article/details/53382354

http://blog.csdn.net/bcbobo21cn/article/details/50915502

http://blog.csdn.net/xw_classmate/article/details/50700399

 

 

http://blog.csdn.net/irelandken/article/details/6935659


https://www.cnblogs.com/liuchuanfeng/p/6862776.html

https://www.cnblogs.com/mengdd/p/3202662.html

http://com0606.iteye.com/blog/994802

http://blog.csdn.net/goskalrie/article/details/51240482

https://www.cnblogs.com/lr393993507/p/5909804.html
----------------------------------------------------------------------------------
如何开发线程安全的Servlet

 1、变量的线程安全:这里的变量指字段和共享数据(如表单参数值)。

  A、将参数变量本地化。多线程并不共享局部变量.所以我们要尽可能的在servlet中使用局部变量。
   例如:String user = "";
         user = request.getParameter("user");

 B、使用同步块Synchronized,防止可能异步调用的代码块。这意味着线程需要排队处理。在使用同板块的时候要尽可能的缩小同步代码的范围,不要直接在sevice方法和响应方法上使用同步,这样会严重影响性能。

3、使用同步的集合类:
  使用Vector代替ArrayList,使用Hashtable代替HashMap。

4、不要在Servlet中创建自己的线程来完成某个功能。
  Servlet本身就是多线程的,在Servlet中再创建线程,将导致执行情况复杂化,出现多线程安全问题。

小结

Servlet的线程安全问题只有在大量的并发访问时才会显现出来,并且很难发现,因此在编写Servlet程序时要特别注意。线程安全问题主要是由实例变量造成的,因此在Servlet中应避免使用实例变量。如果应用程序设计无法避免使用实例变量,那么使用同步来保护要使用的实例变量,但为保证系统的最佳性能,应该同步可用性最小的代码路径。

-----=====================================================

String name = request.getParameter("name");  //获取用户填写的用户名
   
   session.setAttribute("name",name); 


 String name = (String)session.getAttribute("name");//获取保存在session范围内的对象

 


session.removeAttribute("name") // 移除session对象的成员

session.invalidate(); 对session手动销毁,不能再使用了。


设置会话生命周期的方法:
getLastAccessedTime(); // 返回客户端最后一次与会话相关联的请求时间。

setMaxInactiveInterval( 秒) ; // 以秒为单位设置session的有效时间。


HttpSession session = request.getSession();
session.setAttribute("abc",new Integer(567));//新增属性 键:abc 值:new Integer(567)
session.setAttribute("jkl",new Person());//新增属性 键:jkl 值:new Person()
session.setAttribute("abc",new Double(5.67));//已经存在 键abc,将会修改该键对应的值


-----------

package chap03;

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class SaveInfo extends HttpServlet
{
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException,IOException
{
//验证登录者身份,验证过程此处省略
//如果合法用户就产生一个session来放置其登录名


//如果用户输入了用户名,则将其放在session中
if(request.getParameter("userName")!=null)
{
HttpSession session = request.getSession();//没有Session就新建一个
session.setAttribute("abc", request.getParameter("userName"));//在服务器端存储"键-值对"
}
response.setContentType("text/html;charset=GBK");
PrintWriter out = response.getWriter();
out.println("Session已经创建");
out.println("<BR>");
out.println("转到其他<A HREF=/"chap03.GetSession/">页面</A>");
}
public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException,IOException
{
doGet(request,response);
}
}

 

 

实例:
package chap03;

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class GetSession extends HttpServlet
{
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException,IOException
{
response.setContentType("text/html;charset=GBK");
PrintWriter out = response.getWriter();

String user = "";
//此处不新建session,只是去取已经创建的session
HttpSession session = request.getSession(false);
//如果session能够取到,说明用户已经登录
if(session!=null)
{
user = (String)session.getAttribute("abc");
out.println("获得创建的Session");
out.println("<BR>");
out.println("登录名:"+user);
}
//否则,说明用户没有登录,跳转到登录页面让用户登录
else
{
response.sendRedirect("../SessionLogin.htm");
}
}
public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException,IOException
{
doGet(request,response);
}
}

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

1.得到session
// 返回这个request绑定的session对象,如果没有,则创建一个
HttpSession session = request.getSession();
// 返回这个request绑定的session对象,如果没有,则根据create的值决定是否创建一个
HttpSession session = request.getSession(boolean create)

2.向session中添加属性
session.setAttribute(String name,Object val);1
3.从session中得到某个属性
String value = session.getAttribute(String name);1
4.从session中删除某个属性
session.removeAttribute(String name);


比如,我们可以把一个User对象放入session对象中:
// 创建对象
User user = new User();
user.setName("小猫");
user.setColor("红色");
session.setAttribute("cat", user);1
之后,我们可以从session对象中取出这个User对象:


// 获取User
User user = (User)session.getAttribute("cat");

--------------

session中的属性的默认生命周期是30min,这个默认时间可以通过修改web.xml文件来修改
这样修改:
1.在Tomcat根目录\conf\web.xml文件中修改:
<session-config>
        <session-timeout>30</session-timeout>
</session-config>1
这样修改会对所有的web应用生效。

调用setMaxInacttiveInterval(int interval),这里的interval是以秒为单位的,而且这个方法设置的是发呆时间,比如你设置的是60秒,那么在这60秒之内如果你没有操作过session,它就会自动删除,如果你操作过,不管是设置属性还是读取属性,它都会从头开始计时。

 

1.防止用户非法登录到某个页面比如我们的用户管理系统,
必须要登录成功后才能跳转到主页面,而不能直接绕过登录页面直接到主页面,
这个应用是一个非常常见的应用。

这时候,我们需要使用到Session技术,如下,
当在验证用户的控制器LoginClServlet.java验证用户成功后,
将当前的用户信息保存在Session对象中:
// 把user对象保存在session
HttpSession session = request.getSession();
session.setAttribute("login-user", user);


然后在主页面MainFrame.java最开始的地方,取出Session中的登录用户信息,
如果信息为空,则为非法访问,直接跳转到登录页面,并提示相关信息:
// 取出login-user这个session
User login_user = (User)request.getSession().getAttribute("login-user");
if(login_user == null){
    // 说明用户没有登录,让他跳转到登录页面
    request.setAttribute("error", "请登录!");
    request.getRequestDispatcher("/LoginServlet").forward(request,response);
    // 这个return很重要!
    return;
}1
那么这里就存在一个问题,一个网站会有很多个需要防止非法访问的页面,
如果都是用这种方法岂不是很麻烦?

这里有两种解决办法:
第一种是将这段验证用户的代码封装成函数,每次调用
第二种是使用过滤器(后面会介绍)

 


2.用户登录时验证输入的验证码是否正确原理:使用到java的绘图技术
假设我们编写登录页面Login,验证用户的LoginClServlet,以及生成验证码的CreateCode,
如下所示:

用户在访问登录页面Login的时候,Login页面会去请求CreateCode这个Servlet生成验证码,
然后显示在自己的页面上,然后再提交到LoginClServlet进行验证。很显然,
访问Login和请求CreateCode这是从浏览器发出的两次不同的请求,
所以,CreateCode产生的验证码字符串必须放入Session中,才能让LoginClServlet拿到,
然后进行验证。
那么怎么让登录页面Login显示验证码呢?其实很简单,
直接将img的src指向CreateCode这个Servlet即可,如下所示:
out.println("<font color=white>验证码:<input type='text' name='checkcode'/><img src='/mycheckcode/CreateCode'>");1
可以看到运行结果:

这个登录表单提交到LoginClServlet进行验证,它需要从参数中获取用户输入的验证码,再从Session中取出CreateCode这个Servlet放入Session中的正确的验证码,然后对比两者,它的doGet方法的关键代码如下:
//获取用户的id/password/输入的验证码
String id = request.getParameter("id");
String passwd = request.getParameter("passwd");
// 用户输入的验证码
String input_checkcode = request.getParameter("checkcode");
// 正确的验证码
String checkcode = (String)request.getSession().getAttribute("checkcode");
// 先看验证码对不对
if(input_checkcode.toLowerCase().equals(checkcode)){
    // 验证码OK,再到数据库验证id和passwd
}else{
    request.setAttribute("error", "验证码有误");
    request.getRequestDispatcher("/Login").forward(request, response);
}1
这里最重要的其实是生成验证码的Servlet,Servlet代码如下:
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class CreateCode extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        // 7.禁止浏览器缓存随机图片
        response.setDateHeader("Expires", -1);
        response.setHeader("Cache-Control", "no-cache");
        response.setHeader("Pragma", "no-cache");

        // 6.通知客户机以图片方式打开发送过去的数据
        response.setHeader("Content-Type", "image/jpeg");

        // 1.在内存中创建一幅图片
        BufferedImage image = new BufferedImage(110, 30,
                BufferedImage.TYPE_INT_BGR);

        // 2.向图片上写数据
        Graphics g = image.getGraphics();

        // 设背景色
        g.setColor(Color.white);
        g.fillRect(0, 0, 110, 30);

        String checkcode = "";
        // 画5个验证码字符
        for(int i=0;i<5;i++){
            g.setColor(generateColor());
            g.setFont(generateFont());
            String str = generateStr();
            checkcode += str;
            g.drawString(str,20*i,25);
        }

        // 画干扰点
        for(int i=0;i<100;i++){
            Random random = new Random();
            int x = random.nextInt(110);
            int y = random.nextInt(30);
            g.setColor(generateColor());
            g.fillOval(x, y, 2, 2);
        }
        // 画干扰线
        for(int i=0;i<5;i++){
            Random random = new Random();
            int x1 = random.nextInt(110);
            int y1 = random.nextInt(30);
            int x2 = random.nextInt(110);
            int y2 = random.nextInt(30);
            g.setColor(generateColor());
            g.drawLine(x1, y1, x2, y2);
        }

        // 这句话就是把随机生成的验证码,保存到session
        // 验证码不区分大小写,所以这里转为小写
        request.getSession().setAttribute("checkcode", checkcode.toLowerCase());

        // 5.把写好数据的图片输出给浏览器
        ImageIO.write(image, "jpg", response.getOutputStream());

    }

    /**
     * 生成随机字体
     * @return
     */
    public Font generateFont() {
        String[] font_names = new String[] { "Broadway", "方正姚体",
                "Footlight MT Light", "Sitka Text", "方正舒体", "幼圆" ,"Colonna MT"};
        int[] font_styles = new int[]{Font.BOLD, Font.ITALIC, Font.BOLD|Font.ITALIC};

        Random random = new Random();
        int name_index = random.nextInt(font_names.length);
        int style_index = random.nextInt(font_styles.length);

        return new Font(font_names[name_index],font_styles[style_index],28);
    }

    /**
     * 生成随机颜色
     *
     * @return
     */
    public Color generateColor() {
        Random random = new Random();
        return new Color(random.nextInt(256), random.nextInt(256),
                random.nextInt(256));
    }

    /**
     * 生成随机数[0-9a-zA-Z]
     *
     * @return
     */
    public String generateStr() {
        String[] nums = new String[62];
        // 添加0-9这10个数字
        for (int i = 0; i < 10; i++) {
            nums[i] = String.valueOf(i);
        }
        // 添加A-Z这26个大写字母
        for (int i = 65; i < 91; i++) {
            nums[i - 55] = Character.toString((char) i);
        }
        // 添加a-z这26个小写字母
        for (int i = 97; i < 123; i++) {
            nums[i - 61] = Character.toString((char) i);
        }
        // 产生一个随机数
        Random random = new Random();
        int index = random.nextInt(62);
        return nums[index];
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        this.doGet(request, response);
    }

}1
3.实现简易购物车假设我们要在网上买书,那么怎么实现添加到购物车,并可以查看购物车的功能呢?肯定要使用Session。
首先,我们先写一个Book类,该类封装Book的相关信息,这里简单起见,主要有ID号,书名,以及购买的本数。然后模拟一个数据库,如下:
import java.util.HashMap;
import java.util.LinkedHashMap;

/**
 * 模拟数据库
 */
final public class DB {
    private static HashMap<String, Book> hm = null;

    private DB(){

    }

    static{
        hm = new LinkedHashMap<String, Book>();

        Book book1 = new Book("1", "Java基础", 0);
        Book book2 = new Book("2", "Oracle数据库", 0);
        Book book3 = new Book("3", "C语言", 0);
        Book book4 = new Book("4", "Python核心教程", 0);
        Book book5 = new Book("5", "Web技术", 0);

        hm.put(book1.getId(),book1);
        hm.put(book2.getId(),book2);
        hm.put(book3.getId(),book3);
        hm.put(book4.getId(),book4);
        hm.put(book5.getId(),book5);
    }

    /**
     * 得到数据库中所有的书
     * @return
     */
    public static HashMap<String, Book> getBooks(){
        return hm;
    }

    /**
     * 根据ID得到书
     * @param id
     * @return
     */
    public static Book getBookById(String id){
        if(hm.containsKey(id)){
            return hm.get(id);
        }
        return null;
    }
}1
然后在我们的showBook这个Servlet中读取数据库中所有的书的信息,显示在页面上,它的doGet方法为:
public void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    response.setContentType("text/html;charset=utf-8");
    PrintWriter out = response.getWriter();

    out.println("<h2>欢迎光临</h2>");
    out.println("<table border=1>");
    HashMap<String, Book> books = DB.getBooks();
    Iterator it = books.keySet().iterator();
    while(it.hasNext()){
        Book book = books.get(it.next());
        out.println("<tr><td>"+book.getName()+"</td><td><a href='/MyCart/BuyBookCl?id="+book.getId()+"'>点击购买</a></td></tr>");
    }
    out.println("</table>");
}1
可以看到,当用户点击购买的链接时,跳到BuyBookCl这个Servlet进行处理,并且一同传递过去的参数为书的id号,我们看看BuyBookCl是怎么写的:
public void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    response.setContentType("text/html;charset=utf-8");
    //接收用户购买书的名字
    String id = request.getParameter("id");
    String name = DB.getBookById(id).getName();
    HttpSession session = request.getSession();
    // 用HashMap更简单
    // 从session中得到购买的 书
    HashMap<String,Book> books = (HashMap<String,Book>) session.getAttribute("books");
    if(books == null){
        books = new LinkedHashMap<String,Book>();
    }
    if(books.containsKey(id)){
        Book book = books.get(id);
        book.setNum(book.getNum()+1);
    }else{
        Book book = new Book(id, name, 1);
        books.put(id, book);
    }
    session.setAttribute("books", books);
    // 转发到ShowMyCart查看购物车  
    request.getRequestDispatcher("/ShowMyCart").forward(request, response);
}1
我们接收到书的id后,然后从Session中取出保存购物车信息的HashMap,如果这个HashMap为空,则新建一个HashMap;如果这个HashMap不为空,则去查找是否存在该书的ID号,如果已经存在,说明之前已经购买过该书,则将这本书的数量加1,,反之将新购买的书添加进去,并且数量设置为1。
看一下运行结果:
1.ShowBook的页面:

2.点击购买之后跳转到购物车的页面:


--------------------------------------------------------------------------------

以上是应用Session的三个简单的例子,在实际项目中,肯定不止这么简单,比如购物车,最终肯定是要存储在数据库中的。
===================================================


servlet 安全学习代码:

第二种方式是:同步共享数据(加锁)
对要被获取的对象加锁,保证同一时间只能有一个线程访问这个对象。关键字Synchronized。

其中的代码就变成了这个样子:
username=request.getParameter("username");
synchronized(this){
output=response.getWriter();
try {
//为了突出并发问题,在这设置一个延时
Thread.sleep(5000);
output.println("用户名:"+username+"<BR>");
} catch (Exception e) {
e.printStackTrace();

把response这个对象加锁,保证在同一时间只能有一个对象能操作response及其操作。

 

第三种方式是:使用局部变量而不是实例变量
 在刚才写的Servlet类中,因为我们使用两个不同的线程去获取request对象(servlet的内置对象),并且打印出每个user的username,所以造成了输出的错误。
如果把request对象写在方法体中,那么就变成:
@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String username;
PrintWriter output;
运行了几次没有出现错误。
把每个线程的休眠时间增加。
Thread.sleep(10000);
连续运行。

自动提示当前的request对象还没有释放,没有结束。问题解决。

 

究竟最后的两种方法哪种更好呢?思考一下。
一种是同步我们的要操作的对象;一种是使用局部对象。
个人感觉还是局部对象更胜一筹,因为我们不能每次都确切的知道需要同步的对象,而且需要手动的去添加同步方法,相比之下使用局部对象就方便的多了。
如果程序必须使用全局变量时,我们还有同步方法可以使用,不是吗?总会有办法的。
ps:
类变量是类中独立于方法之外的变量,用static 修饰。
实例变量也是独立于方法之外的变量,没用static修饰,也就是对着对象实例化而初始化。
方法变量时在方法之内声明的变量,生命周期与方法一致。

 

 

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

有参考价值的代码:
CSDN新首页上线啦,邀请你来立即体验! 旧版 立即体验
  博客学院下载更多
论坛问答活动码云商城  ?写博客 ?发布Chat 登录注册设置昵称主页消息设置反馈退出
  Java Servlet 开发常用代码、模板、问题 原创 2016年03月17日 17:30:11  标签:
java web /servlet /.1256编辑
删除
.一 空Servlet类模板import java.io.IOException;
mport java.io.PrintWriter;


import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


public class ServletDemo1 extends HttpServlet {


    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {


    }


    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {


    }


}

 

二 web.xml配置   <servlet>
     <servlet-name>ServletDemo1</servlet-name>
     <servlet-class>xxx.yyy.zzz.ServletDemo1</servlet-class>
   </servlet>
 
   <servlet-mapping>
     <servlet-name>ServletDemo1</servlet-name>
     <url-pattern>/servlet/ServletDemo1</url-pattern>
   </servlet-mapping>


    <servlet-mapping>
     <servlet-name>ServletDemo1</servlet-name>
     <url-pattern>/*</url-pattern>
   </servlet-mapping>


/abc/*
/*
/abc
*.do


    <servlet>
        <servlet-name>invoker</servlet-name>
        <servlet-class>
            org.apache.catalina.servlets.InvokerServlet
        </servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>


如果某个Servlet的映射路径仅仅为一个正斜杠(/),那么这个Servlet就成为当前Web应用程序的缺省Servlet。
凡是在web.xml文件中找不到匹配的<servlet-mapping>元素的URL,它们的访问请求都将交给缺省Servlet处理,
  <servlet>
     <servlet-name>ServletDemo2</servlet-name>
     <servlet-class>xxx.yyy.zzz.ServletDemo2</servlet-class>
     <load-on-startup>1</load-on-startup>
   </servlet>
  
   <!-- 将ServletDemo2配置成缺省Servlet -->
   <servlet-mapping>
     <servlet-name>ServletDemo2</servlet-name>
     <url-pattern>/</url-pattern>
   </servlet-mapping>


在<tomcat的安装目录>\conf\web.xml文件中,注册了一个名称为org.apache.catalina.servlets.DefaultServlet的Servlet,并将这个Servlet设置为了缺省Servlet。

 

三 Servlet的线程安全问题  当多个客户端并发访问同一个Servlet时,web服务器会为每一个客户端的访问请求创建一个线程,并在这个线程上调用Servlet的service方法,因此service方法内如果访问了同一个资源的话,就有可能引发线程安全问题。


不存在线程安全问题的代码:


public class ServletDemo3 extends HttpServlet {
 
    
     public void doGet(HttpServletRequest request, HttpServletResponse response)
             throws ServletException, IOException {
        
         /**
          * i变量被多个线程并发访问,但是没有线程安全问题,因为i是doGet方法里面的局部变量,
          * 当有多个线程并发访问doGet方法时,每一个线程里面都有自己的i变量,
          * 各个线程操作的都是自己的i变量,所以不存在线程安全问题
          * 多线程并发访问某一个方法的时候,如果在方法内部定义了一些资源(变量,集合等)
          * 那么每一个线程都有这些东西,所以就不存在线程安全问题了
          */
         int i=1;
         i++;
         response.getWriter().write(i);
     }
 
     public void doPost(HttpServletRequest request, HttpServletResponse response)
             throws ServletException, IOException {
         doGet(request, response);
     }
 
 }


存在线程安全问题的代码:
 public class ServletDemo3 extends HttpServlet {
 
     int i=1;
     public void doGet(HttpServletRequest request, HttpServletResponse response)
             throws ServletException, IOException {
       
         i++;
         try {
             Thread.sleep(1000*4);
         } catch (InterruptedException e) {
             e.printStackTrace();
         }
         response.getWriter().write(i+"");
     }
 
     public void doPost(HttpServletRequest request, HttpServletResponse response)
             throws ServletException, IOException {
         doGet(request, response);
     }
 
 }


  把i定义成全局变量,当多个线程并发访问变量i时,就会存在线程安全问题了;同时开启两个浏览器模拟并发访问同一个Servlet,本来正常来说,第一个浏览器应该看到2,而第二个浏览器应该看到3的,结果两个浏览器都看到了3。
    如何解决?


public class ServletDemo3 extends HttpServlet {
 
     int i=1;
     public void doGet(HttpServletRequest request, HttpServletResponse response)
             throws ServletException, IOException {
         /**
          * 加了synchronized后,并发访问i时就不存在线程安全问题了,
          * 假如现在有一个线程访问Servlet对象,那么它就先拿到了Servlet对象的那把锁
          * 等到它执行完之后才会把锁还给Servlet对象,由于是它先拿到了Servlet对象的那把锁,
          * 所以当有别的线程来访问这个Servlet对象时,由于锁已经被之前的线程拿走了,后面的线程只能排队等候了
          *
          */
         synchronized (this) {//在java中,每一个对象都有一把锁,这里的this指的就是Servlet对象
             i++;
             try {
                 Thread.sleep(1000*4);
             } catch (InterruptedException e) {
                 e.printStackTrace();
             }
             response.getWriter().write(i+"");
         }
        
     }
 
     public void doPost(HttpServletRequest request, HttpServletResponse response)
             throws ServletException, IOException {
         doGet(request, response);
     }
 
 }


  现在这种做法是给Servlet对象加了一把锁,保证任何时候都只有一个线程在访问该Servlet对象里面的资源,这样就不存在线程安全问题了
    这种做法虽然解决了线程安全问题,但是编写Servlet却不能用这种方式处理线程安全问题,假如有9999个人同时访问这个Servlet,那么这9999个人必须按先后顺序排队轮流访问。


  针对Servlet的线程安全问题,Sun公司提供有解决方案的:让Servlet去实现一个SingleThreadModel接口,如果某个Servlet实现了SingleThreadModel接口,那么Servlet引擎将以单线程模式来调用其service方法。
  查看Sevlet的API可以看到,SingleThreadModel接口中没有定义任何方法和常量,在Java中,把没有定义任何方法和常量的接口称之为标记接口,经常看到的一个最典型的标记接口就是"Serializable",这个接口也是没有定义任何方法和常量的,标记接口在Java中有什么用呢?主要作用就是给某个对象打上一个标志,告诉JVM,这个对象可以做什么,比如实现了"Serializable"接口的类的对象就可以被序列化,还有一个"Cloneable"接口,这个也是一个标记接口,在默认情况下,Java中的对象是不允许被克隆的,就像现实生活中的人一样,不允许克隆,但是只要实现了"Cloneable"接口,那么对象就可以被克隆了。


  让Servlet实现了SingleThreadModel接口,只要在Servlet类的定义中增加实现SingleThreadModel接口的声明即可。 
  对于实现了SingleThreadModel接口的Servlet,Servlet引擎仍然支持对该Servlet的多线程并发访问,其采用的方式是产生多个Servlet实例对象,并发的每个线程分别调用一个独立的Servlet实例对象。
  实现SingleThreadModel接口并不能真正解决Servlet的线程安全问题,因为Servlet引擎会创建多个Servlet实例对象,而真正意义上解决多线程安全问题是指一个Servlet实例对象被多个线程同时调用的问题。事实上,在Servlet API 2.4中,已经将SingleThreadModel标记为Deprecated(过时的)。 

 


四 常用功能代码

1 hello world
  public void init() throws ServletException
  {
      message = "Hello World";
  }


  public void doGet(HttpServletRequest request,
                    HttpServletResponse response)
            throws ServletException, IOException
  {


      response.setContentType("text/html");
      PrintWriter out = response.getWriter();
      out.println("<h1>" + message + "</h1>");
  }


2 在客户端输出一个html文档        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
        out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">");
        out.println("<HTML>");
        out.println("  <HEAD><TITLE>A Servlet</TITLE></HEAD>");
        out.println("  <BODY>");
        out.print("    This is ");
        out.print(this.getClass());
        out.println(", using the GET method");
        out.println("  </BODY>");
        out.println("</HTML>");
        out.flush();
        out.close();

 

3 处理用户登陆的servlet实现方法
Login.java

package com.bai;
 
import javax.servlet.http.*;
import java.io.*;
 
public class Login extends HttpServlet{
     public void doGet(HttpServletRequest req,HttpServletResponse res){
         try{req.setCharacterEncoding("gb2312");
         res.setContentType("text/html;charset=gb2312");
             PrintWriter pw=res.getWriter();
             pw.println("<html>");
             pw.println("<body>");
             pw.println("<h1>登陆界面</h1>");
             pw.println("<form action=logincl method=post>");
             pw.println("用户名:<input type=text name=username><br>");
             pw.println("密码:<input type=password name=passwd><br>");
             pw.println("<input type=submit value=login><br>");
             pw.println("</form>");
             pw.println("</body>");
             pw.println("</html>");
         }
         catch(Exception e){
             e.printStackTrace();
         }
     }
    
    public void doPost(HttpServletRequest req,HttpServletResponse res){
         this.doGet(req,res);
     }
 }
 
LoginCl.java

package com.bai;
 
import javax.servlet.http.*;
import java.io.*;
import java.sql.*;
 
public class LoginCl extends HttpServlet{
     public void doGet(HttpServletRequest req,HttpServletResponse res){
        
         Connection conn=null;
         Statement stmt=null;
         ResultSet rs=null;
         String sql = "select username,passwd from users where username = ? and passwd = ?";
         try{//req.setCharacterEncoding("gb2312");
             String user=req.getParameter("username");
             String password=req.getParameter("passwd");
            
            Class.forName("com.mysql.jdbc.Driver");
             conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/sqdb","root","root");
 //            stmt=conn.createStatement();
             PreparedStatement pstmt = conn.prepareStatement(sql);
             pstmt.setString(1, user);
             pstmt.setString(2, password);
             rs = pstmt.executeQuery();
 //            rs=stmt.executeQuery("select top 1 * from users where username='"+user
 //                +"' and passwd='"+password+"'");
             if(rs.next())
             {
                 HttpSession hs=req.getSession(true);
                 hs.setMaxInactiveInterval(60);
                 hs.setAttribute("name",user);
                 res.sendRedirect("welcome?&uname="+user+"&upass="+password);
             }
             else{
                 res.sendRedirect("login"); //url
             }
            
        }
         catch(Exception e){
             e.printStackTrace();
         }finally{
             try{
                 if(rs!=null){
                 rs.close();
                 }
                 if(stmt!=null){
                     stmt.close();
                 }
                 if(conn!=null){
                     conn.close();
                 }   
            }catch(Exception e){
                 e.printStackTrace();
             }       
        }
     }
    
    public void doPost(HttpServletRequest req,HttpServletResponse res){
         this.doGet(req,res);
     }
 }
 
注:
上面这个处理用户名密码带有明显注入漏洞,可以根据用户名从数据库取密码,用取出的密码和用户输入的密码比较


sql=select passwd from users where username = ?  limit 1
if(rs.next())
 {
     String passwd=rs.getString(1);
     if(passwd.equals(password))
             //密码正确
     else //密码错误
 }


Welcome.java

package com.bai;
 
import javax.servlet.http.*;
import java.io.*;
 
public class Welcome extends HttpServlet{
     public void doGet(HttpServletRequest req,HttpServletResponse res){
        
        HttpSession hs=req.getSession();
         String val=(String)hs.getAttribute("pass");
        
        if(val==null){
             try{
                 System.out.print(1);
                 res.sendRedirect("login");
             }catch(Exception e){
                 e.printStackTrace();
             }
            
        }       
           
        String u=req.getParameter("uname");
         String p=req.getParameter("upass");
        
        try{//req.setCharacterEncoding("gb2312");
             PrintWriter pw=res.getWriter();
             pw.println("welcome! "+u+"&pass="+p);
         }
         catch(Exception e){
             e.printStackTrace();
         }
     }
    
    public void doPost(HttpServletRequest req,HttpServletResponse res){
         this.doGet(req,res);
     }
 }


4 servlet中session在servlet中,session是封装在javax.servlet.http.HttpSession这个接口中的,这个接口是构建在cookie或者URL重写的基础上,要得到一个HttpSession的实例,就可以通过HttpServletRequest的getSession()方法来获得
HttpServletRequest有两个重载的getSession()方法,一个接受一个boolean的类型的值,另一个不带任何参数,getSession()方法和getSession(true)方法功能一样,就是如果对应的客户端已经产生过一个session,那么就会返回这个旧的session,否则,这个方法将会产生一个session ID并且和对应的客户端绑定在一起,而如果getSession(false)表示如果对应的客户端已经有对应的session,那么返回这个旧的session,否则不会产生新的session。可以使用HttpSession对象上的isNow()方法来判定这个session是否为新建的
 
HttpSession常用方法
 
public void setAttribute(String name,Object value)
将value对象以name名称绑定到会话

public object getAttribute(String name)
取得name的属性值,如果属性不存在则返回null

public void removeAttribute(String name)
从会话中删除name属性,如果不存在不会执行,也不会抛处错误.

public Enumeration getAttributeNames()
返回和会话有关的枚举值

public void invalidate()
使会话失效,同时删除属性对象

public Boolean isNew()
用于检测当前客户是否为新的会话

public long getCreationTime()
返回会话创建时间

public long getLastAccessedTime()
返回在会话时间内web容器接收到客户最后发出的请求的时间

public int getMaxInactiveInterval()
返回在会话期间内客户请求的最长时间为秒

public void setMaxInactiveInterval(int seconds)
允许客户客户请求的最长时间

ServletContext getServletContext()
返回当前会话的上下文环境,ServletContext对象可以使Servlet与web容器进行通信

public String getId()
返回会话期间的识别号
 
一个保存信息到session的例子
 
sessionlogin.html

<meta name="keywords" content="keyword1,keyword2,keyword3" />
<meta name="description" content="this is my page" />
<meta name="content-type" content="text/html; charset=UTF-8" />

 <!--    <link rel="stylesheet" type="text/css" href="./styles.css">--></pre>
<form action="servlet/saveinfo" method="post">
 用户名:
 <input type="text" name="username" /> <input type="submit" />
 密码:
 <input type="password" name="userpasswd" />
 </form>
<pre>
</pre>
</div>
<div>


package xxx;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class saveinfo extends HttpServlet {

 public saveinfo() {
 super();
 }

 public void destroy() {
 super.destroy(); // Just puts "destroy" string in log
 // Put your code here
 }

 public void doGet(HttpServletRequest request, HttpServletResponse response)
 throws ServletException, IOException {

 //如果用户输入过了用户名 则将其放在session中
 if(request.getParameter("username")!=null);
 {
 HttpSession session = request.getSession();
 session.setAttribute("username",request.getParameter("username"));
 }
 response.setContentType("text/html;charset=GBK");
 PrintWriter out = response.getWriter();
 out.println("session已经创建");
 out.println("
");
 out.println("跳转到其他<a>页面</a>");

 }

 public void doPost(HttpServletRequest request, HttpServletResponse response)
 throws ServletException, IOException {

 doGet(request,response);
 }

 public void init() throws ServletException {
 // Put your code here
 }

}

package xxx;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class getsession extends HttpServlet {

 public getsession() {
 super();
 }

 public void destroy() {
 super.destroy(); // Just puts "destroy" string in log
 // Put your code here
 }

 public void doGet(HttpServletRequest request, HttpServletResponse response)
 throws ServletException, IOException {

response.setContentType("text/html;charset=GBK");
 PrintWriter out = response.getWriter();

 String username = "";
 //此处不是创建session 而是去取已经创建的session
 HttpSession session = request.getSession();
 //如果已经取到,说明已经登录
 if(session!=null)
 {
 username = (String)session.getAttribute("username");
 out.println("获得创建的Session");
 out.println("
");
 out.println("登录名:"+username);
 }
 else
 {
 response.sendRedirect("../sessionlogin.html");
 }
 }

 public void doPost(HttpServletRequest request, HttpServletResponse response)
 throws ServletException, IOException {
 doGet(request,response);
 }

 public void init() throws ServletException {
 // Put your code here
 }

}


5 获得客户端IP和url可以配合实现IP白名单控制,

import javax.servlet.http.HttpServletRequest;
 
public class ClientInfoUtil{
 
/**
* 获得客户端的IP地址
* @param request
* @return
*/
static public String getIP(HttpServletRequest request) {
    String ip = request.getHeader("x-forwarded-for");
    if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
        ip = request.getHeader("Proxy-Client-IP");
    }
    if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
        ip = request.getHeader("WL-Proxy-Client-IP");
    }
    if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
        ip = request.getRemoteAddr();
    }
    return ip;
}
 

/**
* 获得客户端访问服务器的url地址
* @param request
* @return
*/
static public String getURL(HttpServletRequest request) {
    String url = request.getScheme()+"://";  
    url+=request.getHeader("host");  
    url+=request.getRequestURI();  
    if(request.getQueryString()!=null)  {
        url+="?"+request.getQueryString();  
    }
    return url;
}
}


6 JSP+Servlet+JavaBean实现登录登录页面:login.html
登录成功欢迎页面:login_success.jsp
登录失败页面:login_failure.jsp
Servlet处理文件:LoginServlet.java
 
登录页面:login.html

<!-- 一个简单的登录界面 --><!-- 该JSP程序是用来测试与MySQL数据库的连接, 需要一个数据库:LearnJSP,和其中一个表:userinfo 表中有两个字段分别为:UserName varchar (20) not null,UserPwd varchar (20) not null--><html> <head>  <title>登录</title>  <meta http-equiv="content-type" content="text/html; charset=UTF-8">  <meta http-equiv="Content-Language" content="ch-cn"> </head> <body> <!-- Form 用来提取用户填入并提交的信息--> <form method="post" name="frmLogin" action="LoginServlet">  <h1 align="center">用户登录</h1><br>  <div align="center">用户名:   <input type="text" name="txtUserName" value="Your name"    size="20" maxlength="20"    οnfοcus="if(this.value=='Your name')this.value='';"><br>密码:   <input type="password" name="txtPassword" value="Your password"    size="20" maxlength="20"    οnfοcus="if(this.value=='Your password')this.value='';"><br>   <input type="submit" name="Submit" value="提交" onClick="validateLogin();" >             <input type="reset" name="Reset" value="重置"><br>  </div> </form> <!-- javaScript 函数 validateLogin(),用来验证用户名和密码是否为空 -->  <script language="javaScript">   function validateLogin()   {   var sUserName = document.frmLogin.txtUserName.value;   var sPassword = document.frmLogin.txtPassword.value;   if( sUserName=="" )   {    alert("请输入用户名!");    return false;   }   if( sPassword=="" )   {    alert("请输入密码!");    return false;   }   }  </script> </body></html>

登录成功欢迎页面:login_success.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html> <head> <title>My JSP 'login_failure.jsp' starting page</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> <%  String userName = (String)session.getAttribute ( "UserName" ); %> <div align=center>  <%=userName%>  欢迎您,登录成功! </div> </body></html>


登录失败页面:login_failure.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html> <head> <title>My JSP 'login_failure.jsp' starting page</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> <% String userName = (String)session.getAttribute ( "UserName" ); %> <div align=center>  <%=userName%>  对不起,登录失败! </div> </body></html>


Servlet处理文件:LoginServlet.java
/** * 该JSP程序是用来测试与MySQL数据库的连接, * 需要一个数据库:LearnJSP,和其中一个表:userinfo * 表中有两个字段分别为:UserName varchar (20) not null,UserPwd varchar (20) not null */package zieckey.login.servlet;import java.sql.Statement;import java.io.IOException;import java.sql.DriverManager;import java.sql.ResultSet;import java.sql.SQLException;import javax.servlet.Servlet;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class LoginServlet extends HttpServlet implements Servlet{ public LoginServlet () { // TODO Auto-generated constructor stub } /* * (non-Javadoc) * * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, * javax.servlet.http.HttpServletResponse) */ @Override protected void doGet ( HttpServletRequest arg0, HttpServletResponse arg1 )  throws ServletException, IOException { } /* * (non-Javadoc) * * @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest, * javax.servlet.http.HttpServletResponse) */ @Override protected void doPost ( HttpServletRequest request, HttpServletResponse response )  throws ServletException, IOException { response.setContentType ( "text/html" ); String result = ""; // 获取用户名 String sUserName = request.getParameter ( "txtUserName" ); if ( sUserName == "" || sUserName == null || sUserName.length ( ) > 20 ) {  try  {  result = "请输入用户名(不超过20字符)!";  request.setAttribute ( "ErrorUserName", result );  response.sendRedirect ( "login.html" );  } catch ( Exception e )  {  } } // 获取密码 String sPasswd = request.getParameter ( "txtPassword" ); if ( sPasswd == "" || sPasswd == null || sPasswd.length ( ) > 20 ) {  try  {  result = "请输入密码(不超过20字符)!";  request.setAttribute ( "ErrorPassword", result );  response.sendRedirect ( "login.html" );  } catch ( Exception e )  {  } } // 登记JDBC驱动程序 try {  Class.forName ( "org.gjt.mm.mysql.Driver" ).newInstance ( ); } catch ( InstantiationException e ) {  // TODO Auto-generated catch block  e.printStackTrace ( );  System.out.println ("InstantiationException"); } catch ( IllegalAccessException e ) {  // TODO Auto-generated catch block  e.printStackTrace ( );  System.out.println ("IllegalAccessException"); } catch ( ClassNotFoundException e ) {  // TODO Auto-generated catch block  e.printStackTrace ( );  System.out.println ("ClassNotFoundException"); } // 连接参数与Access不同 String url = "jdbc:mysql://localhost/LearnJSP"; // 建立连接 java.sql.Connection connection = null; Statement stmt = null; ResultSet rs = null; try {  connection = DriverManager.getConnection ( url, "root", "011124" );  stmt = connection.createStatement ( );  // SQL语句  String sql = "select * from userinfo where username='" + sUserName   + "' and userpwd = '" + sPasswd + "'";  rs = stmt.executeQuery ( sql );// 返回查询结果 } catch ( SQLException e ) {  // TODO Auto-generated catch block  e.printStackTrace ( ); } try {  if ( rs.next ( ) )// 如果记录集非空,表明有匹配的用户名和密码,登陆成功  {  // 登录成功后将sUserName设置为session变量的UserName  // 这样在后面就可以通过 session.getAttribute("UserName") 来获取用户名,  // 同时这样还可以作为用户登录与否的判断依据  request.getSession ( ).setAttribute ( "UserName", sUserName );  response.sendRedirect ( "login_success.jsp" );  } else  {  // 否则登录失败  //response.sendRedirect ( "MyJsp.jsp" );  response.sendRedirect ( "login_failure.jsp" );  } } catch ( SQLException e ) {  // TODO Auto-generated catch block  e.printStackTrace ( ); } try {  if ( null!=rs )  {  rs.close ( );  }  if ( null!=stmt )  {  stmt.close ( );  }  if ( null!=connection )  {  connection.close ( );  } } catch ( SQLException e ) {  // TODO Auto-generated catch block  e.printStackTrace ( ); } } /** * */ private static final long serialVersionUID = 1L;}


7 java servlet页面跳转 response.sendRedirect("/a.jsp");
response.sendRedirect("http://www.jb51.net");

RequestDispatcher dispatcher = request.getRequestDispatcher("/a.jsp");
dispatcher .forward(request, response);

response.setHeader("Location","");


8 java中Servlet处理乱码
1)从页面获取数据的servlet出现乱码,在servlet中已经把request.setCharacterEncoding("GB2312");加入到代码中去,
JAVA是Unicode编码,先转换成ISO8859-1,然后再转换成GBK或是GB2312.

request.setCharacterEncoding("ISO8859-1");   
ad=request.getParameter("name");   
byte[] temp3 = ad.getBytes("GBK");   
String str = new String(temp3);  

这样就是中文啦

2)直接在服务器里设置编码转换
在Tomcat的conf目录里找到SERVER.XML文件,设置如下:
里面增加一个属性,URIEncoding="GBK"

3)JSP页面上是中文,但是看的后是乱码
解决的办法就是在JSP页面的编码的地方,因为Jsp转成Java文件时的编码问题,默认的话有的服务器是ISO-8859-1,如果一个JSP中直接输入了中文,Jsp把它当作 ISO8859-1来处理是肯定有问题的,这一点,我们可以通过查看Jasper所生成的Java中间文件来确认
 
4)当用Request对象获取客户提交的汉字代码的时候,会出现乱码
解决的办法是:要配置一个filter,也就是一个Servelet的过滤器,

代码如下:

public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain)throws IOException, ServletException {

request.setCharacterEncoding("GBK");
// 传递控制到下一个过滤器

chain.doFilter(request, response);
}

配置web.xml
<filter></filter>
<filter-name></filter-name>Set Character Encoding
<filter-class></filter-class>SetCharacterEncodingFilter
 
<filter-mapping></filter-mapping>
<filter-name></filter-name>Set Character Encoding
<url-pattern></url-pattern>/*

如果还是出现这种情况的话就往下看看是不是出现了第四种情况,Form提交的数据是不是用get提交的,一般来说用post提交的话是没有问题的,如果是的话,看第四种解决的办法。

还有就是对含有汉字字符的信息进行处理,处理的代码是:
public String toUni(String gbStr){
String uniStr = "";
if(gbStr == null){
gbStr = "";
}
try{
byte[] tempByte = gbStr.getBytes("GB2312");
uniStr = new String(tempByte,"ISO8859_1");
}catch(Exception ex){
}
return uniStr;
}
}

也可以在直接的转换,首先将获取的字符串用ISO-8859-1进行编码,然后将这个编码存放到一个字节数组中,然后将这个数组转化成字符串对象就可以了,
String str=request.getParameter(“girl”);
Byte B[]=str.getBytes(“ISO-8859-1”);
Str=new String(B);
通过上述转换的话,提交的任何信息都能正确的显示。

5)在 Form get请求在服务端用request. getParameter(“name”)时返回的是乱码
按tomcat的做法设置Filter也没有用或者用 request.setCharacterEncoding("GBK");也不管用问题是出在处理参数传递的方法上:如果在servlet中用 doGet(HttpServletRequest request, HttpServletResponse response)方法进行处理的话前面即使是写了:

request.setCharacterEncoding("GBK");
response.setContentType("text/html;charset=GBK");

也是不起作用的,返回的中文还是乱码.
如果把这个函数改成doPost(HttpServletRequest request, HttpServletResponse response)一切就OK了。
同样,在用两个JSP页面处理表单输入之所以能显示中文是因为用的是post方法传递的,改成get方法依旧不行。
由此可见在servlet中用doGet()方法或是在JSP中用get方法进行处理要注意。这毕竟涉及到要通过浏览器传递参数信息,很有可能引起常用字符集的冲突或是不匹配。
这个地方理解为request.setCharacterEncoding("GBK");set的是request中的body,而不是header部分,get请求时把参数放在url后边,不是放在body中,所以这个时候request.setCharacterEncoding("GBK")就没有起到作用,换到post提交就没有问题了,
解决的办法是:
1) 打开tomcat的server.xml文件,找到区块,加入如下一行:
URIEncoding=”GBK”

完整的应如下:
<connector uriencoding="GBK" maxthreads="150" debug="0" redirectport="8443" port="8080" enablelookups="false" maxsparethreads="75" minsparethreads="25" connectiontimeout="20000" disableuploadtimeout="true" acceptcount="100"></connector>

重启tomcat,一切OK。

6)JSP页面上有中文,按钮上面也有中文,但是通过服务器查看页面的时候出现乱码
解决的办法是:首先在JSP文件中不应该直接包含本地化的消息文本,而是应该通过<bean:message>标签从Resource Bundle中获得文本。应该把中文文本放到Application.properties文件中,这个文件放在WEB-INF/classes/* 下,例如页面里有姓名,年龄两个label,首先就是要建一个Application.properties,里面的内容应该是name=”姓名” age=”年龄”,然后把这个文件放到WEB-INF/classes/properties/下,接下来根据 Application.properties文件,对他进行编码转化,创建一个中文资源文件,假定名字是 Application_cn.properties。在JDK中提供了native2ascii命令,能够实现字符编码的转换。在DOS环境中找到你放置Application.properties的这个文件的目录,在DOS环境中执行一下命令,将生成按GBK编码的中文资源文件 Application_cn.properties:native2ascii ?encoding gbk Application.properties Application_cn.properties执行以上命令以后将生成如下内容的Application_cn.properties文件: name=u59d3u540d age=u5e74u9f84,在Struts-config.xml中配置:<message-resources parameter="properties.Application_cn"></message-resources>。到这一步,基本上完成了一大半,接着就要在JSP页面上写,到名字的那个label是要写<bean:message key="”name”">,这样的化在页面上出现的时候就会出现中文的姓名,年龄这个也是一样,按钮上汉字的处理也是同样的。
 
7)写入到数据库是乱码
解决的方法:要配置一个filter,也就是一个Servelet的过滤器,代码如同第二种时候一样。
如果是通过JDBC直接链接数据库的时候,配置的代码如下:jdbc:mysql://localhost:3306/workshopdb? useUnicode=true&characterEncoding=GBK,这样保证到数据库中的代码是不是乱码。
如果是通过数据源链接的话不能按照这样的写法了,首先就要写在配置文件中,

<context debug="0" path="/workshop" docbase="workshop"></context>reloadable="true" >
 
<resource name="jdbc/WorkshopDB"></resource>auth="Container"
type="javax.sql.DataSource" />
 
<resourceparams name="jdbc/WorkshopDB"></resourceparams>
<parameter></parameter>
<name></name>factory
<value></value>org.apache.commons.dbcp.BasicDataSourceFactory
 
<parameter></parameter>
<name></name>maxActive
<value></value>100
 
<parameter></parameter>
<name></name>maxIdle
<value></value>30
 
<parameter></parameter>
<name></name>maxWait
<value></value>10000
 
<parameter></parameter>
<name></name>username
<value></value>root
 
<parameter></parameter>
<name></name>password
<value></value>
 
<parameter></parameter>
<name></name>driverClassName
<value></value>com.mysql.jdbc.Driver
 
<parameter></parameter>
<name></name>url
<value></value>

 

8)servlet分页Oracle数据库,获取SCOTT用户EMP表中的数据,

创建一个对象 UserData,用以保存从数据库中获取的数据。

package com.tool;
 
import java.math.BigDecimal;
import java.util.Date;
 
public class UserData {
 
    /**
     * EMP表中的数据属性
     */
    private String ename;
    private String job;
    private BigDecimal empno;
    private BigDecimal mgr;
    private Date hireDate;
    private BigDecimal sal;
    private BigDecimal comm;
    private BigDecimal deptno;
 
    public BigDecimal getEmpno() {
        return empno;
    }
 
    public void setEmpno(BigDecimal empno) {
        this.empno = empno;
    }
 
    public BigDecimal getMgr() {
        return mgr;
    }
 
    public void setMgr(BigDecimal mgr) {
        this.mgr = mgr;
    }
 
    public Date getHireDate() {
        return hireDate;
    }
 
    public void setHireDate(Date hireDate) {
        this.hireDate = hireDate;
    }
 
    public BigDecimal getSal() {
        return sal;
    }
 
    public void setSal(BigDecimal sal) {
        this.sal = sal;
    }
 
    public BigDecimal getComm() {
        return comm;
    }
 
    public void setComm(BigDecimal comm) {
        this.comm = comm;
    }
 
    public BigDecimal getDeptno() {
        return deptno;
    }
 
    public void setDeptno(BigDecimal deptno) {
        this.deptno = deptno;
    }
 
    public String getEname() {
        return ename;
    }
 
    public void setEname(String ename) {
        this.ename = ename;
    }
 
    public String getJob() {
        return job;
    }
 
    public void setJob(String job) {
        this.job = job;
    }
}


创建一个 DBHelper 对象用以与数据库进行交互

package com.dao;
 
import com.tool.UserData;
 
import java.math.BigDecimal;
import java.sql.*;
import java.util.*;
import java.util.Date;
 
public class DBHelper {
 
    Connection conn;  //数据库连接对象
    PreparedStatement pt;  //SQL语句预处理对象
    ResultSet rs;  //结果集对象
 
    public  DBHelper(){
        try {
            Class.forName("oracle.jdbc.driver.OracleDriver");  //装载驱动
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
 
    /**
     * 获取当前页的数据
     * @param curPage
     * @param rowsPerPage
     * @return
     */
    public List<UserData> getData(int curPage, int rowsPerPage) {
 
        List<UserData> dataList = new ArrayList<>();
        String url = "jdbc:oracle:thin:@localhost:1521:orcl";
        try {
            conn = DriverManager.getConnection(url,"scott","tiger");
            String sql = "select * from emp where rownum <= ((? - 1) * "+rowsPerPage+" + "+rowsPerPage+") minus " +
                    " select * from emp where rownum <= (? - 1) * "+rowsPerPage+" ";
            pt = conn.prepareStatement(sql);
            pt.setInt(1,curPage);
            pt.setInt(2,curPage);
            rs = pt.executeQuery();
            while (rs.next()){
                /**
                 * 从结果集中取得数据
                 */
                UserData userData = new UserData();
                BigDecimal empno = rs.getBigDecimal("empno");
                String ename = rs.getString("ename");
                String job = rs.getString("job");
                BigDecimal mgr = rs.getBigDecimal("mgr");
                Date hireDate = rs.getDate("hiredate");
                BigDecimal sal = rs.getBigDecimal("sal");
                BigDecimal comm = rs.getBigDecimal("comm");
                BigDecimal deptno = rs.getBigDecimal("deptno");
                /**
                 * 设置对象属性
                 */
                userData.setEmpno(empno);
                userData.setEname(ename);
                userData.setJob(job);
                userData.setMgr(mgr);
                userData.setHireDate(hireDate);
                userData.setSal(sal);
                userData.setComm(comm);
                userData.setDeptno(deptno);
                dataList.add(userData);  //把对象添加集合中
            }
            rs.close();
            pt.close();
            conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return dataList;
    }
 
    /**
     * 返回总页数
     * @return
     */
    public int getMaxPage(int rowsPerPage) {
        int maxPage;
        int maxRowCount = 0;
        String url = "jdbc:oracle:thin:@localhost:1521:orcl";
        try {
            conn = DriverManager.getConnection(url,"scott","tiger");  //创建数据库连接
            String sql = "select count(*) from emp";
            pt = conn.prepareStatement(sql);
            rs = pt.executeQuery();
            if (rs.next()){
                maxRowCount = rs.getInt(1);  //总行数
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        maxPage = (maxRowCount + rowsPerPage - 1) / rowsPerPage;  //总页数
        return maxPage;
    }
}

创建 Servlet 对显示页面进行控制

package com.servlet;
 
import com.dao.DBHelper;
import com.tool.UserData;
 
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
 
public class Servlet extends HttpServlet {
 
    public int rowsPerPage;  //每页显示的行数
    public int curPage;  //当前页页码
    public int maxPage;  //总共页数
    DBHelper db = new DBHelper();
    public Servlet(){
        rowsPerPage = 5;
    }
 
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String curPage1 = request.getParameter("page");  //获取当前页页码
        if (curPage1 == null){
            curPage = 1;
            request.setAttribute("curPage",curPage);  //设置curPage对象
        }else {
            curPage = Integer.parseInt(curPage1);
            if (curPage < 1){
                curPage = 1;
            }
            request.setAttribute("curPage",curPage);
        }
 
        List<UserData> dataList;
        dataList = db.getData(curPage,rowsPerPage);  //获取当前页的数据
        maxPage = db.getMaxPage(rowsPerPage);  //获取总页数
        request.setAttribute("dataList",dataList);
        request.setAttribute("maxPage", maxPage);
 
        RequestDispatcher rd = request.getRequestDispatcher("pagemain.jsp");  //将请求转发到pagemain.jsp页面
        rd.forward(request,response);
    }
 
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request,response);
    }
}

创建 JSP 页面,显示数据。

<%@ page import="java.util.List" %>
<%@ page import="com.tool.UserData" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>servlet数据分页</title>
    <link rel="stylesheet" type="text/css" href="css.css">
</head>
<body>
<div style="margin-top: 15%; margin-left: 25%">
    <table>
        <caption>SCOTT用户,EMP表中的数据</caption>
        <%! int curPage,maxPage; %>
        <% curPage =Integer.parseInt(request.getAttribute("curPage").toString()); %> <!--取得当前页-->
        <% maxPage =Integer.parseInt((String)request.getAttribute("maxPage").toString()); %> <!--取得总页数-->
        <%if (request.getAttribute("dataList") == null){
        %>
        <tr>
            <td colspan="8">没有数据</td>
        </tr>
        <%
        }else {
        %>
        <tr>
            <!--表头-->
            <th>EMPNO</th>
            <th>ENAME</th>
            <th>JOB</th>
            <th>MGR</th>
            <th>HIREDATE</th>
            <th>SAL</th>
            <th>COMM</th>
            <th>DEPTNO</th>
        </tr>
        <%
            List list = (List) request.getAttribute("dataList");
            for (Object aList : list) {
                UserData userData = (UserData) aList;
        %>
        <tr>
            <!--取得表中数据-->
            <td><%= userData.getEmpno() %></td>
            <td><%= userData.getEname() %></td>
            <td><%= userData.getJob() %></td>
            <td><%= userData.getMgr() %></td>
            <td><%= userData.getHireDate() %></td>
            <td><%= userData.getSal() %></td>
            <td><%= userData.getComm() %></td>
            <td><%= userData.getDeptno() %></td>
        </tr>
        <%
                }
            }
        %>
    </table>
</div>
<div style="margin-top: 8%; margin-left: 29%">
    第<%= curPage %>页,共<%= maxPage %>页 
    <%if (curPage > 1){
    %>
    <a href="Servlet?page=1">首页</a>
    <a href="Servlet?page=<%=curPage - 1%>">上一页</a>
    <%
    }else {
    %>
    首页 上一页
    <%
        }%>
    <%if (curPage < maxPage){
    %> 
    <a href="Servlet?page=<%=curPage + 1%>">下一页</a>
    <a href="Servlet?page=<%=maxPage %>">尾页</a>
    <%
    }else {
    %>
    下一页 尾页
    <%
        }%>
      转至第 <form name="form1" action="Servlet" method="get">
    <label>
        <select name="page" οnchange="document.form1.submit()">
            <%for ( int i = 1; i <= maxPage; i++){
                if (i == curPage){
            %>
            <!--当前页页码默认选中-->
            <option selected value="<%= i%>"><%= i %></option>
            <%
            }else {
            %>
            <option value="<%= i %>"><%= i %></option>
            <%
                    }
                }%>
        </select>
    </label>
</form> 页
</div>
</body>
</html>
 
web.xml
    <servlet>
        <servlet-name>Servlet</servlet-name>
        <servlet-class>com.servlet.Servlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>Servlet</servlet-name>
        <url-pattern>/Servlet</url-pattern>
    </servlet-mapping>

阅读全文
版权声明:本文为博主原创文章,未经博主允许不得转载。  本文已收录于以下专栏:.
 目前您尚未登录,请 登录 或 注册 后进行评论.相关文章推荐  jsp/servlet防止刷新/后退引起的重复提交问题的Java Token代码首先是Token主类。类很简单package com.company.util;import java.util.ArrayList;import javax.servlet.http.HttpSes... yuefengyuan2011-06-23 14:01
3693. java web整合开发王者归来光盘代码-servlet章节...2010-08-26 19:35
904KB
下载.
2017中国程序员薪资调查,未来这门语言将持续高薪!
2017年,程序员IT岗位薪酬大曝光!综合程序员的地域/年限/岗位等因素,报告综合显示,未来持续上升的高薪语言竟然是它!万万没想到...
. Servlet的一些技巧&模板代码
Servlet的一些技巧&模板代码 Request相关获得一些基本参数 view sourceprint? 01 //获取提交地址 ...

e_wsq
2011-09-18 01:16
637
. 修改Myeclipse中Servlet和jsp的模板代码
在实际开发中,每次都要手工删除默认模板的注释和代码,很麻烦,因此可以根据开发的实际情况修改Servlet的模板代码,改成符合实际开发需求的模板代码。 1)修改Servlet模板代码: 具体步骤如下...

xlinsist
2014-12-04 19:02
891
. 修改MyEclipse默认的Servlet代码模板
修改Servlet的默认模板代码    使用MyEclipse创建Servlet时,根据默认的Servlet模板生成的Servlet代码如下:   1 package gacl.servlet.st...

huangxingchen123
2016-09-23 16:33
821
. 修改(My)Eclipse默认的Servlet和jsp代码模板
一、修改Servlet的默认模板代码     使用MyEclipse创建Servlet时,根据默认的Servlet模板生成的Servlet代码如下: 1 package gacl.s...

z742182637
2016-01-07 09:32
1466
. Eclipse使用总结——修改(My)Eclipse默认的Servlet和jsp代码模板
一、修改Servlet的默认模板代码     使用MyEclipse创建Servlet时,根据默认的Servlet模板生成的Servlet代码如下: 1 package gacl.s...

i10630226
2015-12-03 19:48
2866
. MyEclipse使用总结——修改MyEclipse默认的Servlet和jsp代码模板
一、修改Servlet的默认模板代码    使用MyEclipse创建Servlet时,根据默认的Servlet模板生成的Servlet代码如下: 1 package gacl.servl...

jiangeeq
2017-04-12 16:07
2703
.
servlet模板(解决中文乱码,删除不必要代码)...
2016-11-13 13:25
224KB
下载
.
Java代码开发常见问题培训...
2013-04-12 14:53
909KB
下载
.           
 Dedecms模板常用调用标签代码整理
Dedecms模板常用调用标签代码整理 1、最新文档列表 1-5都为调用的arclist标签 {dede:arclist typeid='' titlelen='28' row='6...

acbvydl
2014-10-13 09:49
217
.
java常用开发代码2面试
2010-03-29 17:00
12KB
下载
.
java 常用开发代码
2009-05-11 09:54
42KB
下载
. 常用js模板代码-模块化
本例采用面向对象的方式进行封装库函数,对常用的表单验证、注册登录功能进行一些简单的封装。

u013243347
2016-08-24 15:03
778
.
java常用开发代码3,Struts
2010-03-29 17:04
3.23MB
下载
.
利用Swing开发的JAVA常用组件代码
2008-12-02 23:02
1.89MB
下载
. Dedecms模板常用调用标签代码整理
dedecms判断是否有下级栏目,有就显示所有下级栏目,没有就显示同级栏目 Dedecms模板常用调用标签代码整理 1、最新文档列表 1-5都为调用的arclist标签 {dede...

uyoumond
2014-11-15 14:27
279
.
利用Swing开发的JAVA常用组件代码
2011-11-09 16:39
1.89MB
下载
. Eclipse常用快捷键与代码模板
Eclipse常用快捷键与代码模板 Eclipse常用快捷键汇总 Eclipse的编辑功能非常强大,掌握了Eclipse快捷键功能,能够大大提高开发效率。Eclipse中有如下一些和...

zhihui1017
2016-02-17 09:51
272
.
web开发常用200个JS代码_Web开发_Java快速开发_.net快速开发
2011-03-23 15:04
623KB
下载
..  bcbobo21cn
+关注
. 原创
356
粉丝
166
喜欢
0
码云
 
. 他的最新文章
更多文章 .
  css hack 学习总结 .
 CSS居中学习总结 .
 T-SQL游标学习总结 .
 VS调试js学习总结 .
.在线课程
 
免费直播 神经网络的原理及结构设计

讲师:何宇健

 
Apache Weex:移动研发的进阶之路

讲师:董岩

.热门文章
js调试console.log使用总结图解
17391
opencv 图像去噪学习总结
17122
Java 模板引擎总结
15516
opencv形状识别学习总结
14643
opencv动态目标跟踪学习总结
11384.?0
   1. 一 空Servlet类模板2. 二 webxml配置3. 三 Servlet的线程安全问题4. 四 常用功能代码4-1. hello world4-2. 在客户端输出一个html文档4-3. 处理用户登陆的servlet实现方法4-4. servlet中session4-5. 获得客户端IP和url4-6. JSPServletJavaBean实现登录4-7. java servlet页面跳转4-8. java中Servlet处理乱码4-9. servlet分页   .内容举报
 
返回顶部
 收藏助手 不良信息举报您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因: 色情 政治 抄袭 广告 招聘 骂人
其他  
原文地址:  
原因补充:  (最多只允许输入30个字)
 
   

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

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

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

 

 

package cluster;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;

/**
 * Apriori算法实现 最大模式挖掘,涉及到支持度,但没有置信度计算
 * @author push_pop
 *
 */
public class AprioriMyself {
 
 private static final double MIN_SUPPROT = 0.2;//最小支持度
 private static boolean endTag = false;//循环状态
 static List<List<String>> record = new ArrayList<List<String>>();//数据集
 
 public static void main(String args[]){
  //*************读取数据集**************
  

 

 /**
  * 读取txt数据
  * @return
  */
 public static List<List<String>> getRecord() {
  List<List<String>> record = new ArrayList<List<String>>();
  try {
   String encoding = "GBK"; // 字符编码(可解决中文乱码问题 )
   File file = new File("simple.txt");
   if (file.isFile() && file.exists()) {
    InputStreamReader read = new InputStreamReader(
      new FileInputStream(file), encoding);
    BufferedReader bufferedReader = new BufferedReader(read);
    String lineTXT = null;
   while ((lineTXT = bufferedReader.readLine()) != null) {//读一行文件
     String[] lineString = lineTXT.split(" ");
     List<String> lineList = new ArrayList<String>();
  for (int i = 0; i < lineString.length; i++) {//处理矩阵中的T、F、YES、NO
                              if (lineString[i].endsWith("T")|| lineString[i].endsWith("YES"))
    lineList.add(record.get(0).get(i));
   else if (lineString[i].endsWith("F")|| lineString[i].endsWith("NO"))
     ;// F,NO记录不保存
   else
    lineList.add(lineString[i]);
     }
     record.add(lineList);
    }
    read.close();
   } else {
    System.out.println("找不到指定的文件!");
   }
  } catch (Exception e) {
   System.out.println("读取文件内容操作出错");
   e.printStackTrace();
  }
  return record;
 }
 


                       record = getRecord();

  //控制台输出记录
  System.out.println("以矩阵形式读取数据集record");
  for(int i=0;i<record.size();i++){
   List<String> list= new ArrayList<String>(record.get(i));
   for(int j=0;j<list.size();j++){
    System.out.print(list.get(j)+" ");
   }
   System.out.println();
  }
  

 

 


          /**
  * 获得一项候选集
  * @return
  */
 private static List<List<String>> findFirstCandidate() {
  // TODO Auto-generated method stub
  List<List<String>> tableList = new ArrayList<List<String>>();
  HashSet<String> hs  = new HashSet<String>();
  for (int i = 1; i<record.size(); i++){  //第一行为商品信息
   for(int j=1;j<record.get(i).size();j++){
    hs.add(record.get(i).get(j));
   }
  } 
  Iterator<String> itr = hs.iterator();
  while(itr.hasNext())
                       {
   List<String>  tempList = new ArrayList<String>();
   String Item = (String) itr.next();
   tempList.add(Item);
   tableList.add(tempList);
  }
  return tableList;
 }


  //************获取候选1项集**************
  List<List<String>> CandidateItemset = findFirstCandidate();
  
  //控制台输出1项候选集
  System.out.println("第一次扫描后的1级 备选集CandidateItemset");
  for(int i=0;i<CandidateItemset.size();i++){
   List<String> list = new ArrayList<String>(CandidateItemset.get(i));
   for(int j=0;j<list.size();j++){
    System.out.print(list.get(j)+" ");
   }
   System.out.println();
  }

 


 /**
  * 统计record中出现list集合的个数
  * @param list
  * @return
  */
 private static int countFrequent(List<String> list) {
  // TODO Auto-generated method stub
  int count = 0;
  for(int i = 1; i<record.size(); i++) {
   
   boolean notHaveThisList = false;
   
   for (int k=0; k < list.size(); k++){//判断record.get(i)是否包含list
    boolean thisRecordHave = false;
  for(int j=1; j<record.get(i).size(); j++){
  if(list.get(k).equals(record.get(i).get(j)))  //list。get(k)在record。get(i)中能找到
     thisRecordHave = true;
    }
                            if(!thisRecordHave){
//只要有一个list元素找不到,则退出其余元素比较,进行下一个record。get(i)比较
   notHaveThisList = true;
   break;
   }
          }
   
   if(notHaveThisList == false)
    count++;
   
  }
  return count;
 }


 /**
  * 由k项候选集剪枝得到k项频繁集
  * @param CandidateItemset
  * @return
  */
private static List<List<String>> getSupprotedItemset(List<List<String>> CandidateItemset) {
  // TODO Auto-generated method stub
  boolean end = true;
  List<List<String>> supportedItemset = new ArrayList<List<String>>();
  int k = 0;
  
  for (int i = 0; i < CandidateItemset.size(); i++){
   
   int count = countFrequent(CandidateItemset.get(i));//统计记录数
   
   if (count >= MIN_SUPPROT * (record.size()-1)){ 
    supportedItemset.add(CandidateItemset.get(i));
    end = false;
   }
  }
  endTag = end;//存在频繁项集则不会结束
  if(endTag==true)
   System.out.println("无满足支持度项集,结束连接");
  return supportedItemset;
 }

 

 

 

 

 


  //************获取频繁1项集***************
  List<List<String>> FrequentItemset = getSupprotedItemset(CandidateItemset);
  
  //控制台输出1项频繁集
  System.out.println("第一次扫描后的1级 频繁集FrequentItemset");
  for(int i=0;i<FrequentItemset.size();i++){
   List<String> list = new ArrayList<String>(FrequentItemset.get(i));
   for(int j=0;j<list.size();j++){
    System.out.print(list.get(j)+" ");
   }
   System.out.println();
  }
  
  //***************迭代过程**************
  while(endTag!=true){
  //**********连接操作****由k-1项频繁集      获取      候选k项集**************
  List<List<String>> nextCandidateItemset = getNextCandidate(FrequentItemset);
   
   System.out.println("扫描后备选集");
  for(int i=0;i<nextCandidateItemset.size();i++){
   List<String> list = new ArrayList<String>(nextCandidateItemset.get(i));
    for(int j=0;j<list.size();j++){
     System.out.print(list.get(j)+" ");
    }
    System.out.println();
   }
   
 //**************减枝操作***由候选k项集       获取     频繁k项集****************
 List<List<String>> nextFrequentItemset = getSupprotedItemset(nextCandidateItemset);
   
   System.out.println("扫描后频繁集");
  for(int i=0;i<nextFrequentItemset.size();i++){
   List<String> list = new ArrayList<String>(nextFrequentItemset.get(i));
    for(int j=0;j<list.size();j++){
     System.out.print(list.get(j)+" ");
    }
    System.out.println();
   }
   //*********如果循环结束,输出最大模式**************
   if(endTag == true){
    System.out.println("Apriori算法--->频繁集");
  for(int i=0;i<FrequentItemset.size();i++){
   List<String> list = new ArrayList<String>(FrequentItemset.get(i));
     for(int j=0;j<list.size();j++){
      System.out.print(list.get(j)+" ");
     }
     System.out.println();
    }
   }
   //****************下一次循环初值********************
   CandidateItemset = nextCandidateItemset;
   FrequentItemset = nextFrequentItemset;
  }
  
 }
 
 /**
  * 有当前频繁项集自连接求下一次候选集
  * @param FrequentItemset
  * @return
  */
 private static List<List<String>> getNextCandidate(List<List<String>> FrequentItemset) {
  List<List<String>> nextCandidateItemset = new ArrayList<List<String>>();
  for (int i=0; i<FrequentItemset.size(); i++){
   
   HashSet<String> hsSet = new HashSet<String>();
   HashSet<String> hsSettemp = new HashSet<String>();
   for (int k=0; k< FrequentItemset.get(i).size(); k++)//获得频繁集第i行
    hsSet.add(FrequentItemset.get(i).get(k));
   int hsLength_before = hsSet.size();//添加前长度
   hsSettemp=(HashSet<String>) hsSet.clone();
             for(int h=i+1; h<FrequentItemset.size(); h++){
//频繁集第i行与第j行(j>i)连接   每次添加且添加一个元素组成    新的频繁项集的某一行,  
  hsSet=(HashSet<String>) hsSettemp.clone();//!!!做连接的hasSet保持不变
    for(int j=0; j< FrequentItemset.get(h).size();j++)
     hsSet.add(FrequentItemset.get(h).get(j));
    int hsLength_after = hsSet.size();   
  if(hsLength_before+1 == hsLength_after && isSubsetOf(hsSet,record)==1 && isnotHave(hsSet,nextCandidateItemset)){
  //如果不相等,表示添加了1个新的元素,再判断其是否为record某一行的子集     若是则其为  候选集中的一项
     Iterator<String> itr = hsSet.iterator();
     List<String>  tempList = new ArrayList<String>();
     while(itr.hasNext()){
      String Item = (String) itr.next();
      tempList.add(Item);
     }
     nextCandidateItemset.add(tempList);
    }
     
   }
   
  }
  return nextCandidateItemset;
 }
 /**
  * 判断新添加元素形成的候选集是否在  新的候选集中
  * @param hsSet
  * @param nextCandidateItemset
  * @return
  */
 private static boolean isnotHave(HashSet<String> hsSet,
   List<List<String>> nextCandidateItemset) {
  // TODO Auto-generated method stub
  List<String>  tempList = new ArrayList<String>();
  Iterator<String> itr = hsSet.iterator();
  while(itr.hasNext()){
   String Item = (String) itr.next();
   tempList.add(Item);
  }
  for(int i=0; i<nextCandidateItemset.size();i++)
   if(tempList.equals(nextCandidateItemset.get(i)))
    return false;
  return true;
 }

 /**
  * 判断hsSet是不是record2中的某一记录子集
  * @param hsSet
  * @param record2
  * @return
  */
 private static int isSubsetOf(HashSet<String> hsSet,
   List<List<String>> record2) {
  //hsSet转换成List
  List<String>  tempList = new ArrayList<String>();
  Iterator<String> itr = hsSet.iterator();
  while(itr.hasNext()){
   String Item = (String) itr.next();
   tempList.add(Item);
  }  
  
  for(int i=1;i<record.size();i++){
   List<String>  tempListRecord = new ArrayList<String>();
   for(int j=1;j<record.get(i).size();j++)
    tempListRecord.add(record.get(i).get(j));
   if(tempListRecord.containsAll(tempList))
    return 1;
   }
  return 0;
 }

 


  
 
}

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

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

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

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


请把以下内容发送给学生:

请同学们下载安装使用闽科教务app, 以后每年 app会更新升级一次,里面有部分模块暂时无法使用(因服务器安装配置在后期执行)
希望每位同学把该app传播出去,让更多的人使用。本软件无毒。
我们团队目前在招收新成员(java方向),期待您的加入。
通信邮箱:2645567931@qq.com
软件是基于安卓手机的。


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

C: 系统盘   桌面放上  打印的资料  文件夹(学习 工作  生活)

===================================================
D:工作盘

临时工作文档夹(包含下载的资料):用于 未来要处理的工作

个人档案:  存储的是 本人的重要信息
简历
科研与项目资料:每种类型的项目建一个文件夹(版本递增)
金融财务
职称管理:初级 中级  高级
奖励管理


工作资料:以 单位 为标准 划分出 资料文件夹
例如:闽科

         梅山工程


以 闽科工作内容进一步划分:
课程:教什么课?
        包括:下载的原始资料(含技术资料),上课PPT,
                 实验资料(含上交的学生报告),
                 期末试卷(分年份)  教案教学进度表(版本)  开发工具软件备份


班主任:年级专业

毕业论文信息:下载的论文   学生提交的论文材料(分届) 

期末考试成绩资料:
文档注明 科目  年纪 专业  时间

教务管理资料:例如 课时量(版本) 教材申请表 课表(版本)


学校比赛活动:

 

 

梅山工程

 

 


================================
E:软件安装盘

software

项目代码 testCode

常用的软件工具包

================================
F:文化生活娱乐盘

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SQLAlchemy 是一个 SQL 工具包和对象关系映射(ORM)库,用于 Python 编程语言。它提供了一个高级的 SQL 工具和对象关系映射工具,允许开发者以 Python 类和对象的形式操作数据库,而无需编写大量的 SQL 语句。SQLAlchemy 建立在 DBAPI 之上,支持多种数据库后端,如 SQLite, MySQL, PostgreSQL 等。 SQLAlchemy 的核心功能: 对象关系映射(ORM): SQLAlchemy 允许开发者使用 Python 类来表示数据库表,使用类的实例表示表中的行。 开发者可以定义类之间的关系(如一对多、多对多),SQLAlchemy 会自动处理这些关系在数据库中的映射。 通过 ORM,开发者可以像操作 Python 对象一样操作数据库,这大大简化了数据库操作的复杂性。 表达式语言: SQLAlchemy 提供了一个丰富的 SQL 表达式语言,允许开发者以 Python 表达式的方式编写复杂的 SQL 查询。 表达式语言提供了对 SQL 语句的灵活控制,同时保持了代码的可读性和可维护性。 数据库引擎和连接池: SQLAlchemy 支持多种数据库后端,并且为每种后端提供了对应的数据库引擎。 它还提供了连接池管理功能,以优化数据库连接的创建、使用和释放。 会话管理: SQLAlchemy 使用会话(Session)来管理对象的持久化状态。 会话提供了一个工作单元(unit of work)和身份映射(identity map)的概念,使得对象的状态管理和查询更加高效。 事件系统: SQLAlchemy 提供了一个事件系统,允许开发者在 ORM 的各个生命周期阶段插入自定义的钩子函数。 这使得开发者可以在对象加载、修改、删除等操作时执行额外的逻辑。
SQLAlchemy 是一个 SQL 工具包和对象关系映射(ORM)库,用于 Python 编程语言。它提供了一个高级的 SQL 工具和对象关系映射工具,允许开发者以 Python 类和对象的形式操作数据库,而无需编写大量的 SQL 语句。SQLAlchemy 建立在 DBAPI 之上,支持多种数据库后端,如 SQLite, MySQL, PostgreSQL 等。 SQLAlchemy 的核心功能: 对象关系映射(ORM): SQLAlchemy 允许开发者使用 Python 类来表示数据库表,使用类的实例表示表中的行。 开发者可以定义类之间的关系(如一对多、多对多),SQLAlchemy 会自动处理这些关系在数据库中的映射。 通过 ORM,开发者可以像操作 Python 对象一样操作数据库,这大大简化了数据库操作的复杂性。 表达式语言: SQLAlchemy 提供了一个丰富的 SQL 表达式语言,允许开发者以 Python 表达式的方式编写复杂的 SQL 查询。 表达式语言提供了对 SQL 语句的灵活控制,同时保持了代码的可读性和可维护性。 数据库引擎和连接池: SQLAlchemy 支持多种数据库后端,并且为每种后端提供了对应的数据库引擎。 它还提供了连接池管理功能,以优化数据库连接的创建、使用和释放。 会话管理: SQLAlchemy 使用会话(Session)来管理对象的持久化状态。 会话提供了一个工作单元(unit of work)和身份映射(identity map)的概念,使得对象的状态管理和查询更加高效。 事件系统: SQLAlchemy 提供了一个事件系统,允许开发者在 ORM 的各个生命周期阶段插入自定义的钩子函数。 这使得开发者可以在对象加载、修改、删除等操作时执行额外的逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值