Servlets 和 Java Server Pages
最后修改于 2024 年 1 月 27 日
Servlet 是一个生成动态内容的 Java Web 组件。Servlet 由 Jetty 或 Tomcat 等容器管理;它们是用于基于请求-响应编程模型构建 Web 应用程序的类。Java Server Pages (JSP) 技术允许我们轻松创建同时包含静态和动态组件的 Web 内容。JSP 由 JSP 编译器编译成 servlet。
本章将介绍如何在 Jetty 中设置 servlets 和 Java Server Pages。
处理 POST 请求
HTTP POST 请求将数据从客户端发送到服务器。HTML 表单使用 POST 方法将数据发送到服务器。
在我们的示例中,一个 servlet 处理客户端发送的数据。它检索值并将它们发送回客户端。
tree . ├── build.xml └── src ├── com │ └── zetcode │ └── MyServlet.java └── web ├── index.html └── WEB-INF └── web.xml 5 directories, 4 files
我们的项目目录看起来是这样的。
<!DOCTYPE html> <html> <body> <form id="contact" method="post" action="process.do"> <label for="name">Name:</label> <input type="text" name="name"> <br> <label for="age">Age:</label> <input type="text" name="age"> <input type="submit" value="Submit"> </form> </body> </html>
index.html
文件包含一个 HTML 表单。它有两个 input 标签用于从用户获取数据。稍后可以从请求参数中检索值,这些参数的名称与 input 的 name 属性匹配。form 标签的 action
属性提供了一个 URL 模式,该模式映射到一个特定的 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"> </web-app>
web.xml
是空的。URL 到 servlet 的映射是使用注解创建的。实际上,在我们的示例中不需要该文件。但是,由于并非所有功能都可以被注解替换,因此 web.xml
文件包含在较大的项目中。
package com.zetcode; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.annotation.WebServlet; @WebServlet(urlPatterns = "/process.do") public class MyServlet extends HttpServlet { @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/plain"); response.setStatus(HttpServletResponse.SC_OK); response.getWriter().format("Name: %s%n", request.getParameter("name")); response.getWriter().format("Age: %s%n", request.getParameter("age")); } }
这是我们处理 servlet 的代码。
@WebServlet(urlPatterns = "/process.do")
WebServlet
注解将 com.zetcode.MyServlet
映射到 /process.do
URL 模式。
response.getWriter().format("Name: %s%n", request.getParameter("name"));
我们使用 getParameter
方法从请求对象中检索 name 值。name 参数对应于 input 标签的 name 属性。
<?xml version="1.0" encoding="UTF-8"?> <project name="ProcessForm" default="compile"> <property name="name" value="myform"/> <property environment="env"/> <property name="src.dir" value="src"/> <property name="web.dir" value="${src.dir}/web"/> <property name="build.dir" location="${web.dir}/WEB-INF/classes"/> <property name="jetty.lib.dir" location="${env.JETTY_HOME}/lib"/> <property name="dist.dir" location="dist"/> <property name="deploy.path" location="${env.JETTY_BASE}/webapps"/> <path id="compile.classpath"> <fileset dir="${jetty.lib.dir}"/> </path> <target name="init"> <mkdir dir="${build.dir}"/> <mkdir dir="${dist.dir}"/> </target> <target name="compile" depends="init"> <javac srcdir="${src.dir}" destdir="${build.dir}" includeantruntime="false"> <classpath refid="compile.classpath"/> </javac> <echo>Compilation completed</echo> </target> <target name="archive" depends="compile"> <war destfile="${dist.dir}/${name}.war" webxml="${web.dir}/WEB-INF/web.xml"> <fileset dir="${web.dir}"/> </war> <echo>Archive created</echo> </target> <target name="clean" depends="init"> <delete dir="${build.dir}"/> <delete dir="${dist.dir}"/> <echo>Cleaning completed</echo> </target> <target name="deploy" depends="archive"> <copy file="${dist.dir}/${name}.war" overwrite="true" todir="${deploy.path}"/> <echo>Archive deployed</echo> </target> </project>
这是 Ant 构建文件。
$ curl --data "name=Robert&age=33" localhost:8080/myform/process.do Name: Robert Age: 33
我们使用 curl
工具发出 POST 请求,servlet 以这两行进行响应。
自定义 404 错误页面
本示例设置了一个自定义 JSP 页面,用于显示 HTTP 404
错误。404
或 Not Found 错误消息是 HTTP 标准响应代码,表示客户端已成功与给定服务器通信,但服务器找不到所请求的内容。
$ tree . ├── build.xml └── src ├── com │ └── zetcode │ └── MyServlet.java └── web ├── error404.jsp └── WEB-INF └── web.xml 5 directories, 4 files
这是项目目录的内容。
<%@ page language="java" isErrorPage="true" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <title>Error page</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> </head> <body> <button onclick="history.back()">Back to Previous Page</button> <h1>404 Page Not Found.</h1> <p><b>Error code:</b> ${pageContext.errorData.statusCode}</p> <p><b>Request URI:</b> ${pageContext.request.scheme}://${header.host}${pageContext.errorData.requestURI} </p> </body> </html>
如果 Jetty 找不到请求的页面,将显示此 JSP 页面。
package com.zetcode; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class MyServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/plain"); response.setStatus(HttpServletResponse.SC_OK); response.getWriter().println("MyServlet called"); } }
创建了一个简单的 servlet。该 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>MyServlet</display-name> <servlet id="jsp"> <servlet-name>jsp</servlet-name> <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class> <init-param> <param-name>fork</param-name> <param-value>false</param-value> </init-param> <init-param> <param-name>keepgenerated</param-name> <param-value>true</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet> <servlet-name>MyServlet</servlet-name> <servlet-class>com.zetcode.MyServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>MyServlet</servlet-name> <url-pattern>/myservlet.do</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>jsp</servlet-name> <url-pattern>*.jsp</url-pattern> </servlet-mapping> <error-page> <error-code>404</error-code> <location>/error404.jsp</location> </error-page> </web-app>
web.xml
文件注册了一个处理 JSP 页面的 JspServlet
,注册了我们的 MyServlet,并将 error404.jsp
文件映射到 404 错误。
<?xml version="1.0" encoding="UTF-8"?> <project name="CustomErrorPage" default="compile"> <property name="name" value="customerror"/> <property environment="env"/> <property name="src.dir" value="src"/> <property name="web.dir" value="${src.dir}/web"/> <property name="build.dir" location="${web.dir}/WEB-INF/classes"/> <property name="lib.dir" location="${env.JETTY_HOME}/lib"/> <property name="dist.dir" location="dist"/> <property name="deploy.path" location="${env.JETTY_BASE}/webapps"/> <path id="compile.classpath"> <fileset dir="${lib.dir}"/> </path> <target name="init"> <mkdir dir="${build.dir}"/> <mkdir dir="${dist.dir}"/> </target> <target name="compile" depends="init"> <javac srcdir="${src.dir}" destdir="${build.dir}" includeantruntime="false"> <classpath refid="compile.classpath"/> </javac> <echo>Compilation completed</echo> </target> <target name="archive" depends="compile"> <war destfile="${dist.dir}/${name}.war" webxml="${web.dir}/WEB-INF/web.xml"> <fileset dir="${web.dir}"/> </war> <echo>Archive created</echo> </target> <target name="clean" depends="init"> <delete dir="${build.dir}"/> <delete dir="${dist.dir}"/> <echo>Cleaning completed</echo> </target> <target name="deploy" depends="archive"> <copy file="${dist.dir}/${name}.war" overwrite="true" todir="${deploy.path}"/> <echo>Archive deployed</echo> </target> </project>
这是 Ant 构建文件。
$ java -jar $JETTY_HOME/start.jar --add-to-start=http,deploy,jsp,jstl,annotations
这些模块必须在 Jetty 基础环境中启用。
$ java -jar $JETTY_HOME/start.jar $ curl localhost:8080/customerror/myservlet.do MyServlet called
我们启动 Jetty 并发出一个有效请求。
$ curl localhost:8080/customerror/servlet.do <!DOCTYPE html> <html> <head> <title>Error page</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> </head> <body> <button onclick="history.back()">Back to Previous Page</button> <h1>404 Page Not Found.</h1> <p><b>Error code:</b> 404</p> <p><b>Request URI:</b> https://:8080/customerror/servlet.do</p> </body> </html>
尝试访问不存在的资源会导致 Jetty 发送我们的自定义 404
错误页面。
在本章的 Jetty 教程中,我们使用了 Java servlets 和 JSPs。
作者
列出所有Java教程。