vosamo 2017-10-03T02:52:39+00:00 kejinlu@gmail.com 2017-10-03T00:00:00+00:00 vosamo http://vosamo.github.io/2017/10/yu 五龙潭

五龙潭
我希望变成一条鱼

在趵突泉的涛声中无忧无虑

或者在五龙潭的清池中嬉戏

这是一片欢乐的海洋

有无数的同伴在此徜徉



或许有一天

我偷偷地游进了护城河

肆无忌惮地东闯西荡

仿佛发现了新的天地

偶尔馋嘴的时候

去偷食垂钓者的鱼饵

体验冒险的别样刺激

或者追逐游船的浪花

听着游人的欢声笑语



沿着护城河

我一路狂飙

突然闯进了一片宽阔的海洋

我在荷花从中穿梭

能瞥见千佛山的倒影

我在这海洋中遨游

忘记了迷路的恐惧



当我累了的时候

我就驻足在泉城广场

听会儿音乐喷泉

望着空中游动的鱼形风筝

一时之间恍惚不清

自己是在天上

还是水中
]]>
JSP学习笔记之二(JSP语法) 2016-12-20T00:00:00+00:00 vosamo http://vosamo.github.io/2016/12/JSP-Notes-2 JSP学习笔记之一(JSP介绍) 2016-12-20T00:00:00+00:00 vosamo http://vosamo.github.io/2016/12/JSP-Notes-1 JSP(Java Server Pages)是一种动态网页开发技术,它使用JSP标签在HTML网页中插入Java代码。JSP主要用于实现Java Web应用程序的用户界面部分。JSP经过编译之后编程Servlet,所以JSP的本质就是Servlet。JSP更擅长页面表现,Servlet更擅长逻辑控制。JSP是Servlet技术的扩展。

JSP结构

JSP容器与Web服务器协同合作,为JSP的正常运行提供必要的环境和其他服务。下图显示了JSP容器和JSP文件在Web应用中所处的位置:

JSP结构

Web服务器使用JSP创建网页的步骤:

  1. 浏览器发送请求给服务器
  2. Web服务器识别出这是对JSP网页的请求,将该请求传递给JSP引擎
  3. JSP引擎从磁盘载入JSP文件,转化为Servlet(将模板文本替换为println()语句;将所有JSP元素转化成Java代码)
  4. JSP引擎将servlet编译为可执行类,并且将原始请求传递给servlet引擎
  5. Web服务器的某组件将会调用servlet引擎,然后载入并执行servlet类。在执行过程中,servlet产生HTML格式的输出并将其内嵌于HTTP response中上交给Web服务器
  6. Web服务器以静态HTML网页的形式将HTTP response返回到您的浏览器中

上述步骤可以用下图展示:

一般情况下,JSP引擎会检查JSP文件对应的servlet是否已经存在,并且检查JSP文件的修改日期是否早于servlet。如果JSP文件的修改日期早于对应的servlet,那么容器就可以确定JSP文件没有被修改过并且servlet有效。这使得整个流程与其他脚本语言(比如PHP)相比要高效快捷一些。

JSP生命周期

JSP的生命周期和Servlet类似,区别在于JSP生命周期还包括将JSP文件编译成servlet。JSP的生命周期包括四个阶段:编译、初始化、执行、销毁

编译

当浏览器请求JSP页面时,JSP引擎首先检查是否需要编译这个文件,如果没有编译过或者上次编译之后更新过,则需要编译这个JSP文件。

编译的过程包括三个步骤:

  1. 解析JSP文件
  2. 将JSP文件转化为servlet
  3. 编译servlet

初始化

容器载入JSP文件后,它会在为请求提供任何服务前调用jspInit()方法。

执行

JSP完成初始化之后,JSP引擎会调用_jspService()方法,该方法有一个HttpServletRequest对象和一个HttpServletResponse对象作参数。

_jspService()方法在每个request中被调用一次并且负责产生与之相对应的response,并且它还负责产生所有7个HTTP方法的回应,比如GET、POST、DELETE等等。

销毁

jspDestroy()方法在JSP中等价于servlet中的销毁方法。当您需要执行任何清理工作时复写jspDestroy()方法,比如释放数据库连接或者关闭文件夹等等。

