JavaWeb学习笔记(一)—— Servlet

Servlet

用户在浏览器中输入一个网址并回车,浏览器会向服务器发送一个HTTP请求,服务器端接收并且处理改请求,然后向浏览器发送响应,浏览器接收响应,在将服务器端响应的内容显示出来,这种请求-响应模式就是典型的Web应用程序访问过程。在JavaWeb应用程序中,处理请求和响应的过程就是由Servlet程序来完成的。

1. Servlet 概述

JavaWeb应用程序中所有的请求-响应都是由Servlet来完成的。Servlet没有main方法,当用户访问服务器时,服务器通过调用Servlet的某些方法来完成整个的处理过程。

1.1 Servlet 工作流程

浏览器提交的请求是遵循HTTP协议的,提交的请求通过服务器(Tomcat)接收解析,并且封装成为HttpServletRequest类型的reqeust对象,所有的HTTP头数据都可以通过request的相应方法查询到。

服务器(Tomcat)同时把输出流封装为HttpServletResponse类型的response对象,通过设置response属性,就可以控制输出的内容。服务器(Tomcat)把request和response作为参数,调用Servlet的相应方法,如doGet或者doPost方法。

1.2 Servlet 接口

Servlet 实现了javax.servlet.Servlet接口的类,Servlet接口规定了特定的方法来处理特定的请求,我们只需要实现Servlet的相关方法,用户访问Web应用程序的时候,服务器(Tomcat)会自动调用这些方法来完成业务处理。Servlet业务处理主要方法有一下两种:

  1. Get方法:表示查询信息,URL中可以附带少量的参数信息,但是URL的总长度不能超过255个字符,并且参数会显示在浏览器的地址栏中。
  2. Post方法:表示提交信息,一般用于调教大数据信息或者文件,提交的内容不受长度限制,并且不会显示在浏览器地址栏。

1.3 实现 Servlet

package com.servlet.demo;

import java.io.IOException;

import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class ServletDemo implements Servlet {

	private ServletConfig config;

	public void destroy() {
		System.out.println("执行destory()方法...");
	}

	public ServletConfig getServletConfig() {
		return this.config;
	}

	public String getServletInfo() {
		return this.config.getServletName();
	}

	public void init(ServletConfig config) throws ServletException {
		System.out.println("执行init()方法...");
		this.config = config;
	}

	public void service(ServletRequest request, ServletResponse response) 
			throws ServletException, IOException {
		System.out.println("执行Service()方法...");
	}
}

1.4 配置 Servlet

在JavaWeb应用程序中,Web容器还必须知道浏览器怎么访问这个Servlet。所以我们要配置Servlet的类文件与访问方式。这个配置在Web应用程序的描述文件web.xml文件中。

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://xmlns.jcp.org/xml/ns/javaee"
	xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
	id="WebApp_ID" version="3.1">
	<display-name>servlet</display-name>
	<welcome-file-list>
		<welcome-file>index.html</welcome-file>
	</welcome-file-list>
    
    <!-- 配置Servlet -->
	<servlet>
		<servlet-name>ServletDemo</servlet-name>
		<servlet-class>com.servlet.demo.ServletDemo</servlet-class>
         <!-- 将servlet随Tomcat启动时自动实例化 -->
		<load-on-startup>0</load-on-startup>
	</servlet>
    <!-- 映射Servlet -->
	<servlet-mapping>
		<servlet-name>ServletDemo</servlet-name>
		<url-pattern>/demo</url-pattern>
	</servlet-mapping>
</web-app>

1.4.1 配置 servlet 标签

<servlet></servlet> 分别为Servlet配置的开始与结束标签。中间部分为Servlet的配置信息,其中 <servlet-name><servlet-class> 属性是必须配置的。

  1. <servlet-name>:配置servlet名称,可以为任意字符串,但是保证该名称在web.xml文件中唯一,该名称供<servlet-mapping><filter> 等使用;
  2. <servlet-class>:Servlet类所在包及类名;
1. 在容器启动时实例化 Servlet

<load-on-startup>:配置Servlet的加载模式,可选0和1,如果配置1,服务器会在启动时自动加载该Servlet;

2. 设置Servlet初始化参数

<init-param>:可以在servlet中配置初始化参数,包括一个参数名称和参数值,servlet可以通过其ServletConfig对象的getInitParam(String paramName)方法来获取初始化参数值;

  • <param-name>:配置初始化参数名称;
  • <param-value>:配置初始化参数值;

