前言
这一章将记录使用 NetBeans 在 Tomcat 中创建 servlet 程序。
Servlet(Ser ver App let) 是运行在 WEB 服务端的小程序,目的是和客户端交互并且生成动态的 web 内容,它可以接收来自客户端的请求并生成响应。
环境搭建
本篇记录将基于 Java 环境和 Tomcat 服务器创建 Servlet 应用程序,关于集成 Java 环境和 NetBeans 搭建 Tomcat 服务器可以看之前的记录:
https://hoyue.fun/web_tomcat_starthost.html
创建 Servlet 程序
首先我们必须要新建一个 Web 项目才能创建 servlet 应用,打开 NetBeans IDE,选择 File -> New Project。

然后选择 Java Web -> Web Application 创建 Java Web 项目。

给你的 Web 项目起一个名字,例如 hoyue,我们可以点击 browse 选择这个项目存储的位置:

然后选择我们之前创建过的 Tomcat 服务器,path 处可以填写不同的映射地址。

对于 Frameworks 则不需要选择其他的框架,直接点击 Finish。至此 Java Web 项目已经创建完成。
要创建 Servlet,请打开 Source Package,右键单击

接下来为你的 Servlet 类文件命名,同时也建议自定义 Package(包)名。
PS:Servlet 类文件 没有 main() 方法,它是一个 Java 类,通过覆盖 doGet()、doPost() 等方法来处理客户端请求。

接下来,如果在配置部署中勾选了“将信息添加到部署描述符(web.xml)” ,它会自动将你的 servlet 应用注册到 web.xml 中,让 web 程序能自动识别到你的应用。
我们可以修改 URL Pattern(URL 模式),用于定义访问我们的 servlet 应用 URL。