实例

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<html>
<head>
<title>life.jsp</title>
</head>
<body>

<%!
  private int initVar=0;
  private int serviceVar=0;
  private int destroyVar=0;
%>

<%!
  public void jspInit(){
    initVar++;
    System.out.println("jspInit(): JSP被初始化了"+initVar+"次");
  }
  public void jspDestroy(){
    destroyVar++;
    System.out.println("jspDestroy(): JSP被销毁了"+destroyVar+"次");
  }
%>

<%
  serviceVar++;
  System.out.println("_jspService(): JSP共响应了"+serviceVar+"次请求");

  String content1="初始化次数 : "+initVar;
  String content2="响应客户请求次数 : "+serviceVar;
  String content3="销毁次数 : "+destroyVar;
%>
<h1>菜鸟教程 JSP 测试实例</h1>
<p><%=content1 %></p>
<p><%=content2 %></p>
<p><%=content3 %></p>

</body>
</html>
]]>
Servlet学习笔记之五(Servlet Cookie和Session处理) 2016-12-15T00:00:00+00:00 vosamo http://vosamo.github.io/2016/12/Servlet-Notes-5 Cookie

Cookie是存储在客户端计算机上的文本文件,并保留了各种跟踪信息。Cookie通常设置在HTTP 头信息中。识别返回用户包括三个步骤:

  • 服务器脚本向浏览器发送一组 Cookie。例如:姓名、年龄或识别号码等。
  • 浏览器将这些信息存储在本地计算机上,以备将来使用。
  • 当下一次浏览器向 Web 服务器发送任何请求时,浏览器会把这些 Cookie 信息发送到服务器,服务器将使用这些信息来识别用户。

Servlet 就能够通过请求方法 request.getCookies() 访问 Cookie,该方法将返回一个 Cookie 对象的数组。

Servlet Cookie方法

Servlet有许多操作Cookie的方法,比较重要的有以下几个方法:

  • public void setMaxAge(int expiry):设置cookie的过期时间,以秒为单位。不设置的话,cookie默认只在当前会话有效。
  • public int getMaxAge():返回cookie的生存时间,默认情况下,-1表示cookie将继续下去,直到浏览器关闭。
  • public String getName():返回cookie的名字,名字在cookie创建后不能改变。
  • public void setValue(String newValue):设置与cookie关联的值。
  • public String getValue():获取与cookie关联的值。

通过Servlet设置Cookie

分三步:

  1. 创建一个Cookie对象,使用带有Cookie名称和值的构造函数,名称和值都是字符串。

    Cookie cookie = new Cookie(“key”,”value”);

  2. 设置最大生存时间,下面将设置一个有效期为24小时的cookie:

    cookie.setMaxAge(60*60*24);

  3. 发送cookie到HTTP响应头:response.addCookie(cookie);

通过Servlet删除Cookie

删除一个cookie很简单:读取欲删除的cookie;使用setMaxAge()设置cookie的生存期为0;把这个cookie添加到响应头。

Session

HTTP 是一种”无状态”协议,这意味着每次客户端检索网页时,客户端打开一个单独的连接到 Web 服务器,服务器会自动不保留之前客户端请求的任何记录。

HttpSession 对象

Servlet 提供了 HttpSession 接口,该接口提供了一种跨多个页面请求或访问网站时识别用户以及存储有关用户信息的方式。Servlet 容器使用这个接口来创建一个 HTTP 客户端和 HTTP 服务器之间的 session 会话。会话持续一个指定的时间段,跨多个连接或页面请求。通过调用 HttpServletRequest 的公共方法 getSession() 来获取 HttpSession 对象。

HttpSession session = request.getSession();

需要在向客户端发送任何文档内容之前调用 request.getSession()。

Session跟踪实例

import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;

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

/**
 * Servlet implementation class SessionTrack
 */
