1.创建Servlet类

Servlet在Java EE API规范中的定义:

Servlet是一个运行在Web服务器中的Java小程序。Servlet将会接收和响应来自Web客户端的请求,使用HTTP(超文本传输协议)进行通信。

Servlet是所有Web应用程序的核心类。

运行应用程序的Web容器将会有一个或多个内建的Servlet。这些Servlet将用于处理JavaServer Pages、显示目录列表和访问静态资源。

所有的Servlet都实现了javax.serlvet.Servlet接口,但通常不是直接实现的。Servlet只是一个简单接口,它包含了初始化并销毁Servlet和处理请求的方法。

在大多数情况下,Servlet都继承自javax.servlet.GenericServlet。GenericServlet仍然是一个不依赖于具体协议的Servlet,它只包含了一个抽象的service方法。

作为响应HTTP请求的java.servlet.http.HttpServlet,它继承了GenericServlet,并实现了只接受HTTP请求的service方法。然后,它提供了响应每种HTTP方法类型的方法的空实现。

HttpServlet的方法接受的是javax.servlet.http.HttpServletRequestjavax.servlet.http.HttpServletResponse参数,而不是javax.servlet.ServletRequestjavax.servlet.ServletResponse,这样它就可以轻松访问Servlet服务所处理的请求中的HTTP特定的特性。

package com.wrox;

import javax.servlet.http.HttpServlet;

public class HelloServlet extends HttpServlet
{ }
//为了可以编译该代码,需要将Java EE Servlet API库添加到编译类路径上。

任何未重写的HTTP Servlet方法都将返回一个HTTP状态405作为响应。如果一个Servlet不处理任何请求,当然它就是无用的。

//重写doGet()方法
package com.wrox; import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException; @SuppressWarnings("serial")
public class HelloServlet extends HttpServlet
{
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
//下面没有调用PringtWriter的close方法。一般来说,在Java中只需要关闭自己创建
//的资源即可。Web容器创建了该资源,所以它也会负责关闭该资源。
response.getWriter().println("Hello, World!");
}
}

注意,不需要担心任何原生HTTP请求或响应的细节。Web容器将会处理请求的解释,并从套接字(socket)中读取请求头和参数。在Servlet的方法返回之后,Web容器还将格式化响应头和主体,并写回套接字中。

使用初始化方法和销毁方法

    @Override
public void init() throws ServletException
{
System.out.println("Servlet " + this.getServletName() + " has started.");
} @Override
public void destroy()
{
System.out.println("Servlet " + this.getServletName() + " has stopped.");
}

GenericServlet实现了javax.servlet.Servlet接口中的init(ServletConfig config)方法,所以不需要在自己的init方法实现中调用super.init(servletConfig)

可以使用init方法读取属性文件,或者使用JDBC连接数据库。init方法将在Servlet启动时调用。

如果将Servlet配置为在Web应用程序部署和启动时自动启动,那么它的init方法也将会被调用。否则,init方法将在第一次请求访问它接收的Servlet时调用。

同样地,destroy在Servlet不再接受请求之后立即调用。这通常发生在Web应用程序被停止或卸载,或者Web容器关闭时。总是应该使用destroy方法清理Servlet持有的资源。

2.配置可部署的Servlet

部署描述符将指示Web容器如何部署应用程序。尤其是它定义了应用程序中所有的监听器、Servlet和过滤器,以及应用程序所应使用的设置。

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1"> <display-name>Hello World Application</display-name> <servlet>
<servlet-name>helloServlet</servlet-name>
<servlet-class>com.wrox.HelloServlet</servlet-class>
</servlet> <servlet-mapping>
<servlet-name>helloServlet</servlet-name>
<url-pattern>/greeting</url-pattern>
</servlet-mapping> </web-app>

上面的配置中<servlet><servlet-mapping>标签内的<servlet-name>标签应该一致。Web容器通过这种方式关联这两个配置。

可以将多个URL映射到相同的Servlet:

    <servlet-mapping>
<servlet-name>helloServlet</servlet-name>
<url-pattern>/greeting</url-pattern>
<url-pattern>/salutation</url-pattern>
<url-pattern>/wazzup</url-pattern>
</servlet-mapping>

下面的<load-on-startup>1</load-on-startup>指示Web容器在应用程序启动之后立即启动Servlet。如果多个Servlet配置都包含了该标签,它们将按照标签内的值的大小顺序启动。如果两个或多个Servlet的<load-on-startup>配置相同,那么将按照它们在描述符文件中的出现顺序启动。

    <servlet>
<servlet-name>helloServlet</servlet-name>
<servlet-class>com.wrox.HelloServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>

3.了解doGet、doPost和其他方法

