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");
}
}