本机:MacBook Pro 系统:MacOS 13.4
Tomcat 下载:Apache Tomcat® - Welcome!
这里我下载的是9.0.75版本
启动Tomcat容器碰到Bug:Tomcat started.但是就是没法访问到相关页面,同时jps也没有相关的进程,说明其实没启动起来。同时通过chown改变权限也没法解决问题。
Solution:
查看相关的版本对应记录,以及README的Release notes,发现apache-tomcat-10.1.9需要jdk11及以上,我本地是jdk8,重新下载tar.gz 9.0.75。
重新解压并且startup,可以访问http://localhost:8080了
记得需要配置本地的JAVA_HOME路径,我采用命令vim ~/.bash_profile
export JAVA_HOME="/Library/Java/JavaVirtualMachines/jdk1.8.0_361.jdk/Contents/Home"
pom中导入依赖
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>com.jxzgroupId>
<artifactId>MyJavaWebartifactId>
<packaging>warpackaging>
<version>1.0-SNAPSHOTversion>
<name>MyJavaWeb Maven Webappname>
<url>http://maven.apache.orgurl>
<dependencies>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>servlet-apiartifactId>
<version>2.5version>
dependency>
<dependency>
<groupId>javax.servlet.jspgroupId>
<artifactId>javax.servlet.jsp-apiartifactId>
<version>2.3.3version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>3.8.1version>
<scope>testscope>
dependency>
dependencies>
<build>
<finalName>MyJavaWebfinalName>
build>
project>
main目录下新建java包,并创建com/jxz/servlet目录,在其中放入最简单的HelloServlet,其继承自HttpServlet
package com.jxz.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* @Author jiangxuzhao
* @Description
* @Date 2023/6/3
*/
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
PrintWriter pw = resp.getWriter(); // 获取输出流
pw.print("hello jxz"); // 打印
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doGet(req, resp);
}
}
其中的原理分析:
我们只实现了Get和Post方法,因为这是最普遍的两个Http请求投,我们也可以看到,其实doPost方法也只是复用了一下doGet方法,因为处理是一样的。那么为什么这样子就可以处理http请求了呢?HelloServlet -> public abstract class HttpServlet -> public abstract class GenericServlet -> implements Servlet
/**
* Called by the servlet container to allow the servlet to respond to
* a request.
*
* This method is only called after the servlet's init()
* method has completed successfully.
*
*
The status code of the response always should be set for a servlet
* that throws or sends an error.
*
*
*
Servlets typically run inside multithreaded servlet containers
* that can handle multiple requests concurrently. Developers must
* be aware to synchronize access to any shared resources such as files,
* network connections, and as well as the servlet's class and instance
* variables.
* More information on multithreaded programming in Java is available in
*
* the Java tutorial on multi-threaded programming.
*
*
* @param req the ServletRequest
object that contains
* the client's request
*
* @param res the ServletResponse
object that contains
* the servlet's response
*
* @exception ServletException if an exception occurs that interferes
* with the servlet's normal operation
*
* @exception IOException if an input or output exception occurs
*
*/
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException;
从interface Servlet接口中的定义可以看出:service允许web容器处理请求request,而GenericServlet里面并没有对service()方法进行实现,HttpServlet对service()方法进行了重写,同时这里应用了模板模式,在service中定义了各种http请求方法头method的处理方式,在我们的子类HelloServlet中,让我们重写的doGet或者doPost等方法,子类被调用的时候也就是调用被重写的方法。
/**
*
* Receives standard HTTP requests from the public
* service
method and dispatches
* them to the do
XXX methods defined in
* this class. This method is an HTTP-specific version of the
* {@link javax.servlet.Servlet#service} method. There's no
* need to override this method.
*
*
*
* @param req the {@link HttpServletRequest} object that
* contains the request the client made of
* the servlet
*
*
* @param resp the {@link HttpServletResponse} object that
* contains the response the servlet returns
* to the client
*
*
* @exception IOException if an input or output error occurs
* while the servlet is handling the
* HTTP request
*
* @exception ServletException if the HTTP request
* cannot be handled
*
* @see javax.servlet.Servlet#service
*
*/
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
String method = req.getMethod();
if (method.equals(METHOD_GET)) {
long lastModified = getLastModified(req);
if (lastModified == -1) {
// servlet doesn't support if-modified-since, no reason
// to go through further expensive logic
doGet(req, resp);
} else {
long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
if (ifModifiedSince < (lastModified / 1000 * 1000)) {
// If the servlet mod time is later, call doGet()
// Round down to the nearest second for a proper compare
// A ifModifiedSince of -1 will always be less
maybeSetLastModified(resp, lastModified);
doGet(req, resp);
} else {
resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
}
}
} else if (method.equals(METHOD_HEAD)) {
long lastModified = getLastModified(req);
maybeSetLastModified(resp, lastModified);
doHead(req, resp);
} else if (method.equals(METHOD_POST)) {
doPost(req, resp);
} else if (method.equals(METHOD_PUT)) {
doPut(req, resp);
} else if (method.equals(METHOD_DELETE)) {
doDelete(req, resp);
} else if (method.equals(METHOD_OPTIONS)) {
doOptions(req,resp);
} else if (method.equals(METHOD_TRACE)) {
doTrace(req,resp);
} else {
//
// Note that this means NO servlet supports whatever
// method was requested, anywhere on this server.
//
String errMsg = lStrings.getString("http.method_not_implemented");
Object[] errArgs = new Object[1];
errArgs[0] = method;
errMsg = MessageFormat.format(errMsg, errArgs);
resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
}
}
Web.xml中配置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_4_0.xsd"
version="4.0"
metadata-complete="true">
<!-- 注册servlet名字和类-->
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.jxz.servlet.HelloServlet</servlet-class>
</servlet>
<!--配置Servlet的映射路径和对应的servlet名字-->
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hellojxz</url-pattern>
</servlet-mapping>
</web-app>
Run Configuration中配置web war包到tomcat服务器中
同时指定生成的Deployment war包
除此以外,一个servlet可以指定多个路径映射到相同的servlet,同时可以实现默认的请求路径映射,
<servlet-mapping>
<servlet-name>helloservlet-name>
<url-pattern>/hellojxz2url-pattern>
servlet-mapping>
<servlet-mapping>
<servlet-name>helloservlet-name>
<url-pattern>/*url-pattern>
servlet-mapping>
web-app>