xiaoya的文章

  • Docker(二):Dockerfile 使用介绍


    很早之前就听说过Docker了,但是一直用不到,所以也没有去认真了解过是什么技术,怎么应用。最近正在研发一套系统平台,由于人手不足,只能自己硬着头皮上了,亲自设计系统架构、实现等。其中,为了系统后期方便迁移和部署,想到了Docker。于是,在网上找了一些资料学习学习。我把其中一些个人认为比较优质的博文转载保存,方便查阅。原文链接:Docker(二):Dockerfile 使用介绍

    上一篇文章Docker(一):Docker入门教程介绍了 Docker 基本概念,其中镜像、容器和 Dockerfile 。我们使用 Dockerfile 定义镜像,依赖镜像来运行容器,因此 Dockerfile 是镜像和容器的关键,Dockerfile 可以非常容易的定义镜像内容,同时在我们后期的微服务实践中,Dockerfile 也是重点关注的内容,今天我们就来一起学习它。
    首先通过一张图来了解 Docker 镜像、容器和 Dockerfile 三者之间的关系。

    通过上图可以看出使用 Dockerfile 定义镜像,运行镜像启动容器。
    Dockerfile 概念Docker 镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像不包含任何动态数据,其内容在构建之后也不会被改变。
    镜像的定制实际上就是定制每一层所添加的配置、文件。如果我们可以把每一层修改、安装、构建、操作的命令都写入一个脚本,用这个脚本来构建、定制镜像,那么之前提及的无法重复的问题、镜像构建透明性的问题、体积的问题就都会解决。这个脚本就是 Dockerfile。
    Dockerfile 是一个文本文件,其内包含了一条条的指令(Instruction),每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。有了 Dockerfile,当我们需要定制自己额外的需求时,只需在 Dockerfile 上添加或者修改指令,重新生成 image 即可,省去了敲命令的麻烦。
    Dockerfile 文件格式Dockerfile文件格式如下:
    ## Dockerfile文件格式# This dockerfile uses the ubuntu image# VERSION 2 - EDITION 1# Author: docker_user# Command format: Instruction [arguments / command] ..# 1、第一行必须指定 基础镜像信息FROM ubuntu# 2、维护者信息MAINTAINER docker_user docker_user@email.com# 3、镜像操作指令RUN echo "deb http://archive.ubuntu.com/ubuntu/ raring main universe" >> /etc/apt/sources.listRUN apt-get update && apt-get install -y nginxRUN echo "\ndaemon off;" >> /etc/nginx/nginx.conf# 4、容器启动执行指令CMD /usr/sbin/nginx
    Dockerfile 分为四部分:基础镜像信息、维护者信息、镜像操作指令、容器启动执行指令。一开始必须要指明所基于的镜像名称,接下来一般会说明维护者信息;后面则是镜像操作指令,例如 RUN 指令。每执行一条RUN 指令,镜像添加新的一层,并提交;最后是 CMD 指令,来指明运行容器时的操作命令。
    构建镜像docker build 命令会根据 Dockerfile 文件及上下文构建新 Docker 镜像。构建上下文是指 Dockerfile 所在的本地路径或一个URL(Git仓库地址)。构建上下文环境会被递归处理,所以构建所指定的路径还包括了子目录,而URL还包括了其中指定的子模块。
    将当前目录做为构建上下文时,可以像下面这样使用docker build命令构建镜像:
    docker build .Sending build context to Docker daemon 6.51 MB...
    说明:构建会在 Docker 后台守护进程(daemon)中执行,而不是CLI中。构建前,构建进程会将全部内容(递归)发送到守护进程。大多情况下,应该将一个空目录作为构建上下文环境,并将 Dockerfile 文件放在该目录下。
    在构建上下文中使用的 Dockerfile 文件,是一个构建指令文件。为了提高构建性能,可以通过.dockerignore文件排除上下文目录下不需要的文件和目录。
    在 Docker 构建镜像的第一步,docker CLI 会先在上下文目录中寻找.dockerignore文件,根据.dockerignore 文件排除上下文目录中的部分文件和目录,然后把剩下的文件和目录传递给 Docker 服务。
    Dockerfile 一般位于构建上下文的根目录下,也可以通过-f指定该文件的位置:
    docker build -f /path/to/a/Dockerfile .
    构建时,还可以通过-t参数指定构建成镜像的仓库、标签。
    镜像标签docker build -t nginx/v3 .
    如果存在多个仓库下,或使用多个镜像标签,就可以使用多个-t参数:
    docker build -t nginx/v3:1.0.2 -t nginx/v3:latest .
    在 Docker 守护进程执行 Dockerfile 中的指令前,首先会对 Dockerfile 进行语法检查,有语法错误时会返回:
    docker build -t nginx/v3 .Sending build context to Docker daemon 2.048 kBError response from daemon: Unknown instruction: RUNCMD
    缓存Docker 守护进程会一条一条的执行 Dockerfile 中的指令,而且会在每一步提交并生成一个新镜像,最后会输出最终镜像的ID。生成完成后,Docker 守护进程会自动清理你发送的上下文。 Dockerfile文件中的每条指令会被独立执行,并会创建一个新镜像,RUN cd /tmp等命令不会对下条指令产生影响。 Docker 会重用已生成的中间镜像,以加速docker build的构建速度。以下是一个使用了缓存镜像的执行过程:
    $ docker build -t svendowideit/ambassador .Sending build context to Docker daemon 15.36 kBStep 1/4 : FROM alpine:3.2 ---> 31f630c65071Step 2/4 : MAINTAINER SvenDowideit@home.org.au ---> Using cache ---> 2a1c91448f5fStep 3/4 : RUN apk update && apk add socat && rm -r /var/cache/ ---> Using cache ---> 21ed6e7fbb73Step 4/4 : CMD env | grep _TCP= | (sed 's/.*_PORT_\([0-9]*\)_TCP=tcp:\/\/\(.*\):\(.*\)/socat -t 100000000 TCP4-LISTEN:\1,fork,reuseaddr TCP4:\2:\3 \&/' && echo wait) | sh ---> Using cache ---> 7ea8aef582ccSuccessfully built 7ea8aef582cc
    构建缓存仅会使用本地父生成链上的镜像,如果不想使用本地缓存的镜像,也可以通过--cache-from指定缓存。指定后将不再使用本地生成的镜像链,而是从镜像仓库中下载。
    寻找缓存的逻辑Docker 寻找缓存的逻辑其实就是树型结构根据 Dockerfile 指令遍历子节点的过程。下图可以说明这个逻辑。
    FROM base_image:version Dockerfile: +----------+ FROM base_image:version |base image| RUN cmd1 --> use cache because we found base image +-----X----+ RUN cmd11 --> use cache because we found cmd1 / \ / \ RUN cmd1 RUN cmd2 Dockerfile: +------+ +------+ FROM base_image:version |image1| |image2| RUN cmd2 --> use cache because we found base image +---X--+ +------+ RUN cmd21 --> not use cache because there's no child node / \ running cmd21, so we build a new image here / \RUN cmd11 RUN cmd12+-------+ +-------+|image11| |image12|+-------+ +-------+
    大部分指令可以根据上述逻辑去寻找缓存,除了 ADD 和 COPY 。这两个指令会复制文件内容到镜像内,除了指令相同以外,Docker 还会检查每个文件内容校验(不包括最后修改时间和最后访问时间),如果校验不一致,则不会使用缓存。
    除了这两个命令,Docker 并不会去检查容器内的文件内容,比如 RUN apt-get -y update,每次执行时文件可能都不一样,但是 Docker 认为命令一致,会继续使用缓存。这样一来,以后构建时都不会再重新运行apt-get -y update。
    如果 Docker 没有找到当前指令的缓存,则会构建一个新的镜像,并且之后的所有指令都不会再去寻找缓存。
    简单示例接下来用一个简单的示例来感受一下 Dockerfile 是如何用来构建镜像启动容器。我们以定制 nginx 镜像为例,在一个空白目录中,建立一个文本文件,并命名为 Dockerfile:
    mkdir mynginxcd mynginxvi Dockerfile
    构建一个 Dockerfile 文件内容为:
    FROM nginxRUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.htmlvi Dockerfile
    这个 Dockerfile 很简单,一共就两行涉及到了两条指令:FROM 和 RUN,FROM 表示获取指定基础镜像,RUN 执行命令,在执行的过程中重写了 nginx 的默认页面信息,将信息替换为:Hello, Docker!。
    在 Dockerfile 文件所在目录执行:
    docker build -t nginx:v1 .
    命令最后有一个. 表示当前目录
    构建完成之后,使用 docker images 命令查看所有镜像,如果存在 REPOSITORY 为 nginx 和 TAG 是 v1 的信息,就表示构建成功。
    docker imagesREPOSITORY TAG IMAGE ID CREATED SIZEnginx v1 8c92471de2cc 6 minutes ago 108.6 MB
    接下来使用 docker run 命令来启动容器
    docker run --name docker_nginx_v1 -d -p 80:80 nginx:v1
    这条命令会用 nginx 镜像启动一个容器,命名为docker_nginx_v1,并且映射了 80 端口,这样我们可以用浏览器去访问这个 nginx 服务器:http://192.168.0.54/,页面返回信息:

    这样一个简单使用 Dockerfile 构建镜像,运行容器的示例就完成了!
    修改容器内容容器启动后,需要对容器内的文件进行进一步的完善,可以使用docker exec -it xx bash命令再次进行修改,以上面的示例为基础,修改 nginx 启动页面内容:
    docker exec -it docker_nginx_v1 bashroot@3729b97e8226:/# echo '<h1>Hello, Docker neo!</h1>' > /usr/share/nginx/html/index.htmlroot@3729b97e8226:/# exitexit
    以交互式终端方式进入 docker_nginx_v1 容器,并执行了 bash 命令,也就是获得一个可操作的 Shell。然后,我们用<h1>Hello, Docker neo!</h1>覆盖了 /usr/share/nginx/html/index.html 的内容。
    再次刷新浏览器,会发现内容被改变。

    修改了容器的文件,也就是改动了容器的存储层,可以通过 docker diff 命令看到具体的改动。
    docker diff docker_nginx_v1 ...
    这样 Dockerfile 使用方式就为大家介绍完了,下期为大家介绍 Dockerfile 命令的详细使用。
    参考Dockerfile reference使用Dockerfile构建Docker镜像Docker镜像构建文件Dockerfile及相关命令介绍深入Dockerfile(一): 语法指南Docker — 从入门到实践
    0  留言 2021-02-24 15:24:57
  • Docker(一):Docker入门教程


    很早之前就听说过Docker了,但是一直用不到,所以也没有去认真了解过是什么技术,怎么应用。最近正在研发一套系统平台,由于人手不足,只能自己硬着头皮上了,亲自设计系统架构、实现等。其中,为了系统后期方便迁移和部署,想到了Docker。于是,在网上找了一些资料学习学习。我把其中一些个人认为比较优质的博文转载保存,方便查阅。原文链接:Docker(一):Docker入门教程

    如今Docker的使用已经非常普遍,特别在一线互联网公司。使用Docker技术可以帮助企业快速水平扩展服务,从而到达弹性部署业务的能力。在云服务概念兴起之后,Docker的使用场景和范围进一步发展,如今在微服务架构越来越流行的情况下,微服务+Docker的完美组合,更加方便微服务架构运维部署落地。
    本文详细解释介绍Docker入门相关内容,后期重点关注Docker在微服务体系中的使用。在了解Docker之前我们先考虑几个问题:1、Docker是什么?2、为什么要使用Docker,它有什么优势?带着这些问题我们来看看下面的内容。
    什么是Docker?Docker 是世界领先的软件容器平台。开发人员利用 Docker 可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用 Docker 可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用 Docker 可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为 Linux 和 Windows Server 应用发布新功能。
    Docker 属于 Linux 容器的一种封装,提供简单易用的容器使用接口。它是目前最流行的 Linux 容器解决方案。Docker 将应用程序与该程序的依赖,打包在一个文件里面。运行这个文件,就会生成一个虚拟容器。程序在这个虚拟容器里运行,就好像在真实的物理机上运行一样。有了 Docker,就不用担心环境问题。
    总体来说,Docker 的接口相当简单,用户可以方便地创建和使用容器,把自己的应用放入容器。容器还可以进行版本管理、复制、分享、修改,就像管理普通的代码一样。
    Docker 最初是 dotCloud 公司创始人 Solomon Hykes 在法国期间发起的一个公司内部项目,它是基于 dotCloud 公司多年云服务技术的一次革新,并于 2013 年 3 月以 Apache 2.0 授权协议开源,主要项目代码在 GitHub 上进行维护。Docker 项目后来还加入了 Linux 基金会,并成立推动 开放容器联盟(OCI)。
    Docker 自开源后受到广泛的关注和讨论,至今其 GitHub 项目已经超过 4 万 6 千个星标和一万多个 fork。甚至由于 Docker 项目的火爆,在 2013 年底,dotCloud 公司决定改名为 Docker。Docker 最初是在 Ubuntu 12.04 上开发实现的;Red Hat 则从 RHEL 6.5 开始对 Docker 进行支持;Google 也在其 PaaS 产品中广泛应用 Docker。
    为什么要使用Docker容器除了运行其中应用外,基本不消耗额外的系统资源,使得应用的性能很高,同时系统的开销尽量小。传统虚拟机方式运行 10 个不同的应用就要起 10 个虚拟机,而Docker 只需要启动 10 个隔离的应用即可。
    具体说来,Docker 在如下几个方面具有较大的优势。
    1、更快速的交付和部署
    对开发和运维(devop)人员来说,最希望的就是一次创建或配置,可以在任意地方正常运行。
    开发者可以使用一个标准的镜像来构建一套开发容器,开发完成之后,运维人员可以直接使用这个容器来部署代码。 Docker 可以快速创建容器,快速迭代应用程序,并让整个过程全程可见,使团队中的其他成员更容易理解应用程序是如何创建和工作的。 Docker 容器很轻很快!容器的启动时间是秒级的,大量地节约开发、测试、部署的时间。
    2、更高效的虚拟化
    Docker 容器的运行不需要额外的 hypervisor 支持,它是内核级的虚拟化,因此可以实现更高的性能和效率。
    3、更轻松的迁移和扩展
    Docker 容器几乎可以在任意的平台上运行,包括物理机、虚拟机、公有云、私有云、个人电脑、服务器等。 这种兼容性可以让用户把一个应用程序从一个平台直接迁移到另外一个。
    4、更简单的管理
    使用 Docker,只需要小小的修改,就可以替代以往大量的更新工作。所有的修改都以增量的方式被分发和更新,从而实现自动化并且高效的管理。
    Docker vs VM从下图可以看出,VM是一个运行在宿主机之上的完整的操作系统,VM运行自身操作系统会占用较多的CPU、内存、硬盘资源。Docker不同于VM,只包含应用程序以及依赖库,基于libcontainer运行在宿主机上,并处于一个隔离的环境中,这使得Docker更加轻量高效,启动容器只需几秒钟之内完成。由于Docker轻量、资源占用少,使得Docker可以轻易的应用到构建标准化的应用中。但Docker目前还不够完善,比如隔离效果不如VM,共享宿主机操作系统的一些基础库等;网络配置功能相对简单,主要以桥接方式为主;查看日志也不够方便灵活。

    Docker 在容器的基础上,进行了进一步的封装,从文件系统、网络互联到进程隔离等等,极大的简化了容器的创建和维护。使得 Docker 技术比虚拟机技术更为轻便、快捷。
    作为一种新兴的虚拟化方式,Docker 跟传统的虚拟化方式相比具有众多的优势。Docker 容器的启动可以在秒级实现,这相比传统的虚拟机方式要快得多;Docker 对系统资源的利用率很高,一台主机上可以同时运行数千个 Docker 容器。
    相关概念Docker是CS架构,主要有两个概念:

    Docker daemon: 运行在宿主机上,Docker守护进程,用户通过Docker client(Docker命令)与Docker daemon交互Docker client: Docker 命令行工具,是用户使用Docker的主要方式,Docker client与Docker daemon通信并将结果返回给用户,Docker client也可以通过socket或者RESTful api访问远程的Docker daemon

    了解了Docker的组成,再来了解一下Docker的三个主要概念:

    Docker image:镜像是只读的,镜像中包含有需要运行的文件。镜像用来创建container,一个镜像可以运行多个container;镜像可以通过Dockerfile创建,也可以从Docker hub/registry上下载。Docker container:容器是Docker的运行组件,启动一个镜像就是一个容器,容器是一个隔离环境,多个容器之间不会相互影响,保证容器中的程序运行在一个相对安全的环境中。Docker hub/registry: 共享和管理Docker镜像,用户可以上传或者下载上面的镜像,官方地址为https://registry.hub.docker.com/,也可以搭建自己私有的Docker registry。
    镜像就相当于打包好的版本,镜像启动之后运行在容器中,仓库就是装存储镜像的地方。
    Docker安装建议在linux环境下安装Docker,window环境搭建比较复杂且容易出错,使用Centos7+yum来安装Docker环境很方便。
    Docker 软件包已经包括在默认的 CentOS-Extras 软件源里。因此想要安装 docker,只需要运行下面的 yum 命令:
    yum install docker
    安装完成后,使用下面的命令来启动 docker 服务,并将其设置为开机启动:
    service docker startchkconfig docker on

    LCTT 译注:此处采用了旧式的 sysv 语法,如采用CentOS 7中支持的新式 systemd 语法,如下:

    systemctl start docker.servicesystemctl enable docker.service
    测试
    docker version
    输入上述命令,返回docker的版本相关信息,证明docker安装成功。
    Hello World下面,我们通过最简单的 image 文件”hello world”,感受一下 Docker。
    因为国内连接 Docker 的官方仓库很慢,因此我们在日常使用中会使用Docker 中国加速器。通过 Docker 官方镜像加速,中国区用户能够快速访问最流行的 Docker 镜像。该镜像托管于中国大陆,本地用户现在将会享受到更快的下载速度和更强的稳定性,从而能够更敏捷地开发和交付 Docker 化应用。
    Docker 中国官方镜像加速可通过registry.docker-cn.com访问。该镜像库只包含流行的公有镜像,私有镜像仍需要从美国镜像库中拉取。
    修改系统中docker对应的配置文件即可,如下:
    vi /etc/docker/daemon.json#添加后{ "registry-mirrors": ["https://registry.docker-cn.com"], "live-restore": true}
    运行下面的命令,将 image 文件从仓库抓取到本地。
    docker pull library/hello-world
    上面代码中,docker image pull是抓取 image 文件的命令。library/hello-world是 image 文件在仓库里面的位置,其中library是 image 文件所在的组,hello-world是 image 文件的名字。
    抓取成功以后,就可以在本机看到这个 image 文件了。
    docker images#显示结果REPOSITORY TAG IMAGE ID CREATED SIZEdocker.io/hello-world latest f2a91732366c 3 months ago 1.848 kB
    现在,运行这个 image 文件。
    docker run hello-world#显示结果Hello from Docker!This message shows that your installation appears to be working correctly....
    输出这段提示以后,hello world就会停止运行,容器自动终止。有些容器不会自动终止,因为提供的是服务,比如Mysql镜像等。
    常用命令除过以上我们使用的Docker命令外,Docker还有一些其它常用的命令
    拉取docker镜像
    docker pull image_name
    查看宿主机上的镜像,Docker镜像保存在/var/lib/docker目录下:
    docker images
    删除镜像
    docker rmi docker.io/tomcat:7.0.77-jre7 或者 docker rmi b39c68b7af30
    查看当前有哪些容器正在运行
    docker ps
    查看所有容器
    docker ps -a
    启动、停止、重启容器命令:
    docker start container_name/container_iddocker stop container_name/container_iddocker restart container_name/container_id
    后台启动一个容器后,如果想进入到这个容器,可以使用attach命令:
    docker attach container_name/container_id
    删除容器的命令:
    docker rm container_name/container_id
    删除所有停止的容器:
    docker rm $(docker ps -a -q)
    查看当前系统Docker信息
    docker info
    从Docker hub上下载某个镜像:
    docker pull centos:latestdocker pull centos:latest
    查找Docker Hub上的nginx镜像
    docker search nginx
    执行docker pull centos会将Centos这个仓库下面的所有镜像下载到本地repository。
    参考Docker — 从入门到实践Docker系列之一:入门介绍Docker 入门教程
    0  留言 2021-02-23 08:53:13
  • 基于Servlet和Ajax实现搜索框智能提示


    前段时间自己项目需要实现智能提示功能,于是在网上搜索了相关技术,发现这一篇博文介绍得较为详细,故自己排了下版面,转载到此处,方便自己今后查阅。

    一、简介搜索框相信大家都不陌生,几乎每天都会在各类网站进行着搜索。有没有注意到,很多的搜索功能,当输入内容时,下面会出现提示。这类提示就叫做搜索框的智能提示,本次就为大家介绍如何使用Servlet和Ajax来实现。主要介绍实现原理和代码的前后台实现过程。
    二、项目分析
    实现语言:java
    实现方式:Ajax异步传输
    案例:比如百度的搜索框智能提示


    理论分析:

    在搜索框输入关键字
    浏览器将关键字异步发送给服务器
    服务器经过处理,将相应的数据以JSon(xml)格式返回给客户端
    客户端接收到服务器的响应数据,解析之后使用JS操作DOM显示数据

    演示流程图分析:

    重点内容:

    数据交互采用ajax方式
    JavaScript解析数据动态展示

    三、页面开发3.1 HTML部分body内容
    <body> <div id="mydiv"> <!--输入框--> <input type="text" size="50" id="keyword" onkeyup="getMoreContents()" onblur="keywordBlur()" onfocus="getMoreContents()"/> <input type="button" value="百度一下" width="50px"> <!--内容展示区域--> <div id="popdiv"> <table id="content_table" bgcolor="#FFFAFA" border="0" cellspacing="0" cellpadding="0"> <tbody id="content_table_body"> <%--动态查询出来的数据,显示在此--%> </tbody> </table> </div> </div></body>
    3.2 CSS部分样式代码
    <style type="text/css"> #mydiv { position: absolute; left: 50%; top: 50%; margin-left: -200px; margin-top: -50px; } .mouseOver { background: #708090; color: #FFFAFA; } .mouseOut { background: #FFFAFA; color: #000000; }</style>
    3.3 JavaScript部分获取用户输入内容的关联信息的函数
    function getMoreContents() { //首先获取用户的输入 var content = document.getElementById("keyword"); if (content.value == "") { clearContent(); return; } //然后给服务器发送用户输入的内容,因为采用ajax异步发送数据,所以使用XmlHttp对象 xmlHttp = creatXMLHttp(); //给服务器发送数据 var url = "search?keyword=" + escape(content.value); xmlHttp.open("GET", url, true); //xmlHttp绑定回调方法,这个回调方法会在xmlHttp状态改变的时候被调用 //xmlHttp 状态0-4,我们只关心4(complete),完成后再调用回调方法才有意义 xmlHttp.onreadystatechange = callback; xmlHttp.send(null);}
    获取XmlHttp对象
    function creatXMLHttp() { //对于大多数浏览器都适用 var xmlHttp; if (window.XMLHttpRequest) { xmlHttp = new XMLHttpRequest(); } //要考虑浏览器的兼容性 if (window.ActiveXObject) { xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); if (!xmlHttp) { xmlHttp = new ActiveXObject("Msxml2.XMLHTTP"); } } return xmlHttp;}
    回调函数
    function callback() { //4代表成功 if (xmlHttp.readyState == 4) { //200代表服务器响应成功 if (xmlHttp.status == 200) { //交互成功 获得响应的数据 是文本格式 var result = xmlHttp.responseText; //解析数据 var json = eval("(" + result + ")"); //获取数据后动态显示 展示输入框下面 setContent(json); } }}
    设置关联数据展示
    function setContent(contents) { clearContent(); setLocation(); //获取关联数据的长度,以此来确定生成的<tr> var size = contents.length; //设置内容 for (var i = 0; i < size; i++) { var nextNode = contents[i];//代表的是JSon数据的第i个元素 var tr = document.createElement("tr"); var td = document.createElement("td"); td.setAttribute("border", "0"); td.setAttribute("bgcolor", "#FFFAFA"); td.onmouseover = function () { this.className = 'mouseOver'; }; td.onmouseout = function () { this.className = 'mouseOut'; }; td.onmousedown=function(){ //当鼠标点击一个关联数据的时候,被选中的数据 自动填充到输入框里面 document.getElementById("keyword").value=this.innerHTML; //清除div边框 document.getElementById("popDiv").style.border="none"; }; var text = document.createTextNode(nextNode); td.appendChild(text); tr.appendChild(td); document.getElementById("content_table_body").appendChild(tr); }}
    3.4 前后台程序联调清空之前的数据
    function clearContent() { var contentTableBody = document.getElementById("content_table_body"); var size = contentTableBody.childNodes.length; for (var i = size - 1; i >= 0; i--) { contentTableBody.removeChild(contentTableBody.childNodes[i]); } document.getElementById("popdiv").style.border = "none";}
    输入框失去焦点 清空
    function keywordBlur() { clearContent();}
    设置显示关联信息
    function setLocation() { //关联信息的显示位置 var content = document.getElementById("keyword"); var width = content.offsetWidth;//输入框的宽度 var left = content["offsetLeft"];//距离左边框的距离 var top = content["offsetTop"] + content.offsetHeight;//距离顶部 //获取显示数据div var popdiv = document.getElementById("popdiv"); popdiv.style.border = "black 1px solid"; popdiv.style.left = left + "px"; popdiv.style.top = top + "px"; popdiv.style.width = width + "px"; document.getElementById("content_table").style.width = width + "px";}
    3.5 编写SearchServlet.javaimport net.sf.json.JSONArray;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 SearchServlet extends HttpServlet { static List<String> datas = new ArrayList<String>(); //模拟数据 static { datas.add("ajax"); datas.add("ajax post"); datas.add("becky"); datas.add("bill"); datas.add("james"); datas.add("jerry"); datas.add("hao"); } @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,IOException{ request.setCharacterEncoding("utf-8"); response.setCharacterEncoding("utf-8"); System.out.print("123"); //获取客户端数据 String keyword = request.getParameter("keyword"); //获取关键字 List<String> listData = getData(keyword); //返回json格式 response.getWriter().write(JSONArray.fromObject(listData).toString()); } public List<String> getData(String keyword){ List<String> list = new ArrayList<String>(); for (String data:datas) { if(data.contains(keyword)){ list.add(data); } } return list; }}
    四、最终效果图输入搜索信息下面会智能提示,点击提示信息会自动输入到搜索框中:

    五、项目地址geekerstar/AjaxSearch


    版权声明:本文(除特殊标注外)为原创文章,版权归 Geekerstar 所有。
    本文链接:http://www.geekerstar.com/project/620.html
    除了有特殊标注文章外欢迎转载,但请务必标明出处,格式如上,谢谢合作。
    本作品采用 知识共享署名-非商业性使用-相同方式共享 3.0 中国大陆许可协议 进行许可。
    0  留言 2021-02-22 09:01:01
  • 【翻译】基于python-docx实现的解析docx文件,顺序保存文字、表格、图片

    前些天由于程序的需要,要从docx文档中,按文档的顺序获取文字、图片、表格信息,按自己想要的排版方式,转换成markdown格式。但是,卡在了按顺序获取文字、图片、表格上。查找了很多资料,很多都是介绍怎么使用python-docx添加文字、图片、表格的。后来经过多方查找,终于找到一份国外的源码(源码地址附在文后),已经实现了按顺序获取文字、图片、表格的功能。为了节省大家搜索时间,所以把他的英文文档翻译成中文,方便大家查阅。原文翻译如下:
    python-docx是用于创建和处理Microsoft Word(.docx)文件的Python库。Python-docx包无法按文档顺序完全读取段落,表格和图像。按照文档顺序,它只能一次获取所有段落,或者一次获取所有表格,或者一次获取所有图像。在这里,我提供了一种方法,可以将docx文件中的段落、表格和图像按文档顺序读取到python的数据框中。
    该代码位于“Para_table_image_extraction.py”的文件内。在以任何docx文件作为输入运行此代码时,此代码将生成3个数据帧,即“combined_df”、“table_list”和“image_df”:

    docx文件的所有内容(包括段落,表和图像)都按顺序存储在名为“combined_df”的python数据帧中
    如果在文档的段落之后出现图像,则对该图像的引用将存储在“combined_df”数据框中,而不是实际图像。您将必须从“combined_df”引用图像索引,并从名为“image_df”的单独数据帧中检索图像数据,该数据帧存储image_index和每个图像的相应base64编码图像数据
    类似地,如果在文档中遇到表,则将填充“combined_df”数据框中的“table_id”列。而且,您将不得不从“table_list”中检索与“ table_id”相关的对应表

    下图是示例 word 文档(docx):

    下图是根据上述docx文件生成的“combined_df”数据帧:

    在上述数据帧中:

    para_text:表示文档的实际段落内容(每一行代表文档中的每个段落)
    table_id:表示表格的表ID(如果在该文档的该位置存在表)。如果没有表格,则其值表示为“ Novalue”
    style:代表相应段落的段落样式

    注意,图像和表格不会这样存储在combined_df数据框中。对这些对象的引用仅存储在combined_df中。这意味着对于在Combined_df中存在的每个图像ID或表格ID,您将必须从combined_df中检索图像ID或表格ID,并从image_df和table_list中根据这些ID来获取图像数据或表格数据。
    图像文件以以下符号表示:
    combined_df中的 Document_Imagefile/image1.png/rId7/0这表示该引用实际上是一个图像文件,其中“image1.png”作为图像名称,“rId7”作为图像的唯一ID或标识符,“0”图片索引将在image_df中引用。

    表格对象表示为“<docx.table.0x1020f1160处的表对象>”,它表示在该位置存在一个带有相应table_id的表。您可以在“table_list”索引中根据table_id来获取获取表格数据。table_list包含所有表格的信息。

    我还没有包含使用来自combined_df的唯一标识符从image_df和table_list提取图像和表格的代码。我之所以没有这样做,是因为用例可能因情况而异。您可以用自己的方式提取它们,然后执行您希望执行的任何后续操作。
    原文链接:Python-docx-Reading-paragraphs-tables-and-images-in-document-order
    0  留言 2021-02-13 10:13:48
  • 使用Windows7旗舰版64位来搭建ASP服务器环境

    背景一直来都听别人说,只需要一个公网IP和24小时都开着机,任何一台计算机都可以用来做网站的服务器。由于自己一直没有接触过这方面的知识技术,所以,始终处于似懂非懂的状态。直到某天,我们需要做一个项目,需要写一个客户端上传文件到服务器,而客户端的工作由我负责,所以,为了测试自己写的客户端能不能正常上传文件,就需要本地搭建一个服务器来进行测试。
    自己对Windows系统方面比较熟悉,所以虚拟机里也都是Windows系统的虚拟机。在网上查阅了相关资料后,发现大都是使用Windows Server的操作系统来搭建服务器比较多。但,时间紧迫,不可能还特地下个Windows Server去测试,所以想起了那句话“任何计算机都可以用来做服务器”。于是,便选了Windows 7 64位旗舰版,用来搭建服务器。
    步骤准备一个Windows7 64位旗舰版操作系统。
    1. 安装相应功能组件按顺序以此打开:“开始” —> “控制面板” —> “程序” —> “程序和功能” —> 在窗口的左侧点击“打开或关闭Windows功能”,这样便会弹出如下图所示的窗口。

    点击“Internet 信息服务”前面的“+”,展开子选项,然后将子选项也都全部展开;然后,全部勾选!(这里需要注意的是,一定要全部展开后,再勾选!切不可直接在上级选项点击勾选,这样并不会全部勾选完!所以,一定要全都展开后,再勾选!)

    勾选完成后,点击“确定”,这时需要等一会儿系统安装相应组件。

    2. 添加网站组件安装完成后,回到桌面,鼠标右击“计算机”,选中并点击“管理”,来到管理界面后,在左侧选中并点击“Internet 信息服务(IIS)管理器”,这样,便会显示“Internet 信息服务(IIS)管理器”的管理界面窗口。

    这时,便可以添加自己的网站,进行网站设置了。
    选中“网站”并右击,选择“添加网站…”。

    在“添加网站”对话框中,写入你的网站设置信息.写入网站名称、网页数据存储的路径等,如下图所示。写入完毕后,点击“确定”。

    3. 启动父路径接着,选中自己的网站,在功能视图中,选中“ASP”并双击打开。在“启用父路径”中选择“True”,然后点击右侧的“应用”。


    4. 启用32位应用程序选中“应用程序池”,页面更改后,点击右侧的“设置应用程序池默认设置…”。在“启用32位应用程序”中选择“True”,然后点击“确定”。


    5. 设置网站默认文档最后一步设置,就是添加网站的默认网页。先选中自己的网站,在“功能视图”中选中“默认文档”,并双击打开。

    切换到“默认文档页面”,点击右侧的“添加…”。

    在“添加默认文档”窗口中,输入网站的默认文档,如:index.asp,然后点击“确定”。这是,便可以将自己的网页数据,拷贝到前面设置好的网站物理路径下面了。

    注意:要关闭防火墙PS:要注意的是,再打开网站之前,先检查服务器计算机的防火墙是否处于打开状态。

    若是开启状态,则需要关闭。

    成功关闭后,便可以使用浏览器输入网址,查看网站,就能看到网站正常显示了~

    总结步骤不算是复杂,主要是注意下细节就好了。自己配置的时候,便在上面的组件安装那里犯了错误。原因是我以为只要勾选了父选项,子选项默认也都勾选了。没想到不是这样的,所以,大家在勾选的时候,一定要注意,先把所有选项都展开后,再勾选,这样可以避免一些不必要的错漏。
    1  留言 2018-12-26 09:45:36
  • 使用Windows7旗舰版64位来搭建本地HTTPS测试的ASP服务器

    背景近期写的一个小程序里面,需要用到HTTPS协议来传输数据到指定的HTTPS服务器上面。上传数据的客户端使用WININET库开发完成,但是需要搭建本地测试环境,来测试程序能够成功发送数据到HTTPS的服务器上面。所以,从网上查询了一些相关资料,把环境给成功搭建起来了。现在,想把自己搭建HTTPS测试环境的过程,也分享给大家。
    步骤参考本站上的 《使用Windows7旗舰版64位来搭建ASP服务器环境》 一文来配置ASP服务器,我们是在此ASP服务器上进行配置的。
    按上面参考文章步骤成功安装ASP服务器后,打开“Internet 信息服务(IIS)管理器”,在“功能视图”中选中并双击打开“服务器证书”。

    进入“服务器证书”页面后,点击右侧的“创建自签名证书…”。

    接着,任意新创建的自签名证书设置一个名称,如:“MyHttpsTest”。输入完毕后,点击“确定”。

    接着选中ASP服务器网站,然后,点击右侧的“绑定…”。

    在“网站绑定”窗口中,点击“添加(A)…”。

    在“添加网站绑定窗口”中,“类型(T)”选择“https”,“IP地址(I)”选择服务器的IP地址,“SSL证书()S”选择刚刚创建的自签名证书“MyHttpsTest”,接着点击“确定”。

    这样,便可以成功为网站设置了自签名证书,可以在浏览器中输入:https://192.168.28.137 进行测试。网站可以正常打开,在浏览器中,https有一条红色的斜杠,而且提示“网站的安全证书不受信任”,那是因为我们使用的是自签名证书,并非权威机构颁发的证书,所以会有此提示,不过这不影响到我们使用的HTTPS数据传输。

    总结步骤比较简单,仔细跟着操作应该不会有什么问题。
    2  留言 2018-12-26 09:45:28
eject