@WebServlet("/SessionTrack")
public class SessionTrack extends HttpServlet {
	private static final long serialVersionUID = 1L;

	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
	{
		// 如果不存在 session 会话,则创建一个 session 对象
		HttpSession session = request.getSession(true);
		// 获取 session 创建时间
		Date createTime = new Date(session.getCreationTime());
		// 获取该网页的最后一次访问时间
		Date lastAccessTime = new Date(session.getLastAccessedTime());

	    //设置日期输出的格式  
	    SimpleDateFormat df=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  

		String title = "Servlet Session 实例 - 菜鸟教程";
		Integer visitCount = new Integer(0);
		String visitCountKey = new String("visitCount");
		String userIDKey = new String("userID");
		String userID = new String("Runoob");

		// 检查网页上是否有新的访问者
		if (session.isNew()){
			title = "Servlet Session 实例 - 菜鸟教程";
		 	session.setAttribute(userIDKey, userID);
		} else {
		 	visitCount = (Integer)session.getAttribute(visitCountKey);
		 	visitCount = visitCount + 1;
		 	userID = (String)session.getAttribute(userIDKey);
		}
		session.setAttribute(visitCountKey,  visitCount);

		// 设置响应内容类型
		response.setContentType("text/html;charset=UTF-8");
		PrintWriter out = response.getWriter();

		String docType = "<!DOCTYPE html>\n";
		out.println(docType +
		        "<html>\n" +
		        "<head><title>" + title + "</title></head>\n" +
		        "<body bgcolor=\"#f0f0f0\">\n" +
		        "<h1 align=\"center\">" + title + "</h1>\n" +
		         "<h2 align=\"center\">Session 信息</h2>\n" +
		        "<table border=\"1\" align=\"center\">\n" +
		        "<tr bgcolor=\"#949494\">\n" +
		        "  <th>Session 信息</th><th>值</th></tr>\n" +
		        "<tr>\n" +
		        "  <td>id</td>\n" +
		        "  <td>" + session.getId() + "</td></tr>\n" +
		        "<tr>\n" +
		        "  <td>创建时间</td>\n" +
		        "  <td>" +  df.format(createTime) +
		        "  </td></tr>\n" +
		        "<tr>\n" +
		        "  <td>最后访问时间</td>\n" +
		        "  <td>" + df.format(lastAccessTime) +
		        "  </td></tr>\n" +
		        "<tr>\n" +
		        "  <td>用户 ID</td>\n" +
		        "  <td>" + userID +
		        "  </td></tr>\n" +
		        "<tr>\n" +
		        "  <td>访问统计:</td>\n" +
		        "  <td>" + visitCount + "</td></tr>\n" +
		        "</table>\n" +
		        "</body></html>");
	}
}
]]>
Servlet学习笔记之四(Servlet过滤器) 2016-12-05T00:00:00+00:00 vosamo http://vosamo.github.io/2016/12/Servlet-Notes-4 Servlet过滤器

Servlet过滤器可以动态拦截请求和响应,以变换或使用包含在请求或响应中的信息。可以将一个或多个Servlet过滤器附加到一个或一组Servlet。Servlet过滤器也可以附加到jsp和html文件。调用servlet前调用所有附加的Servlet过滤器。

Servlet 过滤器是可用于 Servlet 编程的 Java 类,可以实现以下目的:

  • 在客户端的请求访问后端资源之前,拦截这些请求。
  • 在服务器的响应发送回客户端之前,处理这些响应。

根据规范建议的各种类型的过滤器:

  • 身份验证过滤器(Authentication Filters)。
  • 数据压缩过滤器(Data compression Filters)。
  • 加密过滤器(Encryption Filters)。
  • 触发资源访问事件过滤器。
  • 图像转换过滤器(Image Conversion Filters)。
  • 日志记录和审核过滤器(Logging and Auditing Filters)。
  • MIME-TYPE 链过滤器(MIME-TYPE Chain Filters)。
  • 标记化过滤器(Tokenizing Filters)。
  • XSL/T 过滤器(XSL/T Filters),转换 XML 内容。

过滤器通过 Web 部署描述符(web.xml)中的 XML 标签来声明,然后映射到您的应用程序的部署描述符中的 Servlet 名称或 URL 模式。

Servlet过滤器方法