3.1 在service方法执行的过程中

service方法的实现是非常复杂的,而且随着Web容器的不同,service方法的实现也会随之变化。

扩展HttpServlet的优点在于我们不需要担心其中的任何细节问题。

通过使用HttpServlet在各种不同方法中定义的HttpServletRequestHttpServletResponse参数,我们可以读取由客户端发送的参数、接受通过表单上传的文件、读取包含在请求正文中的原始数据、读取请求头和操作响应头,并将响应正文返回到客户端。

3.2 使用HttpServletRequest

HttpServletRequest接口是对ServletRequest的扩展。

HttpServletRequest最重要的功能是从客户端发送的请求中获取参数,请求参数有两种不同的形式:

  • 查询参数(URI参数)
  • application/x-www-form-urlencodedmultipart/form-data编码的请求正文
public interface ServletRequest {
//...
//getParameter方法将返回参数的单个值,如果参数有多个值,就返回第一个值。
public String getParameter(String name); //getParameterNames方法返回所有可用参数的名字的枚举。
public Enumeration<String> getParameterNames(); //getParameterValues方法返回参数的值的数组,如果参数只有一个值,就返回只有一个元素的数组。
public String[] getParameterValues(String name); //getParameterMap方法返回一个包含了所有参数名值对的 java.util.Map<String, String[]>
public Map<String, String[]> getParameterMap();
//...
}

有几个方法可用于帮助决定HTTP请求内容的类型、长度和编码。

方法getContentType将返回请求的MIME(多用途互联网邮件扩展)内容类型,例如 application/x-www-form-urlencodedapplication/jsontext/plainapplication/zip等。

MIME内容类型描述了数据的类型。

方法getContentLength返回请求正文的长度,以字节为单位。

方法getCharacterEncoding将返回请求内容的字符编码。

public interface HttpServletRequest extends ServletRequest {
//...
//返回客户端用于创建请求的完整URL,包含协议(http或https)、服务器名称、端口号和服务器路径,但不包括查询字符串
public StringBuffer getRequestURL(); //它只返回URL中的服务器路径部分
public String getRequestURI(); //它只返回用于匹配Servlet映射的URL部分
public String getServletPath(); //返回指定名字的头数据
public String getHeader(String name); //返回请求头中所有头数据的名字的枚举
public Enumeration<String> getHeaderNames(); //如果有某个特定的头的值一直是数字,那么可以调用该方法返回一个数字。
public int getIntHeader(String name); //对于可以表示有效时间戳的头数据,该方法将返回一个Unix时间戳。
public long getDateHeader(String name);
//...
}

3.3 使用HttpServletResponse

HttpServletResponse接口继承了ServletResponse,HttpServletResponse可以设置响应头、编写响应正文、重定向请求、设置HTTP状态码以及将Cookies返回到客户端等任务。

方法getOutputStream将返回一个javax.servlet.ServletOutputStream,而方法getWriter将返回一个java.io.PrintWriter,通过它们都可以向响应中输出数据。

在向响应正文中输出数据时,可能需要设置内容类型或编码格式。可以通过setContentTypesetCharacterEncoding方法进行设置。如果计划在使用getWriter时调用setContentTypesetCharacterEncoding,那么必须在getWriter之前调用setContentTypesetCharacterEncoding,因为这样的getWriter方法返回的writer才能获得正确的字符编码设置。在getWriter调用之后调用的setContentTypesetCharacterEncoding将被忽略。

如果在调用getWriter之前未调用setContentTypesetCharacterEncoding,返回的writer将使用容器的默认编码。

方法sendRedirect将客户端重定向至另一个URL。

4.使用参数和接受表单提交

@WebServlet(
name = "helloServlet",
urlPatterns = {"/greeting", "/salutation", "/wazzup"},
loadOnStartup = 1
)
public class HelloServlet extends HttpServlet
{
private static final String DEFAULT_USER = "Guest"; @Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
//获取名为"user"的参数
String user = request.getParameter("user");
if(user == null)
user = HelloServlet.DEFAULT_USER; //将响应的内容类型设置为text/html,将字符编码设置为UTF-8
response.setContentType("text/html");
response.setCharacterEncoding("UTF-8"); //从响应中获得一个PrintWriter,并输出一个兼容于HTML5的文档
PrintWriter writer = response.getWriter();
writer.append("<!DOCTYPE html>\r\n")
.append("<html>\r\n")
.append(" <head>\r\n")
.append(" <title>Hello User Application</title>\r\n")
.append(" </head>\r\n")
.append(" <body>\r\n")
.append(" Hello, ").append(user).append("!<br/><br/>\r\n")
.append(" <form action=\"greeting\" method=\"POST\">\r\n")
.append(" Enter your name:<br/>\r\n")
.append(" <input type=\"text\" name=\"user\"/><br/>\r\n")
.append(" <input type=\"submit\" value=\"Submit\"/>\r\n")
.append(" </form>\r\n")
.append(" </body>\r\n")
.append("</html>\r\n");
} @Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
//接收表单提交,将请求委托给doGet方法。
this.doGet(request, response);
} //...