1.4.2 配置 servlet-mapping标签

  1. <servlet-name>:配置指明采用该访问方式Servlet的名称,与<servlet>标签中的<servlet-name>须一致;
  2. <url-pattern>:配置该servlet的访问方式,该标签前面加上Web应用程序的路径,再加上服务器域名端口号信息就是访问该servlet的网址。

1.5 Servlet生命周期和生命周期方法

Servlet 生命周期可被定义为从创建直到毁灭的整个过程。以下是 Servlet 遵循的过程:

  • Servlet 通过调用 init () 方法进行初始化;
  • Servlet 调用 service() 方法来处理客户端的请求;
  • Servlet 通过调用 destroy() 方法终止(结束);

以上的init()service()destory() 三个方法属于Servlet的生命周期方法。

  1. init():被设计成只调用一次。它在第一次创建 Servlet 时被调用,在后续每次用户请求时不再调用。
  2. service(): 执行实际任务的主要方法。Servlet 容器(即 Web 服务器)调用 service() 方法来处理来自客户端的请求,并把格式化的响应写回给客户端。每次服务器接收到一个 Servlet 请求时,服务器会产生一个新的线程并调用服务。
  3. destory():只会被调用一次,在 Servlet 生命周期结束时被调用。

2. 通过继承 HttpServlet 编写 Servlet

直接实现Servlet接口来编写Servlet不方便,需要实现的方法太多。javax.servlet.http.HttpServlet类实现了Servlet接口所有方法,通过继承HttpServlet编写Servlet,一般只需要覆盖doGet()和doPost()方法即可。

package com.servlet;

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

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

public class FirstServlet extends HttpServlet {

	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		this.log("执行 doGet 方法...");
		this.execute(request, response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		this.log("执行 doPost 方法...");
		this.execute(request, response);
	}
	
	public long getLastModified(HttpServletRequest request) {
		this.log("执行 getLastModified 方法...");
		return -1;
	}

	private void execute(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		response.setCharacterEncoding("utf-8");
		request.setCharacterEncoding("utf-8");
		//获取访问该 Servlet 的 URI
		String requestURI = request.getRequestURI();
		// 获取访问 Servlet 的方式
		String method = request.getMethod();
		
		String param = request.getParameter("param");
		
		response.setContentType("text/html");
		
		PrintWriter out = response.getWriter();
		
		out.println("<!DOCTYPE html>");
		out.println("<html>");
		out.println("<head>");
		out.println("<title>First Servlet</title>");
		out.println("</head>");
		out.println("<body>");
		
		out.println("以<span color='red'> " + method +"</span> 方式访问该页面,取得的 param 参数为:" + param+"。");
		out.println("<br/>");
		
		out.println("<form action='"+ requestURI +"' method='get'>");
		out.println("<input type='text' name='param' value='param string'/>");
		out.println("<input type='submit' value='以 GET 方式查询页面'/>");
		out.println("</form>");
		
		out.println("<form action='"+ requestURI +"' method='post'>");
		out.println("<input type='text' name='param' value='param string'/>");
		out.println("<input type='submit' value='以 Post 方式提交到页面'/>");
		out.println("</form>");
		
		out.println("<script type='text/javascript'>");
		out.println("document.wirte('本页最后更新时间为 :' + document.lastModified);");
		out.println("</script>");
		
		out.println("</body>");
		out.println("</html>");
		
		out.flush();
		out.close();
	}

}

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
id="WebApp_ID" version="3.1">
<display-name>servlet</display-name>
<welcome-file-list>
	<welcome-file>index.html</welcome-file>
	<welcome-file>index.htm</welcome-file>
	<welcome-file>index.jsp</welcome-file>
	<welcome-file>default.html</welcome-file>
	<welcome-file>default.htm</welcome-file>
	<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<!-- 配置FirstServlet -->
<servlet>
	<servlet-name>FirstServlet</servlet-name>
	<servlet-class>com.servlet.FirstServlet</servlet-class>
</servlet>
<!-- 映射FirstServlet -->
<servlet-mapping>
	<servlet-name>FirstServlet</servlet-name>
	<url-pattern>/first</url-pattern>
</servlet-mapping>
</web-app>

3. 请求和响应

客户端浏览器发送给一个请求,服务器接收并处理请求,最后向客户端浏览器发送响应,结束一次Web访问过程。

3.1 获取 request 的变量

客户端浏览器发出的请求被封装成为HttpServletRequest类型对象,所有的信息包括请求地址、请求参数、提交的数据、上传的文件,客户端的IP地址,甚至是客户操作系统都包含在HttpServletRequest类型的对象中。

package com.servlet;

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

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