当然还可以通过 @WebServlet 注解来解决,之后也会讲解。如果选择添加 @WebServlet 注解这里请不要勾选。
@WebServlet注解用于将一个 Java 类声明为 Servlet,并指定它所处理的 URL 模式。
至此就已经创建好了 servlet 应用。
运行 Servlet 应用
遇到错误问题可以到下面的 Q&A 下查找!
以一个 ServletHello 作为一个测试应用,让它输出 hello world。例如下面的这个程序:
import java.io.*;import javax.servlet.*;import javax.servlet.http.*;
/** * Hello World! servlet */public class ServletHello extends HttpServlet{ /** * Respond to any HTTP GET request with an * HTML Hello World! page. * @param request * @param response * @throws javax.servlet.ServletException * @throws java.io.IOException */ @Override public void doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // Set the HTTP content type in response header response.setContentType("text/html; charset=\"UTF-8\"");
// Create the body of the response try ( // Obtain a PrintWriter object for creating the body // of the response PrintWriter servletOut = response.getWriter()) { // Create the body of the response servletOut.println( "<!DOCTYPE html \n" + " PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \n" + " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\"> \n" + "<html xmlns='http://www.w3.org/1999/xhtml'> \n" + " <head> \n" + " <title> \n" + " ServletHello.java \n" + " </title> \n" + " </head> \n" + " <body> \n" + " <p> \n" + " Hello World! \n" + " </p> \n" + " </body> \n" + "</html> "); servletOut.close(); } }}我们可以将这些代码添加到刚才创建好的文件中,替换到 Package 之下(如果你设定了 Package 的名字):

注意:如果代码块区域出现了黄色三角形警告,可以点击自动修复让 NetBeans 帮你修改警告的部分即可。(上述提供的代码已经做出一部分修改)

(下面添加内容仅为没有勾选添加到 web.xml 的用户需要的操作)
如果你之前没有勾选添加到 web.xml 的选项,请添加一些内容用于定义 URL 模式。
我们需要引用一个 javax.servlet.annotation.WebServlet 库和 @WebServlet 注解。
import javax.servlet.annotation.WebServlet;@WebServlet(name = "ServletHello", urlPatterns = { "/ServletHello" })// Class 定义之前我们使用 @WebServlet 注解来定义一个 servlet,并使用 urlPatterns 属性将 HTTP GET 请求映射到 /ServletHello 路径上。当客户端访问这个路径时,将会执行 doGet 方法并将 “Hello, World!” 字符串写入 HTTP 响应中。

然后我们就可以通过这个地址运行访问我们的应用了。选择左侧该 Servlet 应用,点击 Run。

接下来设置 URL 模式,这里因为我们这个例子中没有参数,那就直接点击 OK 即可。

然后等待 NetBeans 的部署,完成后就可以在浏览器中查看结果了。我的例子的地址为:http://localhost:8084/hoyue/ServletHello
一般你的地址为:http://hostname:[port]/project_name/servlet_name
成功结果如图:

动态响应案例
上面的 hello 例子没有体现出 servlet 根据 GET 与 POST 动态反馈内容的能力,下面是一个简单的动态响应案例。
一个博客有一个登录页面和一个评论页面。如果我们正确填写了账号密码就会跳转到评论页面,反之则没有。
博客文件将会被放在项目的 MOBFiles 文件夹下,登录页面为
login.html,addentry.html表示一个评论页面,servlet 类文件为Login.java
我们先创建 servlet 类文件并命名为 Login,在 Package 之后写下如下代码:
代码已做精简(去除暂未使用的 import,并调整路径):
import java.io.*;import javax.servlet.*;import javax.servlet.http.*;
public class Login extends HttpServlet {/*** Processes requests for both HTTP GET and POST methods.** @param request servlet request* @param response servlet response* @throws ServletException if a servlet-specific error occurs* @throws IOException if an I/O error occurs*/@Overrideprotected void doGet (HttpServletRequest request,HttpServletResponse response)throws ServletException, IOException{ response.sendRedirect("./MOBFiles/login.html");}
@Overrideprotected void doPost(HttpServletRequest request,HttpServletResponse response)throws ServletException, IOException{ String username = request.getParameter("username"); String password = request.getParameter("pwd"); if (username != null && password != null && username.equals("nice") && password.equals("try")) { HttpSession session = request.getSession(); session.setAttribute("loggedIn", true); response.sendRedirect("./MOBFiles/addentry.html"); } else { response.sendRedirect("./MOBFiles/login.html"); }}}
代码的意思是:
- 在
doGet方法中,servlet 发送一个重定向响应到 URL./MOBFiles/login.html。这意味着当用户使用 HTTP GET 请求访问 servlet 时,他们将被重定向到登录页面。 - 在
doPost方法中,servlet 处理 POST 请求,使用getParameter()方法从请求中检索username和pwd参数。当两者与正确值nice/try匹配时,创建会话并设置loggedIn=true,再重定向到./MOBFiles/addentry.html。 - 否则重定向回登录页面。
接下来就是两个简单的 html 页面及其 CSS 文件,我们把它们放到项目的 MOBFiles 文件夹下(即移动到 web 目录下),如下图:

这些文件放到了网盘中可以直接下载:
当然我们需要修改 login.html 文件中提交的 action,以便于将 POST 内容发送给 servlet。只需要填写 /project_name/Login 即可(根据你的项目名调整)。

最后尝试运行这个 servlet 程序,然后在浏览器中访问它,我设置的地址为 http://localhost:8084/hoyue/Login,一般为 http://hostname:[port]/project_name/Login_name
输入地址后会被重定向到登录页面 login.html:

在 servlet 程序中设置的账号为 nice,密码为 try,输入正确后会跳转到评论页面:

如果密码错误则重新返回登录页面:

至此,这是一个简单的根据 GET 与 POST 做出响应的 servlet 程序案例。
Q&A
下面是一些常见问题与解答,如果遇到了其他问题,欢迎在评论区留言,或通过邮箱等方式联系我。
-
Q:Class “[classname]” neither has a main method nor is it a servlet specified in web.xml
首先,请注意 在左侧文件中右键运行文件,而不是点击上方的运行键。上方的运行键在部署后将需要
main()方法,而 servlet 没有main()方法。除此之外,这个问题还说明你的 Servlet 类没有在 web.xml 文件中被定义为 servlet:如果你想将你的类作为 servlet 运行,那么你需要在 web.xml 文件中定义它。-
如果你在创建 servlet 的时候勾选了 自动添加,请在 Files -> web -> WEB-INF 找到 web.xml,检查
<servlet-name>和<servlet-class>是否填写正确;若你修改了文件名,也需要同步修改这里的配置。形如:<servlet><servlet-name>Servletname</servlet-name><servlet-class>package_name.Servletname</servlet-class></servlet><servlet-mapping><servlet-name>Servletname</servlet-name><url-pattern>/url</url-pattern></servlet-mapping> -
如果你 没有勾选 添加到 web.xml,那么请检查
@WebServlet注解,例如在 ServletHello 类上添加注解,指定名称为 “MyServlet”,URL 模式为 “/hello”:@WebServlet(name = "MyServlet", urlPatterns = { "/hello" })
-
-
Q:“HTTP Status 404 – Not Found” 错误
这通常是由于 servlet 的 URL 映射不正确 导致。确保在 web.xml 文件中或者在
@WebServlet注解里正确地映射了 servlet 的 URL,并且在浏览器中输入的 URL 与映射匹配。例如项目名为 hoyue,映射 URL 模式为/ServletHello,则应访问http://hostname:[port]/hoyue/ServletHello。 -
Q:
javax.servlet不存在可能因为没有将 Servlet API 添加到项目依赖。NetBeans 中右键项目 -> Properties -> Libraries -> Add Library,选择 Java EE API(或合适版本)。或将
javax改为jakarta的相应包名。 -
Q:Tomcat 部署时报错,
StandardWrapperValve.invoke分配异常、ClassNotFoundException通常是 Tomcat 找不到你的 servlet 类文件。确认 web.xml 的类名与包名一致;或将编译产物打成 JAR 放置到 Tomcat 的
lib目录,让类加载器可见。 -
Q:Can’t import
javax.servlet.annotation.WebServlet请确认 Tomcat 版本并多尝试构建。可在 web.xml 头部添加如下声明以启用 3.0 规范:
<web-app xmlns="http://java.sun.com/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://java.sun.com/xml/ns/javaeehttp://www.java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0"> -
Q:没用到的 import 头
可以删除,没有影响。
-
Q:头部报错
incorrect package如果创建时未设置包名,将位于 default package,不需要
package语句;若自定义了包名,需要在头部使用package xxx;声明,例如:package servlet; -
Q:类名与文件名不匹配
Java 要求
public类名与文件名一致。请检查类名与文件名是否一致。
后记
这一章记录了使用 NetBeans 在 Tomcat 中创建 servlet 程序的一些简单细节。