接受多值参数的例子:

@WebServlet(
name = "multiValueParameterServlet",
urlPatterns = {"/checkboxes"}
)
public class MultiValueParameterServlet extends HttpServlet
{
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
response.setContentType("text/html");
response.setCharacterEncoding("UTF-8"); PrintWriter writer = response.getWriter();
writer.append("<!DOCTYPE html>\r\n")
.append("<html>\r\n")
.append(" <head>\r\n")
.append(" <title>Hello User Application</title>\r\n")
.append(" </head>\r\n")
.append(" <body>\r\n")
.append(" <form action=\"checkboxes\" method=\"POST\">\r\n")
.append("Select the fruits you like to eat:<br/>\r\n")
.append("<input type=\"checkbox\" name=\"fruit\" value=\"Banana\"/>")
.append(" Banana<br/>\r\n")
.append("<input type=\"checkbox\" name=\"fruit\" value=\"Apple\"/>")
.append(" Apple<br/>\r\n")
.append("<input type=\"checkbox\" name=\"fruit\" value=\"Orange\"/>")
.append(" Orange<br/>\r\n")
.append("<input type=\"checkbox\" name=\"fruit\" value=\"Guava\"/>")
.append(" Guava<br/>\r\n")
.append("<input type=\"checkbox\" name=\"fruit\" value=\"Kiwi\"/>")
.append(" Kiwi<br/>\r\n")
.append("<input type=\"submit\" value=\"Submit\"/>\r\n")
.append(" </form>")
.append(" </body>\r\n")
.append("</html>\r\n");
} @Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
String[] fruits = request.getParameterValues("fruit"); response.setContentType("text/html");
response.setCharacterEncoding("UTF-8"); PrintWriter writer = response.getWriter();
writer.append("<!DOCTYPE html>\r\n")
.append("<html>\r\n")
.append(" <head>\r\n")
.append(" <title>Hello User Application</title>\r\n")
.append(" </head>\r\n")
.append(" <body>\r\n")
.append(" <h2>Your Selections</h2>\r\n"); if(fruits == null)
writer.append(" You did not select any fruits.\r\n");
else
{
writer.append(" <ul>\r\n");
for(String fruit : fruits)
{
writer.append(" <li>").append(fruit).append("</li>\r\n");
}
writer.append(" </ul>\r\n");
} writer.append(" </body>\r\n")
.append("</html>\r\n");
}
}

5.使用初始化参数配置应用程序

5.1 使用上下文初始化参数

在部署描述符中添加上下文初始化参数:

    <context-param>
<param-name>settingOne</param-name>
<param-value>foo</param-value>
</context-param>
<context-param>
<param-name>settingTwo</param-name>
<param-value>bar</param-value>
</context-param>

在Servlet代码的任何地方都可以轻松获得和使用这些参数。

@WebServlet(
name = "contextParameterServlet",
urlPatterns = {"/contextParameters"}
)
public class ContextParameterServlet extends HttpServlet
{
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
ServletContext c = this.getServletContext();
PrintWriter writer = response.getWriter(); writer.append("settingOne: ").append(c.getInitParameter("settingOne"))
.append(", settingTwo: ").append(c.getInitParameter("settingTwo"));
}
}

应用程序中的所有Servlet都将共享这些初始化参数。在所有的Servlet中它们的值都是相同的。有时需要使某个设置只作用于某一个Servlet,那么就需要使用Servlet初始化参数。

5.2 使用Servlet初始化参数

public class ServletParameterServlet extends HttpServlet
{
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
//从ServletConfig对象中获取初始化参数
ServletConfig c = this.getServletConfig();
PrintWriter writer = response.getWriter(); writer.append("database: ").append(c.getInitParameter("database"))
.append(", server: ").append(c.getInitParameter("server"));
}
}

部署描述符中的配置:

    <servlet>
<servlet-name>servletParameterServlet</servlet-name>
<servlet-class>com.wrox.ServletParameterServlet</servlet-class>
<init-param>
<param-name>database</param-name>
<param-value>CustomerSupport</param-value>
</init-param>
<init-param>
<param-name>server</param-name>
<param-value>10.0.12.5</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>servletParameterServlet</servlet-name>
<url-pattern>/servletParameters</url-pattern>
</servlet-mapping>

