JavaEE 7教程

如何开发一个Servlet应用

  前面我们在使用Gradle建立一个Java项目已经建立了一个Web项目,也可以导入到Eclipse等开发工具,下面我们基于这个空的项目建立第一个Servlet。

  servlet被定义为JSR340,以及完整的规范可以下载。 servlet是托管在一个servlet容器的Web组件,并生成动态 内容。 Web客户端使用请求/响应模式与servlet交互。该servlet容器是负责Servlet的生命周期,接收请求和发送响应,并且执行所需的那部分的任何其它编码/解码。

  Servlet的性能在 TechEmpower综合Go,Python和Java语言,Ruby,PHP Clojure,Groovy,JavaScript,Erlang,Haskell,scala,Lua,和C.等Web框架的多次测试中性能名列前茅。

WebServlet

  一个Servlet是一个用元注解@WebServlet标注的继承javax.servlet.http.HttpServlet的类:

@WebServlet("/account")
public class AccountServlet extends javax.servlet.http.HttpServlet {
//. . .
}

类名默认是servlet的名称,可以使用注释的name属性覆盖。Servlet可以以多个URL部署:

@WebServlet(urlPatterns={"/account", "/accountServlet"})
public class AccountServlet extends javax.servlet.http.HttpServlet {
//. . .
}

@WebInitParam能够规定初始化参数:

@WebServlet(urlPatterns="/account",
     initParams={
     @WebInitParam(name="type", value="checking") } )
public class AccountServlet extends javax.servlet.http.HttpServlet {
//. . .
}

对于HttpServlet接口有一个的doXXX方法来处理每个HTTP的GET,POST, PUT,DELETE,HEAD,OPTIONS,和TRACE请求。通常情况下,开发者关注 与重写的doGet和doPost方法。下面的代码显示了一个servlet 处理GET请求:

@WebServlet("/account")
public class AccountServlet
extends javax.servlet.http.HttpServlet {
  @Override
  protected void doGet(HttpServletRequest request, HttpServletResponse response) {
     //. . .
  }
}

HttpServletRequest和HttpServletResponse的捕获来自Web客户端请求/响应
请求参数包含:HTTP头,如主机, 端口和上下文,更多的信息可从HttpServletRequest中查询。

下面是显示一个简单的 响应客户端:

protected void doGet(HttpServletRequest request,
HttpServletResponse response) {
try (PrintWriter out = response.getWriter()) {
out.println("<html><head>");
out.println("<title>MyServlet</title>");
out.println("</head><body>");
out.println("<h1>My First Servlet</h1>");
//. . .
out.println("</body></html>");
} finally {
//. . .
}
}

假设URL传入一个参数:account?tx=jdon

protected void doGet(HttpServletRequest request,
HttpServletResponse response) {
  String txValue = request.getParameter("tx");获得tx值
//. . .
}

@WebInitParam是用来规定Servlet启动的初始参数。

String type = null;
@Override
public void init(ServletConfig config) throws ServletException {
type = config.getInitParameter("type");
//. . .
}

你可以通过重写操javax.servlet.Servlet接口的方法对servlet的生命周期调用方法的默认行为
初始化,服务和销毁。 通常情况下,可以是在init数据库连接的初始化和在destory中释放关闭。

您也可以使用在Web应用程序的部署描述符web.xml的servlet和servlet-mapping元素定义了一个servlet:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1"
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">
<servlet>
  <servlet-name>AccountServlet</servlet-name>
  <servlet-class>org.sample.AccountServlet</servlet-class>
</servlet>
<servlet-mapping>
  <servlet-name>AccountServlet</servlet-name>
  <url-pattern>/account</url-pattern>
</servlet-mapping>
</web-app>

在部署描述符中定义的值覆盖使用注解定义的值。

一个Servlet被打包在一个war文件。多个servlet可以被包装 在一起,他们都有着一个servlet上下文。 ServletContext中提供的细节是 关于servlet的执行环境,用于与 容器通信,例如,通过读取封装在该web应用程序的资源,写入一个日志文件,或调度请求。

ServletContext从HttpServletRequest:获得。

protected void doGet(HttpServletRequest request,
HttpServletResponse response) {
  ServletContext context = request.getServletContext();
//. . .
}

一个servlet可以发送一个HTTP cookie,名为JSESSIONID的,到客户端的会话跟踪。
此cookie可能被标记为HttpOnly,这就保证了cookie是不 暴露在客户端脚本代码,从而有助于缓解某些码种crosssite的 脚本攻击。

SessionCookieConfig config = request.getServletContext().
getSessionCookieConfig();
config.setHttpOnly(true);

此外,URL重写可以使用由servlet作为会话跟踪的基础。ServletContext.getSessionCookieConfig方法返回SessionCookieConfig,其可以被用来配置该cookie的不同的属性。 HttpSession接口可以用来查看和操作有关的信息,如会话标识符和创建时间,并把对象绑定到会话中。 下面一个新的会话对象也可被以创建:

protected void doGet(HttpServletRequest request,
HttpServletResponse response) {
HttpSession session = request.getSession(true);
//. . .
}

session.setAttribute 和 session.getAttribute用来绑定对象到session中。

一个servlet可以请求转发到另一个servlet进一步处理。 您可以通过使用RequestDispatcher调度请求到不同的资源实现这一目标 ,这可以从HttpServletRequest.getRequestDispatch获得
ServletContext.getRequestDispatcher。前者可以接受相对路径, 而后者可以接受相对于当前上下文的路径

protected void doGet(HttpServletRequest request,
HttpServletResponse response) {
request.getRequestDispatcher("bank").forward(request, response);
//. . .
}

分发到另外一个同一个容器内的servlet.

你可以通过调用HttpServletResponse.sendRedirect方法重定向一个servlet响应给其他资源
。这发出了一个临时重定向响应(http 301)给客户端, 并在客户端发出一个新的请求到指定的URL。注意,在这种情况下,该 原始请求对象不可用于重定向的URL。重定向也可以
稍微慢一些,因为它需要客户端两个请求:

protected void doGet(HttpServletRequest request,
HttpServletResponse response) {
//. . .
response.sendRedirect("http://example.com/SomeOtherServlet");
}

  除了使用@ WebServlet和web.xml声明的servlet,你可以以编程方式将它们定义,
使用ServletContext.addServlet方法您可以从做到这一点, 该ServletContainerInitializer.onStartup或ServletContextListener.contextInitialized方法。
调用ServletContainerInitializer.onStartup方法,当应用程序 正在启动对于给定的ServletContext。该addServlet方法返回 ServletRegistration.Dynamic,然后可被用于创建URL映射,设置 安全角色,设置初始化参数,并管理其它配置项:

public class MyInitializer implements ServletContainerInitializer {
@Override
public void onStartup (Set<Class<?>> clazz, ServletContext context) {
ServletRegistration.Dynamic reg =
context.addServlet("MyServlet", "org.example.MyServlet");
reg.addMapping("/myServlet");
}
}

下页

JavaEE教程

Java学习心得