• 学习笔记2018-1-7

    2018-01-07 21:20:00
    一、Java集合 1、Deque接口提供了一个典型的实现类: ArrayDeque,从该名称就可以看出,它是一个基于数组实现的双端队列,创建 Deque时同样可指定一个 numElements参数,该参数用于指定 Object数组的长度;如果不...

    一、Java集合
    1、Deque接口提供了一个典型的实现类: ArrayDeque,从该名称就可以看出,它是一个基于数组实现的双端队列,创建 Deque时同样可指定一个 numElements参数,该参数用于指定 Object数组的长度;如果不指定 numElements参数, Deque底层数组的长度为16。
    2、Set与Map之间的关系非常密切。虽然Map中放的元素是key- -value对,Set集合中放的元素是单个对象,但如果我们把key-value对中的 value当成key的附庸:key在哪里, value就跟在哪里。这样就可以像对待Set一样来对待Map了。事实上,Map提供了一个Enty内部类来封装key-value对,而计算Enty存储时则只考虑 Entry封装的key.从Java源码来看Java是先实现了Map,然后通过包装一个所有 value都为null的Map就实现了Set集合。
    3、Hashtable和 HashMap存在两点典型区别。Hashtable是一个线程安全的Map实现,但 HashMap是线程不安全的实现,所以 HashMap比Hashtable的性能高一点;Hashtable不允许使用null作为key和value,如果试图把null值放进 Hashtable中,将会引发Nullpointerexception异常;但 HashMap可以使用null作为key或 value,由于 HashMap里的key不能重复,所以 HashMap里最多只有一个 key-value对的key为null,但可以有无数多个 key-value对的 value为null。从 Hashtable的类名上就可以看出它是一个古老的类,它的命名甚至没有遵守Java的命名规范:每个单词的首字母都应该大写。也许当初开发 Hashtable的工程师也没有注意到这一点,后来大量Java程序中使用了 Hashtable类,所以这个类名也就不能改为Hash Table了,否则将导致大量程序需要改写。与 Vector类似的是,尽量少用 Hashtable实现类,即使需要创建线程安全的Map实现类,也无须使用 Hashtable实现类,可以通过后面介绍的 Collections工具类把 HashMap变成线程安全的
    4、如果需要使用 Weakhashmap的key来保留对象的弱引用,则不要让该key所引对象具有任何强引用,否则将失去使用 Weakhashmap的意义
    5、IdentityHashMap实现类。这个Map实现类的实现机制与 Hash Map基本相似,但它在处理两个key相等时比较独特:在Identity HashMap中,当且仅当两个key严格相等(keyl==key2)时, Identity HashMap才认为两个key相等:对于普通的 Hash Map而言,只要keyl和key2通过 equals方法比较返回true,且它们的 hashCode()值相等即可。
    6、Java提供了一个操作Set、List和Map等集合的工具类: Collections,该工具类里提供了大量方法对集合元素进行排序、查询和修改等操作,还提供了将集合对象设置为不可变、对集合对象实现同步控制等方法。
    6.1、排序操作
    Collections提供了如下几个方法用于对List集合元素进行排序。

    static void reverse( List list):反转指定List集合中元素的顺序
    static void shuffle( List list)):对List集合元素进行随机排序( (shuffle方法模拟了“洗牌”动作)。
    static void sort(List list):根据元素的自然顺序对指定List集合的元素按升序进行排序。static void sort(List list,. Comparator c):根据指定 Comparator产生的顺序对List集合元素进行排序
    static void swap( List list,inti,intj):将指定List集合中的i处元素和j处元素进行交换
    static void rotate( List list, int distance):当 distance为正数时,将list集合的后 i distance个元素“整体”移到前面;当 distance为负数时,将lit集合的前 distance个元素“整体”移到后面。该方法不会改变集合的长度。

    二、类、对象和接口
    1、对于只有一个抽象方法的接口,需要这种接口的对象时,就可以提供一个 lambda表达式。这种接口称为函数式接口( functional interface)
    ■注释:你可能想知道为什么函数式接口必须有一个抽象方法。不是接口中的所有方法都是抽象的吗?实际上,接口完全有可能重新声明 Object类的方法,如 to String或 clone这些声明有可能会让方法不再是抽象的。( Java API中的一些接口会重新声明 Object方法来附加 javadoc注释。 Comparator API就是这样一个例子。)更重要的是,正如6.1.5节所述,在 Java SE8中,接口可以声明非抽象方法。
    2、如果设计你自己的接口,其中只有一个抽象方法,可以用 Functionallnterface 注解来标记这个接口。这样做有两个优点。如果你无意中增加了另一个非抽象方法,编译器会产生一个错误消息。另外 Javadoc页里会指出你的接口是一个函数式接口。并不是必须使用注解。根据定义,任何有一个抽象方法的接口都是函数式接口。不过使用@ Functionallnterface注解确实是一个很好的做法。

    3、内部类中声明的所有静态域都必须是final。原因很简单,我们希望一个静态域只有一个实例,不过对于每个外部对象,会分别有一个单独的内部类实例。如果这个域不是 final,它可能就不是唯一的。
    4、内部类不能有 static方法。Java语言规范对这个限制没有做任何解释。其实也可以允许有静态方法,限制只能访问外围类的静态域和方法就好。显然,Java设计者认为相对于这种复杂性来说,它带来的好处有些得不偿失。
    5、初始化块。前面已经讲过两种初始化数据域的方法:
    ·在构造器中设置值
    ·在声明中赋值
    实际上,Java还有第三种机制,称为初始化块( (initialization block)。在一个类的声明中,可以包含多个代码块。只要构造类的对象,这些块就会被执行。例如,
    class Employee{
    static int nextid
    String name
    Double salary:
    ∥/object block

    {
    id++
    }
    public Employee(String n, double s)
    {
    nane n,
    salary s:
    }
    }
    在这个示例中,无论使用哪个构造器构造对象,id域都在对象初始化块中被初始化。首先运行初始化块,然后才运行构造器的主体部分。这种机制不是必需的,也不常见。通常会直接将初始化代码放在构造器中。有时会在面试中见到这种用法:
    例如:下面的技巧称为“双括号初始化”( double brace initialization),这里利用了内部类语法。ArrayList list = new ArrayList<>(){{add(“1”);add(“2”)}}等同于
    ArrayList list = new ArrayList<>();
    list.add(“1”);
    list.add(“2”);
    6、建立一个与超类大体类似(但不完全相同)的匿名子类通常会很方便。不过,对于 equals方法要特别当心。第5章中,我们曾建议 equals方法最好使用以下测试: if ( i==other)return false;但是对匿名子类做这个测试时会失败。
    7、生成日志或调试消息时,通常希望包含当前类的类名,如:System.err.println("Something happened in"+getclass());不过,这对于静态方法不奏效。毕竟,调用 getclass时调用的是 this.,而静态方法没有this。所以应该使用以下表达式:new Object(){}.getClass().getEnclosingClass()// gets class of static method
    在这里, new会建立 Object的一个匿名子类的一个匿名对象, getEnclosingClass()则得到其外围类,也就是包含这个静态方法的类。

    展开全文
  • 2019年最新Java学习路线图,路线图的宗旨就是分享,专业,便利,让喜爱Java的人,都能平等的学习。从今天起不要再找借口,不要再说想学Java却没有资源,赶快行动起来,Java等你来探索,高薪距你只差一步! java...

     

    2019年最新Java学习路线图, 路线图的宗旨就是分享,专业,便利,让喜爱Java的人,都能平等的学习。从今天起不要再找借口,不要再说想学Java却没有资源,赶快行动起来,Java等你来探索,高薪距你只差一步!

     

    java学习基础

    针对Java零基础入门学习者,比较详细的知识点总结和学习路线

    数据库

     

    数据库是程序员必须要掌握中知识点,详细的学习思路和面试题,

    适用/适合人群:

    拥有Java语言并可以实现网站爬取数据并分析

    目标:

    掌握mysql,Oracle在各个平台上的安装及使用

    Mysql数据库基础

    1. mysql概述、优点、运行原理及内存结构
    2. mysql数据类型
    3. mysqlDDL语句的使用
    4. SQL语言的使用
    5. DML语句的介绍及使用
    6. SQL事务
    7. SQL查询机制、查询基础、技巧、查询优化;

    Mysql数据库高级

    1. mysql数据库引擎分类
    2. mysql事务
    3. mysql表
    4. mysql数据类型
    5. mysql视图
    6. mysql索引
    7. mysql分页
    8. SQL语句优化技巧

    Oracle实战

    1. Oracle安装与调试
    2. Oracle数据类型
    3. Oracle与MySQL对比
    4. Oracle数据结构概述
    5. Oracle运行原理
    6. Oracle内存结构
    7. Oracle表空间
    8. 用户,表,序列的创建及使用
    9. Oracle索引
    10. Oracle分区表的创建及使用

    PL/SQL实战

     

    1. PL/SQL基础知识
    2. 异常处理
    3. 游标
    4. 存储过程

    JDBC

     

    1. JDBC概述
    2. JDBC工作原理
    3. JDBC API
    4. JDBC访问数据库
    5. JDBC常用接口

    ●数据库连接池

    1. Java多线程开发
    2. 多线程与单线程比较
    3. 多线程应用
    4. 多线程使用注意事项
    5. 数据库连接池技术

     

    WEB前端技术

    目标:

    1. 掌握HTML,CSS,JavaScript等前端基本技术,并使用JSP,Servlet开发小型网站
    2. 使用框架技术开发大型网站

    HTML+CSS基础

     

    1. W3C标准
    2. HTML编辑工具
    3. HTML标签
    4. CSS的基本用法
    5. 在HTML中引入CSS样式

     

    CSS高级

    1. CSS编辑网页文本
    2. 列表样式
    3. 盒子模型
    4. 浮动
    5. 定位网页元素

    JS基础

    1. JavaScript核心语法
    2. 程序调试
    3. JavaScript对象

    JS高级

    1. 初识jQuery,jQuery选择器
    2. jQuery中的事件与动画
    3. jQuery操作DOM
    4. 表单校验

    JavaWEB

     

    web基础技(项目实战),初级的一般是用JSP(Java Server Pages)+servlet+Javabean来开发的,对大型的网站一般是使用框架来开发的,例如struts,hibernate,spring,典型的struts框架结构。

    JavaWEB项目

     

    EGOA项目、二手车电商平台项目都是JAVAWEB的项目

     

    Java高级框架

     

    设计模式

      设计原则 【单一职责、里氏替换、依赖倒置、接口隔离、迪米特法则、开闭原则】

      代理模式

      工厂模式

      策略模式

    Spring源码

     Spring核心组件

    IOC机制

     

    AOP实现原理【aop编辑思想、aop在spring中的使用、cglib和jdk动态代理】

    Transaction事务处理【事务隔离级别】

    SpringMVC【DispatcherServlet、请求映射、参数绑定与转换、页面渲染】

    Mybatis

    mydatis代码

    Sqlsession原理

    mybatis事务

    自带缓存机制与Spring结合实现缓存

    使用代码生成器快速开发

    互联分布式网架构体系

    1SpringBoot

    starter快速集成组件【缓存、数据库、消息队列、搜索引擎】

    AutoConfigure自动化配置

    Actuator系统监控【数据库、消息队列中间件、自定义监控】

    新注解特性分析

     

    工程化管理

    git管理

    maven

    Sonar代码质量检测平台

    jenkins持续集成

    Devops持续集成

    jenkins环境构建

    jenkins集成git/svn/tomcat/sonar

    jenkins插件机制

    微服务架构

    架构设计

    互联网架构【服务化架构】

    DDD领域驱动设计【建模、事件驱动】

    分布式系统架构

    微服务架构【服务拆分、服务治理】

    SpringCloud

    config分布式配置中心

    Eureka注册与发现机制

    Ribbon客户端负载均衡

    Hystrix服务熔断组件

    feign声明式服务调用

    Zuu网关服务

    docker

    decker【镜像、容器、常用命令】

    私有仓库

    docker swarm集群搭建

    docker compose部署脚本

    docker service服务编排

    docker stack分布式集群部署

    docker portainer容器可视化管理工具

    maven插件打包docker镜像

    docker部署运行java程序

    docker应用【搭建ELK、RabbitMQ、Mysql、部署高可用springCloud微服务实现动态扩容、、】

    分布式技术

    RPC模式【rmi,http,hessian】

    分布式系统指挥者Zookeeper【CAP理论、ZK、、】

    Dubbo框架【服务化思想、dubbo特性、dubbo原理】

    服务发现机制

    mock机制

    容错机制

    负载均衡机制

    序列化方式

    多协议支持

    配置加载机制

    数据绑定实现原理

    与spring的集成原理

    rpc-协议原理

    netty的使

    高并发开发技术

    java多线程【基础线程、线程池和Executor框架、线程安全、】

    java常用并发工具接口和类【ContDownLatch、CyclicBarrier、Semaphore、Exchange、ConcurrentHashMap、ConcurrentSkipListMap、Fork\Jion、HashMap、List】

    NIO【阻塞\非阻塞、高性能网络编辑框架-natty、】

    高并发-缓存【Redis、memcached、】

    高并发-消息队列【ActiveMq(JMS规范、ack机制)、RabbitMq(AMQP规范)】

    高并发-分流【DNS分流、CDN分流+加速、Nginx、LVS】

    高并发技术实战

    分布式锁定实现方案【redis、zookeeper】

    分布式事务解决方案【X/A协议、消息队列、TCC解决】

    分布式系统校验【分布式session、JWT方式、单点框架】

    互联网高可用框架【负载均衡技术分析、keepalive实现】

    分布式订单流水号生成策略【基于数据库、基于雪花算法、基于redis、】

    分布式系统数据存储【】

     

    传统数据库、

    NoSQL数据库、

    MYSQL高可用、

    MongoDB、

    大数据分库分表解决方案mycat

    性能优化

    JVM优化【参数调优、性能】

    WEB【java低能代码、Tomcat容器原理\手写简版Tomcat、Tomcat参数、Benchmark】

    SQL优化【数据库存储引擎、索引、Sql语句性能、SQL语句{业务层面、数据库层面、sql语句拆分}】

     

     

    展开全文
  • Java OpenCV使用教程标签(空格分隔): opencv最近公司让处理银行卡图片,遂去找教程,决定使用下opencv.该博文主要记录一些操作的处理.环境搭建:下载openCV后,把build文件夹里面的java拷贝到项目目录主程序里面启动...

    Java OpenCV使用教程

    标签(空格分隔): opencv


    最近公司让处理银行卡图片,遂去找教程,决定使用下opencv.该博文主要记录一些操作的处理.

    环境搭建:

    下载openCV后,把build文件夹里面的java拷贝到项目目录

    主程序里面启动前加载该库

        static {
            System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
            //注意程序运行的时候需要在VM option添加该行 指明opencv的dll文件所在路径
            //-Djava.library.path=$PROJECT_DIR$\opencv\x64
        }

    IDEA内这样配置

    这里写图片描述


    例图:
    这里写图片描述


    1.Mat与BufferedImage的转换

    Mat类是OpenCV最基本的一个数据类型,它可以表示一个多维的多通道的数组。Mat常用来存储图像,包括单通道二维数组——灰度图,多通道二维数组——彩色图。

    1.1 mat转BufferedImage

            Mat grayMat = Highgui.imread("E:/temp/3.jpg");
            byte[] data1 = new byte[grayMat.rows() * grayMat.cols() * (int)(grayMat.elemSize())];
            grayMat.get(0, 0, data1);
            BufferedImage image1 = new BufferedImage(grayMat.cols(),
                                    grayMat.rows(),BufferedImage.TYPE_BYTE_GRAY);
            image1.getRaster().setDataElements(0, 0, grayMat.cols(), grayMat.rows(), data1);

    1.2 BufferedImage转mat

        BufferedImage src = ImageIO.read(input);
        Mat srcMat = new Mat(src.getHeight(), src.getWidth(), CvType.CV_8UC3);

    2.图片灰度化

    就是把图片转换为黑白照

            Imgproc.cvtColor(srcMat, destMat, Imgproc.COLOR_RGB2GRAY);

    该函数把原srcMat转换为灰度图像放入grayMat中,自己再转换为BufferedImage显示即可.

    这里写图片描述

    3.二值化处理

    也就是只留两个值,黑白

             Mat binaryMat = new Mat(grayMat.height(),grayMat.width(),CvType.CV_8UC1);
            Imgproc.threshold(grayMat, binaryMat, max1, max2, Imgproc.THRESH_BINARY);

    这里写图片描述

    4.图像腐蚀

    这里使用3*3的图片去腐蚀

            Mat element = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(3, 3));
            Imgproc.erode(srcMat,destMat,element);

    腐蚀后变得更加宽,粗.便于识别
    这里写图片描述

    5.遍历,获取和修改像素值

    二值图片,当成一个二维矩阵就可以了,双重循环,使用get方法获取像素点,使用put方法修改像素点

         for (int y = 0; y < imgSrc.height(); y++)
            {
                for (int x = 0; x < imgSrc.width(); x++)
                {
                    //得到该行像素点的值
                        double[] data = imgSrc.get(y,x);
                        for (int i1 = 0; i1 < data.length; i1++) {
                            data[i1] = 255;//像素点都改为白色
                        }
                        imgSrc.put(i,j,data);
                }
            }

    6.过滤和切割

    过滤和切割要找到一个开始行或列,结束行或列,这就有一个简单的算法.该算法从第一行开始遍历,统计每一行的像素点值符合阈值的个数,再根据个数判断该点是否为边界.找到后过滤和切割自然就很简单了,直接创建个该范围的新的Mat对象.

            for (int y = 0; y < imgSrc.height(); y++)
            {
                int count = 0;
                for (int x = 0; x < imgSrc.width(); x++)
                {
                    //得到该行像素点的值
                    byte[] data = new byte[1];
                    imgSrc.get(y, x, data);
                    if (data[0] == 0)
                        count = count + 1;
                }
                if (state == 0)//还未到有效行
                {
                    if (count >= 150)//找到了有效行
                    {//有效行允许十个像素点的噪声
                        a = y;
                        state = 1;
                    }
                }
                else if (state == 1)
                {
                    if (count <= 150)//找到了有效行
                    {//有效行允许十个像素点的噪声
                        b = y;
                        state = 2;
                    }
                }
            }
            System.out.println("过滤下界"+Integer.toString(a));
            System.out.println("过滤上界"+Integer.toString(b));

    截取

            //参数,坐标X,坐标Y,截图宽度,截图长度
            Rect roi = new Rect(0, 0, imgSrc.width(), b - a);
            Mat res = new Mat(new Size(roi.width, roi.height),CvType.CV_8UC1);

    过滤是从上到下,判断该行的黑色像素点是否大于一定值,大于则留下,找到上边界,下边界后立即停止.
    这里写图片描述

    7.识别

    使用tesseract-ocr进行识别,效果还是很不错的.github地址

    这里写图片描述

    8.资料

    后来发现一个很不错的网站,分享一下,里面有一些使用案例

    http://www.w3ii.com/java_dip/default.html
    
    展开全文
  • java验证码识别--1

    2014-04-02 14:29:20
    java验证码识别--1 http://blog.csdn.net/problc/article/details/5794460 java验证码识别--2 http://blog.csdn.net/problc/article/details/5797507 java验证码识别--3 ...

    java验证码识别--1

    http://blog.csdn.net/problc/article/details/5794460

    java验证码识别--2

    http://blog.csdn.net/problc/article/details/5797507

    java验证码识别--3

    http://blog.csdn.net/problc/article/details/5800093

    java验证码识别--4

    http://blog.csdn.net/problc/article/details/5846614

    java验证码识别--5

    http://blog.csdn.net/problc/article/details/5983276

    如何识别高级的验证码-粘连等

    http://blog.csdn.net/problc/article/details/22796609

    常见验证码的弱点与验证码识别

    http://blog.csdn.net/problc/article/details/22796971


    (本文仅用于学习研究图像匹配识别原理,不得用于其他用途。)

    完整eclipse工程http://download.csdn.net/detail/problc/3829004

    最近看了看验证码的识别,先从最简单的做起吧(固定大小,固定位置,固定字体)

     

    验证码识别基本分四步,图片预处理,分割,训练,识别

     

    看一个最简单验证码

    这是一个德克萨斯扑克的注册页面的验证码

     

    1。图像的预处理

    这种直接根据亮度设个阈值处理就可以了

     

    处理完图片效果为

    图像基本分得比较清楚,图片分割也比较容易

     

    2。分割

    这个验证码居然是固定位置的,分割相当简单,直接截取相应位置就可以了

    3。训练

    直接拿几张图片,包含0-9,每个数字一个样本就可以了,将文件名对应相应的数字

    4。识别

    因为是固定大小,固定位置,识别也很简单。

    直接拿分割的图片跟这个十个图片一个像素一个像素的比,相同的点最多的就是结果。比如如果跟5.jpg最相似,那么识别的结果就是5。

    下面是识别结果,很容易达到100%

     

     

    完整代码(csdn连个附件都不支持):

     

    展开全文
  • JAVA学习篇--Servlet详解

    2014-10-16 15:52:22
    servlet由来    做过BS项目的人都知道,浏览器能够根据HTML静态标记语言来显示各式各样的网页。但是如果我们需要在网页上完成一些...或者说网页显示的内容在服务器的数据库中。...这种网页我们就叫做动态网页。 ...当客户


    Servlet由来

     

         做过BS项目的人都知道,浏览器能够根据HTML静态标记语言来显示各式各样的网页。但是如果我们需要在网页上完成一些业务逻辑:比如登陆验证。或者说网页显示的内容在服务器的数据库中。如果是这样,除了负责显示的HTML标记之外,必须还要有完成这些业务功能的代码存在。这种网页我们就叫做动态网页。

         对于静态网页而言,服务器上存在的是一个个纯HTML文件。当客户端浏览器发出HTTP请求时,服务器可以根据请求的URL找到对应的HTML文件,并将HTML代码返回给客户端浏览器。

         但是对于动态网页,服务器上除了找到需要显示的HTML标记外,还必须执行所需要的业务逻辑,然后将业务逻辑运算后的结果和需要显示的HTML标记一起生成新的HTML代码。最后将新的带有业务逻辑运算结果的HTML代码返回给客户端。

     

    为了实现动态网页的目标,JavaServlet技术因应而生,它能够以一种可移植的方法来提供动态的、面向用户的内容。

     

    简单来说:

    servlet是在服务器上运行的小程序。Servlet的主要功能在于交互式地浏览和修改数据,生成动态Web内容,是为web开发服务的。

     

    CGI与Servlet对比

     

    开始的时候,公共网关接口(CommonGateway Interface,CGI)脚本是生成动态内容的主要技术。虽然使用得非常广泛,但CGI脚本技术有很多的缺陷,这包括平台相关性和缺乏可扩展性。为了避免这些局限性,JavaServlet技术因应而生,它能够以一种可移植的方法来提供动态的、面向用户的内容。处理用户请求。

     

         对比一:当用户浏览器发出一个Http/CGI的请求,或者说调用一个CGI程序的时候,服务器端就要新启用一个进程(而且是每次都要调用),调用CGI程序越多(特别是访问量高的时候),就要消耗系统越多的处理时间,只剩下越来越少的系统资源,对于用户来说,只能是漫长的等待服务器端的返回页面了,这对于电子商务激烈发展的今天来说,不能不说是一种技术上的遗憾。

      而Servlet充分发挥了服务器端的资源并高效的利用。每次调用Servlet时并不是新启用一个进程,而是在一个Web服务器的进程中共享和分离线程,而线程最大的好处在于可以共享一个数据源,使系统资源被有效利用。故servlet不是线程安全的,单实例多线程的


      对比二:传统的CGI程序,不具备平台无关性特征,系统环境发生变化,CGI程序就要瘫痪,而Servlet具备Java的平台无关性,在系统开发过程中保持了系统的可扩展性、高效性。


      对比三:传统技术中,一般大都为二层的系统架构,即Web服务器+数据库服务器,导致网站访问量大的时候,无法克服CGI程序与数据库建立连接时速度慢的瓶颈,从而死机、数据库死锁现象频繁发生。而我们的Servlet有连接池的概念,它可以利用多线程的优点,在系统缓存中事先建立好若干与数据库的连接,到时候若想和数据库打交道可以随时跟系统"要"一个连接即可,反应速度可想而知。

     

     

    Servlet的运行过程

       

         ⒈ 客户端发送请求至服务器端;

       ⒉服务器端根据web.xml文件中的Servlet相关配置信息,将客户端请求转发到相应的Servlet

         ⒊ Servlet引擎调用Service()方法,根据request对象中封装的用户请求与数据库进行交互,返回数据之后,Servlet会将返回的数据封装到response对象中;

       ⒋ Servlet生成响应内容并将其传给服务器。响应内容动态生成,通常取决于客户端的请求 

    ⒌ 服务器将响应返回给客户端


     


    Servlet生命周期


        

     

    1) 加载和实例化;在第一次请求Servlet时,Servlet容器将会创建Servlet实例;

    2) 初始化;Servlet容器加载完成Servlet之后,必须进行初始化,此时,init方法将被调用;

    3) Servlet初始化之后,就处于响应请求的就绪状态,此时如有客户端请求发送,就会调用Servlet实例的service()方法,并且根据用户的请求方式,调用doPost或者doGet方法;

    4) 最后,Servlet容器负责将Servlet实例进行销毁,调用destroy方法实现;

      对于更多的客户端请求,Server创建新的请求和响应对象,仍然激活此Servlet的service()方法,将这两个对象作为参数传递给它。如此重复以上的循环,但无需再次调用init()方法。

        一般Servlet只初始化一次(只有一个对象),当Server不再需要Servlet时(一般当Server关闭时),Server调用Servlet的Destroy()方法。

     

    实例解析:


                 


    html代码--客户端浏览器

    <span style="font-family:KaiTi_GB2312;"><html>
    	<head>
    		<title>学生管理</title>
    	</head>
    	<body>
    		<h1>根据出生日期段查询</h1>
    		<form action="queryStudentServlet">
    			出生日期 :<input type="text" name="beginDate">至<input type="text" name="endDate">
    			<input type="submit" value="查询学生">
    		</form>
    	</body>
    </html>
    </span>

    配置文件

    <span style="font-family:KaiTi_GB2312;"><servlet>
    		<servlet-name>StudentMgrServlet</servlet-name>
    		<servlet-class>StudentServlet</servlet-class>
    	</servlet>
    	<servlet-mapping>
    		<servlet-name>StudentMgrServlet</servlet-name>
    		<url-pattern>/queryStudentServlet</url-pattern>
    	</servlet-mapping>
    </span>

    servlet处理过程

    <span style="font-family:KaiTi_GB2312;">	import java.text.*;
    	import java.util.*;
    	import java.io.*;
    	import javax.servlet.http.*;
    	import javax.servlet.*;
    	
    	import com.bjpowernode.exam.model.*;
    	import com.bjpowernode.exam.manager.*;
    	
    	public class StudentServlet extends HttpServlet {
    	
    		public void doGet(HttpServletRequest request, HttpServletResponse response)	
    		throws ServletException, IOException {
    			doPost(request, response);
    		}
    		
    		public void doPost(HttpServletRequest request, HttpServletResponse response)
    		throws ServletException, IOException {
    			
    			String sBeginDate = request.getParameter("beginDate");
    			String sEndDate = request.getParameter("endDate");
    			
    			Date beginDate = new Date();
    			Date endDate = new Date();
    			try {
    				beginDate = new SimpleDateFormat("yyyy-MM-dd").parse(sBeginDate);
    			 	endDate = new SimpleDateFormat("yyyy-MM-dd").parse(sEndDate);
    			 }catch(Exception e) {
    				e.printStackTrace();		 
    			 }	 
    			
    			
    			StudentManager studentManager = new StudentManagerImpl();
    			List<Student> studentList = studentManager.findStudentList(beginDate, endDate);
    			//表格省略…
    		}
    	}
    </span>

    Servlet如何同时处理多个请求?


           Servlet采用多线程来处理多个请求的同时访问。Servlet容器通过线程池来管理维护服务请求。所谓线程池,相当于数据库连接池,实际上是等待执行代码的一组线程,叫做工作者线程。Servlet容器通过一个调度线程来管理工作者线程。
    · 当容器收到一个Servlet的访问请求,调度者线程就从线程池中选出一个工作者线程,将用户请求传递给该线程,然后由该线程处理Servlet的service()方法;
    · 当这个线程在执行的时候,容器收到一个新的请求,调度者线程再次从线程池中选出一个新的工作者线程;
    · 当容器同时收到对同一个Servlet的多个请求时,那么Servlet的service方法将在多线程中并发执行。


    注:

        1.Servlet容器默认采用单实例多线程的方式来处理请求。这样减少了产生Servlet实例的开销,提升了对请求的响应时间;
        2.对于Tomcat容器来讲,可以在其server.xml中通过<Connector>中设置线程池中的线程数目。


    如何开发线程安全的Servlet?


           Servlet容器采用多线程来处理请求,提高性能的同时也造成了线程安全问题。要开发线程安全的Servlet应该从一下几个方面进行:
    1.  变量的线程安全; 多线程并不共享局部变量,所以我们要尽可能的在Servlet中使用局部变量;
    2.  代码块的线程安全; 使用同步块Synchronized,防止可能调用的代码块;但是要注意的是,要尽可能得缩小同步代码的方范围,不要在service方法和响应方法上直接使用同步,这会严重影响性能。
    3.  属性的线程安全; ServletContext,HttpSession,ServletRequest对象中属性;
    4.  使用同步集合; 使用Vector代替ArrayList,使用HashTable代替HashMap;
    5.  不要在Servlet中创建自己的线程来完成某个功能; Servlet本身就是多线程的,如果再创建新的线程,将会导致线程执行复杂化,出现线程安全问题;
    6.  在多个Servlet中,对外部对象,比如:文件;进行修改操作一定要加锁,做到互斥访问;



    总结:

     

        一个servlet就是Java编程语言中的一个类,它被用来扩展服务器的性能,服务器上驻留着可以通过“请求-响应”编程模型来访问的应用程序。Servlet通过解析http请求,取得客户端的参数来进行下一步操作。其实简单来说,servlet就是一个控制器,取参数,调用业务逻辑.

        而在.net 中HttpHandler是一个HTTP请求的真正处理中心,也正是在这个HttpHandler容器中,ASP.NET Framework才真正地对客户端请求的服务器页面做出编译和执行,并将处理过后的信息附加在HTTP请求信息流中再次返回到HttpModule中。




     


    展开全文
  • 这是Java学习指南系列课程的第1篇,介绍Java语言的入门语法,引领希望学习Java语言编程的初学者进入Java大门。 本课程不需要其他语言作为基础,可以直接学习。 课程从Java开发平台的下载和安装开始,从...
  • 在博主认为,对于入门级学习java的最佳学习方法莫过于视频+博客+书籍+总结,前三者博主将淋漓尽致地挥毫于这篇博客文章中,至于总结在于个人,实际上越到后面你会发现学习的最好方式就是阅读参考官方文档其次就是...
  • Java集合-----Set 集合:就像一种容器,可以把多个对象放进该容器中。 Java集合分为:Set、List、Map三种体系。 Set:无序的,不可重复的; List:有序的,可重复的; Map:代表有映射关系的集合,Map保存的每一项...
  • 多个double类型的数直接相加的时候,可能存在精度误差.( 由于计算机算法以及硬件环境决定只能识别 0 1。计算机默认的计算结果在都在一个指定精度范围之内,想往深的了解,可以学习数值分析等) 在金融方面是绝对不...
  • 这个问题一上来,一脸懵逼,只知道两者的值是不一样的,前者是-2后者是2,至于为什么,不知道。但是凡事都有个为什么,深究之下,原来是属于纯粹的数学问题: ...-5 = (-1)* 3 +(-2); 此时, k = [n/m] = [(-5)/
  • 最近在系统的学习Java并发(concurrent),遂将学习所得整理成博文,作为今后参考的依据。 内容简述 基本概念与发展历史 Thread的线程方法与状态转换 JMM、指令重排、happens-before原则、原子性、可见性与有序...
  • 当然,这里我只是说Java学习路线,因为自己就是学Java的,对Java理当很熟悉,对于其它方面,我也不是很了解。 基础阶段 首先是基础阶段,在基础阶段,我们必须掌握Java基础,Mysql数据库,Ora...
  • Java学习笔记--导航

    2015-11-20 10:34:20
    Java入门(1)——http://blog.csdn.net/q547550831/article/details/49533977 Java入门(2)——http://blog.csdn.net/q547550831/article/details/49818745
  • 今天在使用Java NIO的Channel和Buffer进行文件操作时候,报了java.nio.charset.MalformedInputException: Input length = 1异常,具体如下: java.nio.charset.MalformedInputException: Input length = 1 at java...
  • Java进阶学习路线图

    2014-08-14 14:37:18
    第一条路线(技术专精): 初级Java开发---中级--高级---项目主管--Java项目经理---网站架构师----资深专家 第二条路线(技术转产品):初级Java开发---中级--产品策划--产品经理---产品总监 第三条路线(技术转...
  • 在编写java程序时,由于java本身的窗口并不漂亮,因此很多时候我们需要通过重绘窗口来达到美观的效果   在重绘时,对于上面左边的标准窗口,我们可能需要去除他的边框来得到上面右边的窗口,此时,可以使用JWindow...
  • java注解学习---@Target({ElementType.PACKAGE})理解和使用(三)一、使用 @HaHaTargetPackage 注解遇到问题1、新建一个类,直接在当前包上使用 @HaHaTargetPackage 提示错误信息: Package annotations must be in ...
  • 在DRP项目中,多次提到了Filter,它解决了字符集的统一设置以及统一控制简单WebCache,从中我们可以体会到,它给我们带来的好处不仅仅是减少代码量这么简单,它的出现避免了我们每个页面重复的编写相同的代码,减少...
  • JAVA8学习笔记-function

    2017-01-05 17:34:00
    JAVA8学习笔记-Function
  • 本文将告诉你学习Java需要达到的30个目标,学习过程中可能遇到的问题,及学习路线。希望能够对你的学习有所帮助。对比一下自己,你已经掌握了这30条中的多少条了呢? 路线 Java发展到现在,按应用来分主要分为三大...
1 2 3 4 5 ... 20
收藏数 1,045,583
精华内容 418,233