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教程。