过滤器是一个实现了java.servlet.Filter接口的Java类。该接口定义了三个方法:

  • public void doFilter(ServletRequest, ServletResponse, FilterChain),该方法完成实际的过滤操作,当客户端请求方法与过滤器设置匹配的URL时,Servlet容器将先调用过滤器的doFilter方法。FilterChain用户访问后续过滤器。
  • public void init(FilterConfig filterConfig),web 应用程序启动时,web 服务器将创建Filter 的实例对象,并调用其init方法,读取web.xml配置,完成对象的初始化功能,从而为后续的用户请求作好拦截的准备工作(filter对象只会创建一次,init方法也只会执行一次)。开发人员通过init方法的参数,可获得代表当前filter配置信息的FilterConfig对象。
  • public void destroy(),Servlet容器在销毁过滤器实例前调用该方法,在该方法中释放Servlet过滤器占用的资源。

FilterConfig使用

Filter的init方法中提供了一个FilterConfig对象,在web.xml中的配置如下:

<filter>
	<filter-name>LoginFilter</filter-name>
	<filter-class>com.runoob.test.LogFilter</filter-class>
	<init-param>
		<param-name>Site</param-name>
		<param-value>菜鸟教程</param-value>
	</init-param>
</filter>

在 init 方法使用 FilterConfig 对象获取参数:

public void  init(FilterConfig config) throws ServletException {
	// 获取初始化参数
	String site = config.getInitParameter("Site");
	// 输出初始化参数
	System.out.println("网站名称: " + site);
}

Servlet 过滤器实例

我们先定义一个Servlet:

package com.vosamo.serv;

import java.util.Enumeration;
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;

/**
 * Servlet implementation class DisplayHeader
 */
public class DisplayHeader extends HttpServlet {
	private static final long serialVersionUID = 1L;

    /**
     * @see HttpServlet#HttpServlet()
     */
    public DisplayHeader() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
	    response.setContentType("text/html;charset=UTF-8");
		PrintWriter out = response.getWriter();
		String title = "HTTP Header 请求实例 - 菜鸟教程实例";
        String docType =
            "<!DOCTYPE html> \n";
            out.println(docType +
            "<html>\n" +
            "<head><meta charset=\"utf-8\"><title>" + title + "</title></head>\n"+
            "<body bgcolor=\"#f0f0f0\">\n" +
            "<h1 align=\"center\">" + title + "</h1>\n" +
            "<table width=\"100%\" border=\"1\" align=\"center\">\n" +
            "<tr bgcolor=\"#949494\">\n" +
            "<th>Header 名称</th><th>Header 值</th>\n"+
            "</tr>\n");

        Enumeration headerNames = request.getHeaderNames();

        while(headerNames.hasMoreElements()) {
            String paramName = (String)headerNames.nextElement();
            out.print("<tr><td>" + paramName + "</td>\n");
            String paramValue = request.getHeader(paramName);
            out.println("<td> " + paramValue + "</td></tr>\n");
        }
        out.println("</table>\n</body></html>");
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}

然后定义一个绑定到该Servlet的Filter:

package com.vosamo.serv;

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

/**
 * Servlet Filter implementation class DisplayHeaderFilter
 */
public class DisplayHeaderFilter implements Filter {

    /**
     * Default constructor.
     */
    public DisplayHeaderFilter() {
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see Filter#destroy()
	 */
	public void destroy() {
		// TODO Auto-generated method stub
	}

	/**
	 * 该方法完成实际的过滤操作,当客户端请求与过滤设置匹配的URL时,Servlet容器将先调用
	 * 过滤器的doFilter方法;FilterChain用于访问后续过滤器
	 * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
	 */
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		// TODO Auto-generated method stub
		// place your code here
	    System.out.println("网站地址: http://www.runoob.com");
		// pass the request along the filter chain
		chain.doFilter(request, response);
	}

	/**
	 * init方法只在web应用启动时执行一次,使用FilterConfig对象获取参数
	 * @see Filter#init(FilterConfig)
	 */
	public void init(FilterConfig fConfig) throws ServletException {
		// TODO Auto-generated method stub
	    String site = fConfig.getInitParameter("Site");
	    System.out.println("网站名称: " + site);
	}

}

过滤器映射

<filter>
  <display-name>DisplayHeaderFilter</display-name>
  <filter-name>DisplayHeaderFilter</filter-name>
  <filter-class>com.vosamo.serv.DisplayHeaderFilter</filter-class>
  <init-param>
    <param-name>Site</param-name>
    <param-value>菜鸟教程</param-value>
  </init-param>
