1. 双击 bin 目录下的 startup.bat 文件
2. 输入 http://localhost:8080/,显示如下界面代表安装成功, 默认在 8080 端口
3. 注意,不要关闭黑窗口,关闭了,tomcat 服务就停止了.
问题:没有关闭之前的Tomcat服务
解决办法:pkill -9 java的方式强制关闭tomcat服务,然后重新启动。
...\conf\logging.properties配置文件中默认设置的UTF-8改为GBK
打开...\logs日志文件查看日志,查看出错的地方并对症下药。
当我们点击startup.bat之后,黑屏一闪而逝,那么我们可以在startup.bat的末尾敲击pause之后,报错,当我们再次点击之后就会出现对应的错误。没有问题就会出现你的对应的配置文件,jdk之类的。如果还无法解决,看看server.xml中的具体配置是不是缺少某个文件或者文件位置安装错误。
1. server.xml 用于配置 tomcat 的基本设置(启动端口,关闭端口, 主机名)
2. wex.xml 用于指定 tomcat 运行时配置(比如 servlet 等..)
3. webapps 目录是存放 web 应用,就是网站,通常在我们的url后面添加/.....即可。
例如:localhost:8080/web/text.txt就是访问webapps的text.txt文件
1.1 WEB应用是多个web资源的集合。简单的说,可以把web应用理解为硬盘上的一个目录, 这个目录用于管理多个web资源。
1.2 Web应用通常也称之为web应用程序,或web工程,通俗的说 就是网站
一个 WEB 应用由多个 WEB 资源或其它文件组成,包括 html 文件、css 文件、js 文件、动 态 web 页面、java 程序、支持 jar 包、配置文件等。开发人员在开发 web 应用时,按照规 定目录结构存放这些文件。否则,在把 web 应用交给 web 服务器管理时,不仅可能会使 web 应用无法访问,还会导致 web 服务器启动报错
1. news Web工程(目前都是静态资源 html, 图片)
2. 将该news目录/文件夹 拷贝到 Tomcat 的webapps目录下
3. 浏览器输入: http://ip[域名]:port/news/子目录../文件名
1.在Tomcat 下的 conf 目录\Catalina\localhost\ 下,配置文件,比如hong.xml(提醒:知道 Tomcat通过配置,可以把一个web应用,映射到指定的目录,可以解决磁盘空间分配
2.访问web工程: http://ip[域名]:port/hong/index.html 就表示访问 D:\album 目录下的 index.html
1. 在浏览器地址栏中输入访问地址如下:http://ip[域名]:port,没有Web工程/应用名时,默认访问的是 ROOT 工程
2. 在浏览器地址栏中输入的访问地址如下: http://ip[域名]:port/工程名/ ,没有资源名, 默认访问 index.jsp 页面
我们可以通过package打包成war格式或者jar格式返给webapps里面进行编译
思考问题: Tomcat 底层实现 和 调用到 Servlet 流程?
Tomcat 有三种运行模式(BIO, NIO, APR), 因为准备要说的是 Tomcat 如何接收客户端请求,解析请求, 调用 Servlet , 并返回结果的机制流程, 采用 BIO 线程模型来模拟.
import java.io.*; import java.net.ServerSocket; import java.net.Socket; /** * @author hong * @version 1.0 * 这是第一个版本的tomcat ,可以完成,接收浏览器的请求,并返回信息 */ public class HspTomcatV1 { public static void main(String[] args) throws IOException { //1. 创建ServerSocket, 在 8080端口监听 ServerSocket serverSocket = new ServerSocket(8080); System.out.println("=======mytomcat在8080端口监听======"); while (!serverSocket.isClosed()) { //等待浏览器/客户端的连接 //如果有连接来,就创建一个socket //这个socket就是服务端和浏览器端的连接/通道 Socket socket = serverSocket.accept(); //先接收浏览器发送的数据 //inputStream 是字节流=> BufferedReader(字符流) InputStream inputStream = socket.getInputStream(); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "utf-8")); String mes = null; System.out.println("=======接收到浏览器发送的数据======="); //循环的读取 while ((mes = bufferedReader.readLine()) != null) { //判断mes的长度是否为0 if (mes.length() == 0) { break;//退出while } System.out.println(mes); } //我们的tomcat会送-http响应方式 OutputStream outputStream = socket.getOutputStream(); //构建一个http响应的头 //\r\n 表示换行 //http响应体,需要前面有两个换行 \r\n\r\n String respHeader = "HTTP/1.1 200 OK\r\n" + "Content-Type: text/html;charset=utf-8\r\n\r\n"; String resp = respHeader + "hi, hong"; System.out.println("========我们的tomcat 给浏览器会送的数据======"); System.out.println(resp); outputStream.write(resp.getBytes());//将resp字符串以byte[] 方式返回 outputStream.flush(); outputStream.close(); inputStream.close(); socket.close(); // //等会 // inputStream.close(); // socket.close(); } } }
/** * @author hong * @version 1.0 */ public class HspTomcatV2 { public static void main(String[] args) throws IOException { //在8080端口监听 ServerSocket serverSocket = new ServerSocket(8080); System.out.println("=======hongtomcatV2 在8080监听======="); //只要 serverSocket没有关闭,就一直等待浏览器/客户端的连接 while (!serverSocket.isClosed()) { //1. 接收到浏览器的连接后,如果成功,就会得到socket //2. 这个socket 就是 服务器和 浏览器的数据通道 Socket socket = serverSocket.accept(); //3. 创建一个线程对象,并且把socket给该线程 // 这个是java线程基础 HspRequestHandler hspRequestHandler = new HspRequestHandler(socket); new Thread(hspRequestHandler).start(); } } }
浏览器请求 http://localhost:8080/hongCalServlet, 提交数据,完成计算 任务,如果 servlet 不存在,返回 404
package com.hspedu.tomcat; import com.hspedu.tomcat.handler.HspRequestHandler; import com.hspedu.tomcat.servlet.HspHttpServlet; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.io.SAXReader; import javax.servlet.Filter; import javax.servlet.http.HttpSession; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.net.ServerSocket; import java.net.Socket; import java.util.List; import java.util.concurrent.ConcurrentHashMap; /** * @author hong * @version 1.0 * 第3版的Tomcat, 实现通过xml+反射来初始化容器 */ public class HspTomcatV3 { //1. 存放容器 servletMapping // -ConcurrentHashMap // -HashMap // key - value // ServletName 对应的实例 public static final ConcurrentHashMapservletMapping = new ConcurrentHashMap<>(); //2容器 servletUrlMapping // -ConcurrentHashMap // -HashMap // key - value // url-pattern ServletName public static final ConcurrentHashMap servletUrlMapping = new ConcurrentHashMap<>(); //你可以这里理解session, tomcat还维护一个容器 public static final ConcurrentHashMap sessionMapping = new ConcurrentHashMap<>(); //你可以这里理解filter, tomcat还维护了filter的容器 public static final ConcurrentHashMap filterUrlMapping = new ConcurrentHashMap<>(); public static final ConcurrentHashMap filterMapping = new ConcurrentHashMap<>(); //变强.. public static void main(String[] args) { HspTomcatV3 hspTomcatV3 = new HspTomcatV3(); hspTomcatV3.init(); //启动hsptomcat容器 hspTomcatV3.run(); } //启动HspTomcatV3容器 public void run() { try { ServerSocket serverSocket = new ServerSocket(8080); System.out.println("=====hongtomcatv3在8080监听======"); while (!serverSocket.isClosed()) { Socket socket = serverSocket.accept(); HspRequestHandler hspRequestHandler = new HspRequestHandler(socket); new Thread(hspRequestHandler).start(); } } catch (IOException e) { e.printStackTrace(); } } //直接对两个容器进行初始化 public void init() { //读取web.xml => dom4j => //得到web.xml文件的路径 => 拷贝一份. String path = HspTomcatV3.class.getResource("/").getPath(); //System.out.println("path= " + path); //使用dom4j技术完成读取 SAXReader saxReader = new SAXReader(); //困难->真的掌握 try { Document document = saxReader.read(new File(path + "web.xml")); System.out.println("document= " + document); //得到根元素 Element rootElement = document.getRootElement(); //得到根元素下面的所有元素 List elements = rootElement.elements(); //遍历并过滤到 servlet servlet-mapping for (Element element : elements) { if ("servlet".equalsIgnoreCase(element.getName())) { //这是一个servlet配置 //System.out.println("发现 servlet"); //使用反射将该servlet实例放入到servletMapping Element servletName = element.element("servlet-name"); Element servletClass = element.element("servlet-class"); servletMapping.put(servletName.getText(), (HspHttpServlet) Class.forName(servletClass.getText().trim()).newInstance()); } else if ("servlet-mapping".equalsIgnoreCase(element.getName())) { //这是一个servlet-mapping //System.out.println("发现 servlet-mapping"); Element servletName = element.element("servlet-name"); Element urlPatter = element.element("url-pattern"); servletUrlMapping.put(urlPatter.getText(), servletName.getText()); } } } catch (Exception e) { e.printStackTrace(); } //验证,这两个容器是否初始化成功 System.out.println("servletMapping= " + servletMapping); System.out.println("servletUrlMapping= " + servletUrlMapping); } }