public class RequestServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		
		request.setCharacterEncoding("utf-8");
		response.setCharacterEncoding("utf-8");
		response.setContentType("text/html");
		
		PrintWriter out = response.getWriter();
		
		// 获取 user-agent 请求头		
		String userAgent = request.getHeader("user-agent");
		
		String os = getOS(userAgent);
		String navigator = getNavigator(userAgent);
		
		out.println("你使用的操作系统是: "+ os +" 系统");
		out.println("<br/>");
		out.println("你使用的浏览器是: "+ navigator +" 浏览器");
		
		out.flush();
		out.close();
		
		
	}
	private static String getOS(String userAgent) {
		if (userAgent.indexOf("Ubuntu") > 0) {
			return "Ubuntu";
		}
		return "未知";
	}
	
	private static String getNavigator(String userAgent) {
		if (userAgent.indexOf("Firefox") > 0) {
			return "Mozllia Firefox";
		}
		return "未知";
	}
}

RequestServlet配置:

<servlet>
    <servlet-name>RequestServlet</servlet-name>
    <servlet-class>com.servlet.request.RequestServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>RequestServlet</servlet-name>
    <url-pattern>/request</url-pattern>
</servlet-mapping>

3.2 使用 response 生成图片验证码

package com.servlet.response;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;

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

import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;

public class IdentityServlet extends HttpServlet {

	public static final char[] CHARS = { '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
			'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' };

	// 获取随机数
	public static Random random = new Random();

	// 随机获取6位验证码
	public StringBuffer getIdentityCode() {

		// 创建缓存字符串
		StringBuffer buffer = new StringBuffer();

		for (int i = 0; i < 6; i++) {
			buffer.append(CHARS[random.nextInt(CHARS.length)]);
		}

		return buffer;
	}

	public static Color getRandomColor() {
		return new Color(random.nextInt(255), random.nextInt(255), random.nextInt(255));
	}

	public static Color getReverseColor(Color c) {
		return new Color(255 - c.getRed(), 255 - c.getGreen(), 255 - c.getBlue());
	}

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

		response.setContentType("image/jpeg");

		String identityCode = getIdentityCode().toString();
		request.getSession(true).setAttribute("identityCode", identityCode);
		// 设置验证码图片的高度和宽度
		int width = 100;
		int height = 30;

		Color backColor = getRandomColor();
		Color frontColor = getReverseColor(backColor);

		BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

		Graphics2D g = bi.createGraphics();
		g.setFont(new Font(Font.SANS_SERIF, Font.BOLD, 16));

		g.setColor(backColor);
		g.fillRect(0, 0, width, height);

		g.setColor(frontColor);
		g.drawString(identityCode, 18, 20);

		for (int i = 0; i < random.nextInt(100); i++) {
			g.drawRect(random.nextInt(width), random.nextInt(height), 1, 1);
		}

		ServletOutputStream out = response.getOutputStream();
		JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);

		encoder.encode(bi);
		out.flush();

	}

}

IdentityServlet配置信息:

<servlet>
    <servlet-name>identity</servlet-name>
    <servlet-class>com.servlet.response.IdentityServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>identity</servlet-name>
    <url-pattern>/identity</url-pattern>
</servlet-mapping>

4. 读取 web.xml 参数

在JavaWeb开发中,源码上微小的变动就需要重新编译class文件,然后重新部署,会带来大量的工作。现在,可以将一些常亮信息存放于配置文件中。当程序需求发生变化,只需修改配置文件即可。web.xml提供了设置初始化参数的功能,可以将这些信息配置在web.xml文件中。

4.1 初始化参数(init-param)

web.xml配置servlet时, 标签可以包含多个 来配置多个初始化参数。servlet中提供了如下的方法来操作来获取初始化参数的名称和值:

  1. String getInitParameter(String parameterName) : 获取指定初始化参数的值;
  2. Enumeration<String> getInitParameterNames() : 获取所有初始化参数名称;

web.xml配置信息如下:

<!-- 配置InitParamServlet -->
<servlet>
	<servlet-name>InitParamServlet</servlet-name>
	<servlet-class>com.servlet.initParam.InitParamServlet</servlet-class>
	<!-- 配置初始化参数 -->
	<init-param>
		<param-name>admin</param-name>
		<param-value>martin0319</param-value>
	</init-param>
	<init-param>
		<param-name>adminPassword</param-name>
		<param-value>319517</param-value>
	</init-param>
</servlet>
<servlet-mapping>
	<servlet-name>InitParamServlet</servlet-name>
	<url-pattern>/param</url-pattern>
</servlet-mapping>

InitParamServlet

package com.servlet.initParam;

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

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

public class InitParamServlet extends HttpServlet {

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