</filter>
<filter-mapping>
  <filter-name>DisplayHeaderFilter</filter-name>
  <servlet-name>DisplayHeader</servlet-name>
  <url-pattern>/servletTest/DisplayHeader</url-pattern>
</filter-mapping>

这样访问/servletTest/DisplayHeader时,会被过滤器DisplayHeaderFilter拦截,然后执行doFilter方法,最后返回响应。

Web 应用程序可以根据特定的目的定义若干个不同的过滤器。假设您定义了两个过滤器 AuthenFilter 和 LogFilter。web.xml 中的 filter-mapping 元素的顺序决定了 Web 容器应用过滤器到 Servlet 的顺序。

]]>
PostgreSQL使用uuid类型主键 2016-11-25T00:00:00+00:00 vosamo http://vosamo.github.io/2016/11/Postgresql-Uuid PostgreSQL内置uuid类型,性能不错,但是PostgreSQL默认没有安装uuid相关操作函数,需要手动导入。

操作步骤:

1. 导入uuid相关函数

你如果安装了postgresql数据库的话,可以在找到:/usr/pgsql-9.4/share/extension/uuid-ossp--1.0.sql

将其导入到你需要使用uuid的数据库:

psql -d dbname -U dbuser -f /usr/pgsql-9.4/share/extension/uuid-ossp--1.0.sql

2. 创建extension

导入成功之后会得到一个提示信息:create extension "uuid-ossp"

进入你的数据库:psql dbname

执行语句:create extension "uuid-ossp";

3. 创建uuid类型字段

创建数据表的时候可指定id类型为uuid:

id uuid NOT NULL DEFAULT uuid_generate_v4()

]]>
Servlet学习笔记之三(Servlet表单、请求和响应) 2016-11-03T00:00:00+00:00 vosamo http://vosamo.github.io/2016/11/Servlet-Notes-3 在交互过程中,经常需要将一些数据通过浏览器发送给web服务器,最后传递给后台程序处理。最常用的提交数据方法是GET和POST。

GET方法

GET方法是浏览器向Web服务器提交信息的默认方法。是通过请求字符串的形式传递数据,如下:

http://www.test.com/hello?key1=value1&key2=value2

GET方法提交数据有大小限制:请求字符串不得超过1024个字符。另外,GET方法不会对提交的数据加密,相对来说不够安全,所以GET方法更多是用来从服务器获取数据。

POST方法

POST方法是比较可靠的提交数据的方法,和GET方法不同,POST方法不是把数据作为请求字符串放在URL中提交,而是把这些数据作为一个单独的消息放在消息体中提交。

HTTP协议把请求分为三部分:状态行、请求头、消息主体。类似于下面这样:

<method>
<request-url>
<version>
<headers>
<entity-body>
</entity-body>
</headers>
</version>
</request-url>
</method>

协议规定POST提交的数据必须放在消息主体(entity-body)中,但协议没有规定数据必须使用什么编码方式。数据提交之后,服务端能够成功解析才行,服务端通常根据请求头中的Content-Type字段来获知消息主体中的数据是何种编码方式,再对消息主体进行解析。

常见的消息主体编码方式有四种:

application/x-www-form-urlencoded

这应该是最常见的 POST 提交数据的方式了。浏览器的原生 form 表单,如果不设置 enctype 属性,那么最终就会以 application/x-www-form-urlencoded 方式提交数据。请求类似于下面这样:

  POST http://www.example.com HTTP/1.1
  Content-Type: application/x-www-form-urlencoded;charset=utf-8
  title=test&content=hello

提交的数据按照 key1=val1&key2=val2 的方式进行编码。

multipart/form-data

我们使用表单上传文件时,必须让 form 的 enctyped 等于这个值。

application/json

JSON 格式支持比键值对复杂得多的结构化数据,形式上更加灵活。而且,后台也易于解析。提交JSON数据形式一般为:

POST http://www.example.com HTTP/1.1

Content-Type: application/json;charset=utf-8

{"title":"test","sub":[1,2,3]}

这种方案,可以方便的提交复杂的结构化数据,特别适合 RESTful 的接口。