考虑到多线程安全的问题:永远不要在静态或实例变量中存储请求或响应对象。任何属于请求的对象和资源都只应该被用作本地变量和方法参数。

参考:《Java Web高级编程》第3章

Java EE之Servlet的更多相关文章

  1. Java EE javax.servlet中的ServletContext接口

    ServletContext接口 public interface ServletContext (https://docs.oracle.com/javaee/7/api/javax/servlet ...

  2. Java EE之servlet实现用户登录

    1.在连接数据库的JAVA类中添加查询功能: 在这之前有一个连接数据库的方法: Connection conn=null; PreparedStatement stat=null;           ...

  3. Java EE之servlet处理表单提交的请求

    1.在源包下新建一个Servlet页,取名为LoginServlet: package weinidingServlet;                            //该Servlet所 ...

  4. java EE :Servlet 接口

    Servlet 生命周期  : 调用当前 Servlet 类构造函数进行实例化 Servlet 通过调用 init () 方法进行初始化 Servlet 调用 service() 方法来处理客户端的请 ...

  5. Java EE javax.servlet中的RequestDispatcher接口

    RequestDispatcher接口 public interface RequestDispatcher 一.介绍 定义一个对象,从客户端接收请求并将其发送到服务器上的任何资源(例如servlet ...

  6. Java EE javax.servlet中的Servlet接口

    Servlet接口 public interface Servlet 其实现类有:FaceServlet.GenericServlet.HttpServlet 一.介绍 Servlet接口定义了所有s ...

  7. Java EE javax.servlet.http中的HttpSession接口

    HttpSession接口 public interface HttpSession (https://docs.oracle.com/javaee/7/api/javax/servlet/http/ ...

  8. Java EE javax.servlet.http中的HttpRequest抽象类

    HttpRequest抽象类 public abstract class HttpServlet extends GenericServlet 实现的接口有:Serializable, Servlet ...

  9. Java EE javax.servlet中的ServletResponse接口

    ServletResponse接口 public interface ServletResponse 子接口:HttpServletResponse 实现类:HttpServletResponseWr ...

随机推荐

  1. MFC -- Excel操作简介(基于VS2010)

    一.添加与 Excel 操作相关的头文件 项目 -> 类向导,在右上方有一个下拉栏,选择其中的 类型库中的MFC类(T),即可看到下图所示界面,选择“文件”选项,然后在下方的位置选项中添加本地文 ...

  2. 机器人平台框架Yarp - Yet another robot platform

    简介 ROS有强大和易用的特性,用的人很多,目前已经推出2.0版本,有相关的官网和论坛.然而其缺点也比较明显. 只能基于Ubuntu系统,且一个ROS版本只能对应一个具体的Ubuntu版本    通信 ...

  3. python service 服务没有及时响应启动或控制请求

    1053错误 代码运行没有问题后,安装服务,然而start 的时候出现错误 1053:服务没有及时响应启动或控制请求(Error 1053: The service did not respond t ...

  4. vs2013 CodeLens

    那东西叫 CodeLens  只有VS2013 旗舰版 (update 2及以上) 才可以用,高级版 专业版都没有.如何打开CodeLens呢?在VS菜单栏 >> 工具 >> ...

  5. IIs8 svc

    IIS8中添加WCF支持几种方法小结[图文] 方法一 最近在做Silverlight,Windows Phone应用移植到Windows 8平台,在IIS8中测试一些传统WCF服务应用,发现IIS8不 ...

  6. 进阶系列(4)—— C#文件与流

    一. 驱动器 在Windows操作系统中,存储介质统称为驱动器,硬盘由于可以划分为多个区域,每一个区域称为一个驱动器..NET Framew   ork提供DriveInfo类和 DriveType枚 ...

  7. Leetcode题库——9.回文数

    @author: ZZQ @software: PyCharm @file: HuiWenShu.py @time: 2018/9/16 16:51 要求:判断一个整数是否是回文数.回文数是指正序(从 ...

  8. BNUOJ 52305 Around the World 树形dp

    题目链接: https://www.bnuoj.com/v3/problem_show.php?pid=52305 Around the World Time Limit: 20000msMemory ...

  9. EasyUi模糊匹配搜索框combobox

    现在项目当中很多已经应用了Jquery-easyUi这个界面框架了,所以,学习一点easyUI的常用工具就显得很重要了,现在介绍的就是我在项目中用到的easyUi的模糊匹配组合框combobox. c ...

  10. 0422数学口袋精灵bug发现

    团队成员的博客园地址: 蔡彩虹:http://home.cnblogs.com/u/caicaihong/ 曾治业:http://www.cnblogs.com/zzy999/ 蓝叶:http://w ...