		response.setCharacterEncoding("utf-8");
		request.setCharacterEncoding("utf-8");

		response.setContentType("text/html");

		PrintWriter out = response.getWriter();

		String requestURI = request.getRequestURI();

		out.println("<!DOCTYPE HTML>");
		out.println("<html>");
		out.println("<head>");
		out.println("<title>Test Init-Param</title>");
		out.println("</head>");
		out.println("<body>");
		out.println("<form action='" + requestURI + "' method='post'>");
		out.println("账号:<input type='text' name='loginName' />"
				+ "<br />"
				+ "密码:<input type='password' name='loginPassword' />"
				+ "<br />"
				+ "<input type='submit' value='Log In Now' />");
		out.println("</form>");
		out.println("</body>");
		out.println("</html>");

	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) 
        throws ServletException, IOException {
		
		response.setCharacterEncoding("utf-8");
		request.setCharacterEncoding("utf-8");

		response.setContentType("text/html");

		PrintWriter out = response.getWriter();
		
		//	获取由表达提交的数据		
		String username = request.getParameter("loginName");
		String password = request.getParameter("loginPassword");
		
		/*
		 * 获取web.xml中配置参数
		 * 	1、获取ServletConfig对象
		 * 	2、获取所有初始化参数名称
		 * 	3、通过初始化参数名称获取初始化参数值
		 */
		ServletConfig config = this.getServletConfig();
		
		String initName = config.getInitParameter("admin");
		String initPassword = config.getInitParameter("adminPassword");
		
		if (username.equalsIgnoreCase(initName) && password.equalsIgnoreCase(initPassword)) {
			out.println("欢迎登陆...");
		} else {
			out.println("用户名或密码错误...");
		}

	}

}

4.2 上下文参数(context-param)

由于 init-param 是配置在<servlet>标签中的,只能由这个servlet类调用,不能被其他的servlet调用,不是全局参数。如果需要配置全局参数,需要用到上下文参数(文档参数),上下文参数使用<context-param>标签配置。

上下文参数可以使用ServletConfig对象来获取。Servlet中通过getServletConfig().getServletContext()方法来获取一个ServletContext对象。

  1. String getInitParameter(String parameterName) : 获取指定上下文参数的值;
  2. Enumeration<String> getInitParameterNames() : 获取所有上下文参数名称;

ContextParamServlet配置信息:

<context-param>
	<param-name>upload folder</param-name>
	<param-value>attachment</param-value>
</context-param>
<context-param>
	<param-name>allowed file type</param-name>
	<param-value>.jpg, .gif, .bmp</param-value>
</context-param>
<!-- 配置 ContextParamServlet -->
<servlet>
	<servlet-name>ContextParamServlet</servlet-name>
	<servlet-class>com.contextParam.ContextParamServlet</servlet-class>
</servlet>
<servlet-mapping>
	<servlet-name>ContextParamServlet</servlet-name>
	<url-pattern>/context</url-pattern>
</servlet-mapping>

ContextParamServlet类:

package com.contextParam;

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

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

public class ContextParamServlet extends HttpServlet {
	
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		
		response.setCharacterEncoding("utf-8");
		request.setCharacterEncoding("utf-8");
		
		response.setContentType("text/html");
		
		PrintWriter out = response.getWriter();
		//	获取ServletContext对象
		ServletContext context = this.getServletConfig().getServletContext();
		//	获取上下文参数
		String uploadFolder = context.getInitParameter("upload folder");
		String allowFileType = context.getInitParameter("allowed file type");
		//	获取实际磁盘路径
		String realPath = context.getRealPath(uploadFolder);
		
		out.println("<!DOCTYPE html>");
		out.println("<html>");
		out.println("<head>");
		out.println("<title>读取上下文参数</title>");
		out.println("</head>");
		out.println("<body>");
		
		out.println("<table>");
		out.println("<tr>");
		out.println("<td>上传文件夹:</td>");
		out.println("<td>" + uploadFolder + "</td>");
		out.println("</tr>");
		
		out.println("<tr>");
		out.println("<td>实际磁盘路径:</td>");
		out.println("<td>" + realPath + "</td>");
		out.println("</tr>");
		
		out.println("<tr>");
		out.println("<td>允许上传类型:</td>");
		out.println("<td>" + allowFileType + "</td>");
		out.println("</tr>");
		out.println("</table>");
		
		out.println("</body>");
		out.println("</html>");
		
		out.flush();
		out.close();
		
	}

}
posted @ 2018-04-25 13:50  Java路上小菜鸟  阅读(319)  评论(0编辑  收藏  举报