text/xml

XML-RPC协议就是一种使用 HTTP 作为传输协议,XML 作为编码方式的远程调用规范。

使用Servlet获取表单数据

  • getParameter():您可以调用 request.getParameter() 方法来获取表单参数的值
  • getParameterValues():如果参数出现一次以上,则调用该方法,并返回多个值,例如复选框
  • getParameterNames():如果您想要得到当前请求中的所有参数的完整列表,则调用该方法
]]>
Servlet学习笔记之二(Servlet实例) 2016-11-03T00:00:00+00:00 vosamo http://vosamo.github.io/2016/11/Servlet-Notes-2 Servlet是接受http请求进行处理并作出响应的实现了 javax.servlet.Servlet 接口的Java类。下面我们在Eclipse中创建一个工程,实现一个Servlet。

创建工程

在Eclipse中,依次选择File > New > Other > Web > Dynamic Web Project创建一个Web工程,工程名为servletTest。然后选择File > New > Other > Web > Servlet,创建一个Servlet类。

代码如下:

package com.vosamo.serv;

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;

/**
 * Servlet implementation class ServTest
 */
public class ServTest extends HttpServlet {
	private static final long serialVersionUID = 1L;
	private String message;

    /**
     * @see HttpServlet#HttpServlet()
     */
    public ServTest() {
        super();
        // TODO Auto-generated constructor stub
    }
	/* (non-Javadoc)
     * @see javax.servlet.GenericServlet#init()
     */
    @Override
    public void init() throws ServletException {
        // TODO Auto-generated method stub
        message = "Hello World! Hello Inspur!";
    }
    /**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// 设置响应内容类型
	    response.setContentType("text/html");

	      // 实际的逻辑是在这里
	      PrintWriter out = response.getWriter();
	      out.println("<h1>" + message + "</h1>");	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}

在WEB-INF下,web.xml文件中可以看到Servlet类的配置:

<servlet>
   <description></description>
   <display-name>ServTest</display-name>
   <servlet-name>ServTest</servlet-name>
   <servlet-class>com.vosamo.serv.ServTest</servlet-class>
 </servlet>
 <servlet-mapping>
   <servlet-name>ServTest</servlet-name>
   <url-pattern>/ServTest</url-pattern>
 </servlet-mapping>

访问Servlet

启动Tomcat,在浏览器中输入http://localhost:8080/servletTest/ServTest可以看到message内容。

]]>
Servlet学习笔记之一(Servlet简介) 2016-11-01T00:00:00+00:00 vosamo http://vosamo.github.io/2016/11/Servlet-Notes-1 Servlet是什么?

Java Servlet是运行在Web服务器或应用服务器上的程序,它是作为来自Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层。

Servlet架构

下图展示了Servlet在Web应用程序中的位置:

servlet架构

Servlet的任务

  • 处理http请求,读取客户端发送的显式数据,比如表单数据
  • 读取客户端发送的隐式数据,比如cookies、媒体类型和浏览器能理解的压缩格式等
  • 处理数据并生成结果。这个过程可能需要访问数据库,执行 RMI 或 CORBA 调用,调用 Web 服务,或者直接计算得出对应的响应
  • 发送显式的数据到客户端。该文档的格式可以是多种多样的,包括文本文件(HTML 或 XML)、二进制文件(GIF 图像)、Excel 等
  • 发送隐式的 HTTP 响应到客户端。这包括告诉浏览器或其他客户端被返回的文档类型,设置 cookies 和缓存参数,以及其他类似的任务

在Eclipse中进行Servlet开发的话需要将servlet-api.jar包添加到build path中。

Servlet的生命周期

Servlet的生命周期是从创建到销毁的整个过程。以下是Servlet遵循的过程:

  1. Servlet通过调用init()方法进行初始化
  2. Servlet通过调用service()方法来处理客户端的请求
  3. Servlet通过调用destroy()方法来终止结束
  4. 最后Servlet由JVM的垃圾回收器回收

init()方法

init()方法仅在Servlet第一次创建的时候被调用一次,在Servlet的整个生命周期中仅调用这一次。它主要是完成一些初始化的工作,加载一些简单的数据。

init()方法的定义如下:

public void init() throws ServletException {
  // 初始化代码...
}

service()方法

service()方法是执行实际任务的方法,也就是响应http请求的方法。Servlet对象是单例,但访问是多线程。

每次服务器接收到一个Servlet请求时,服务器会产生一个新的线程并调用服务。service() 方法检查 HTTP 请求类型(GET、POST、PUT、DELETE 等),并在适当的时候调用 doGet、doPost、doPut,doDelete 等方法。

public void service(ServletRequest request,
                    ServletResponse response)
      throws ServletException, IOException{
}

service() 方法由容器调用,service 方法在适当的时候调用 doGet、doPost、doPut、doDelete 等方法。doGet和doPost是最常用的两个方法。

doGet()方法

客户端发起的GET请求交由该方法处理。

public void doGet(HttpServletRequest request,
                  HttpServletResponse response)
    throws ServletException, IOException {
    // Servlet 代码
}

doGet()方法

客户端发起的POST请求交由该方法处理。

public void doPost(HttpServletRequest request,
                   HttpServletResponse response)
    throws ServletException, IOException {
    // Servlet 代码
}

destroy()方法

destroy()方法和init()方法一样也是只调用一次,在Servlet生命周期结束时被调用。destroy() 方法可以让您的 Servlet 关闭数据库连接、停止后台线程、把 Cookie 列表或点击计数器写入到磁盘,并执行其他类似的清理活动。

在调用 destroy() 方法之后,servlet 对象被标记为垃圾回收。

public void destroy() {
  // 终止化代码...
}

架构图

下图展示了一个典型的Servlet生命周期:

Servlet生命周期

  • 第一个到达服务器的HTTP请求被委派到Servlet容器
  • Servlet容器在调用service()方法之前加载 Servlet
  • 然后Servlet容器处理由多个线程产生的多个请求,每个线程执行一个单一的 Servlet 实例的service()方法
]]>
python批量重命名文件 2016-10-15T00:00:00+00:00 vosamo http://vosamo.github.io/2016/10/python-batch-rename os.walk

在递归遍历某文件夹及其子文件夹时,使用os.walk特别方便。

os.walk的输出结果是这样的,是一个生成器对象:

(  /dir,               [dir1,dir2......],                  [ file1,file2,................ ]  ),

(  /dir/dir1 ,       [] ,                                    [file10,file12......]       ) ,  

(  /dir/dir2 ,       []                                      [file20,...........]         ) ,

生成器每次返回的是一个三元元组(root, dirs, files),其中root表示路径,dirs表示路径下的文件夹,files表示路径下的文件。具体的执行过程如下:

1,先从根目录进行遍历,读取跟目录的文件夹和文件。

2,以根目录第一个子目录为新的根目录,读取其文件夹和文件。

3,再以2中的第一个子文件夹为根目录,读取文件夹和文件。(这个应该是属于树结构里面的自上而下深度遍历算法)

4,读取1步骤里面其他子目录的文件夹和文件。

os.rename

上面我们通过os.walk可以获得某个文件夹下及其子文件夹下的所有文件夹和文件,这样我们就可以调用os.rename(old, new)来给文件重命名了。好了,现在说一下我们的具体需求:我想把为知笔记的文件导入到有道云笔记上,但是在为知笔记上写的markdown笔记文件导出为文本文件时,发现后缀名变成了.md.txt,也就是多了后缀名,这样直接导入由道云笔记是不行的,一个个修改后缀名又太麻烦,下面我们使用os.walkos.rename这两个函数来实现批量文件的后缀名修改。将下面这段代码保存为rename.py,然后放入你想要批量修改文件后缀名的文件夹下,假设里面存放的文件都是以.md.txt.txt为后缀名的,然后运行python rename.py就可以了。

#!/usr/bin/env python
# coding=utf-8
import os

for root, dirs, files in os.walk(os.getcwd()):
    for file in files:
        file_path = os.path.join(root, file)
        print file_path
        if file_path.endswith('.md.txt'):
            new_file_name = file_path[:-4]
            print new_file_name
            os.rename(file_path, new_file_name)
        elif file_path.endswith('.txt'):
            new_file_name = file_path[:-3] + 'md'
            os.rename(file_path, new_file_name)
]]>