文章目录
- Tomcat
- 概念
- 自制简易的服务器
- JavaEE规范
- Tomcat安装
- Tomcat启动
- Tomcat的资源部署
- 直接部署
- 虚拟映射
- Tomcat的设置
Tomcat
概念
- 服务器:两层含义。
- 软件层面:软件,可以将本地的资源发布到网络中,供网络上面的其他用户来访问,比如tomcat;
- 硬件层面:一台性能比较高效的计算机主机,云服务器。
- 服务器开发:指的是在服务器软件程序中进一步去编写程序来运行
- 静态资源:页面一成不变的。
- 动态资源:富有交互性、变化性。
- 目前访问的网站页面基本都是动态资源。本质就是程序。比如登录之后会显示各自的用户名。开发动态资源的技术有很多种,其中java语言中 servlet。
自制简易的服务器
单线程的服务器:
public class ServerDemo {public static void main(String[] args) throws IOException {ServerSocket serverSocket = new ServerSocket(8089);Socket socket = serverSocket.accept();// 怎么从socket获取信息InputStream inputStream = socket.getInputStream();byte[] bytes = new byte[20480];//输入的数据会放到字节数组bytes里面;读出的长度会返回lengthint length = inputStream.read(bytes);String inputStr = new String(bytes, 0, length);System.out.println(inputStr);// 想根据url上面的信息,返回1.txt 1.png// 应该拿出请求行; 再取出第二个数据// \r\n表示回车int index1 = inputStr.indexOf("\r\n");String firstLine = inputStr.substring(0, index1);// firstLine 为 GET /1.txt HTTP/1.1System.out.println(firstLine);// Strings = {GET, /1.txt, HTTP/1.1}String[] strings = firstLine.split(" ");System.out.println(strings[0]);System.out.println(strings[1]);System.out.println(strings[2]);// split之后获取到了1.txt// resourceName = 1.txtString resourceName = strings[1].substring(1);System.out.println(resourceName);// data如果有数据// 那么则传入1.txt// 1. 把数据的字节数组写回来// 2. 文件不存在,返回长度为0的字节数组byte[] data = getDataFromFile(resourceName);OutputStream outputStream = socket.getOutputStream();StringBuffer stringBuffer = new StringBuffer();if (data.length == 0) {// 代表文件没找到stringBuffer.append("HTTP/1.1 404 NotFound\r\n");stringBuffer.append("Server: coo1heisenberg\r\n");stringBuffer.append("Content-type: text/html\r\n");stringBuffer.append("\r\n");// 如果文件没找到,把data数组赋值data = "<div style = 'font-size: 50px'>file not found</div>".getBytes("utf-8");} else {stringBuffer.append("HTTP/1.1 200 Ok\r\n");stringBuffer.append("Server: coo1heisenberg\r\n");stringBuffer.append("Content-type: text/html\r\n");stringBuffer.append("\r\n");}// StringBuffer里面是响应行,响应头,空行的内容outputStream.write(stringBuffer.toString().getBytes("utf-8"));// data里面是文件的内容outputStream.write(data);outputStream.close();}private static byte[] getDataFromFile(String resourceName) throws IOException {InputStream inputStream1 = ServerDemo1.class.getClassLoader().getResourceAsStream(resourceName);byte[] bytes = new byte[20480];if (inputStream1 == null) {return new byte[0];} else {int len = inputStream1.read(bytes);byte[] bytes1 = Arrays.copyOf(bytes, len);return bytes1;}}
}
多线程的服务器:
public class ServerDemo {public static void main(String[] args) throws IOException {ServerSocket serverSocket = new ServerSocket(8089);while (true) {Socket socket = serverSocket.accept();new Thread(() -> {// 怎么从socket获取信息InputStream inputStream = null;try {inputStream = socket.getInputStream();} catch (IOException e) {throw new RuntimeException(e);}byte[] bytes = new byte[20480];//输入的数据会放到字节数组bytes里面;读出的长度会返回lengthint length = 0;try {length = inputStream.read(bytes);} catch (IOException e) {throw new RuntimeException(e);}String inputStr = new String(bytes, 0, length);System.out.println(inputStr);// 想根据url上面的信息,返回1.txt 1.png// 应该拿出请求行; 再取出第二个数据// \r\n表示回车int index1 = inputStr.indexOf("\r\n");String firstLine = inputStr.substring(0, index1);// firstLine 为 GET /1.txt HTTP/1.1System.out.println(firstLine);// Strings = {GET, /1.txt, HTTP/1.1}String[] strings = firstLine.split(" ");System.out.println(strings[0]);System.out.println(strings[1]);System.out.println(strings[2]);// split之后获取到了1.txt// resourceName = 1.txtString resourceName = strings[1].substring(1);System.out.println(resourceName);// data如果有数据// 那么则传入1.txt// 1. 把数据的字节数组写回来// 2. 文件不存在,返回长度为0的字节数组byte[] data = new byte[0];try {data = getDataFromFile(resourceName);} catch (IOException e) {throw new RuntimeException(e);}OutputStream outputStream = null;try {outputStream = socket.getOutputStream();} catch (IOException e) {throw new RuntimeException(e);}StringBuffer stringBuffer = new StringBuffer();if (data.length == 0) {// 代表文件没找到stringBuffer.append("HTTP/1.1 404 NotFound\r\n");stringBuffer.append("Server: coo1heisenberg\r\n");stringBuffer.append("Content-type: text/html\r\n");stringBuffer.append("\r\n");// 如果文件没找到,把data数组赋值try {data = "<div style = 'font-size: 50px'>file not found</div>".getBytes("utf-8");} catch (UnsupportedEncodingException e) {throw new RuntimeException(e);}} else {stringBuffer.append("HTTP/1.1 200 Ok\r\n");stringBuffer.append("Server: coo1heisenberg\r\n");stringBuffer.append("Content-type: text/html\r\n");stringBuffer.append("\r\n");}// StringBuffer里面是响应行,响应头,空行的内容try {outputStream.write(stringBuffer.toString().getBytes("utf-8"));} catch (IOException e) {throw new RuntimeException(e);}// data里面是文件的内容try {outputStream.write(data);} catch (IOException e) {throw new RuntimeException(e);}try {outputStream.close();} catch (IOException e) {throw new RuntimeException(e);}}).start();}}private static byte[] getDataFromFile(String resourceName) throws IOException {InputStream inputStream1 = ServerDemo1.class.getClassLoader().getResourceAsStream(resourceName);byte[] bytes = new byte[20480];if (inputStream1 == null) {return new byte[0];} else {int len = inputStream1.read(bytes);byte[] bytes1 = Arrays.copyOf(bytes, len);return bytes1;}}
}
抽象出一个Request方法:
public class Request {// GET POSTString method;String resourceName;String protocol;// 请求头用什么数据来装?Map<String, String> Header = new HashMap<>();public void parseContent(String content) {//parseFirstLine(content);parseHeaders(content);}private void parseHeaders(String content) {// 在windows下面是\n// 在Linux下面是 \r\n// 在mac下面是 \rint index1 = content.indexOf("\r\n");// 怎么确定请求头结束int index2 = content.indexOf("\r\n\r\n");String headersStr = content.substring(index1 + 2, index2);System.out.println(headersStr);// 1.按照\r\n切分split// 2. 得到数组,代表一行// 3. 一行切分,按照":"}private void parseFirstLine(String content) {int index = content.indexOf("\r\n");String firstLine = content.substring(0, index);String[] strings = firstLine.split(" ");method = strings[0];resourceName = strings[1];protocol = strings[2];}
}
JavaEE规范
- 制定了一系列的接口。相应的厂商需要实现该接口,对于开发者来说,只需要面向接口编程即可。
- JDBC也是,定义了很多的接口
Tomcat安装
Tomcat控制台乱码解决办法:
- 原因:cmd是GBK编码,Tomcat是UTF8编码
- 解决:
- 修改
logging.properties
配置:- 打开
tomcat/conf/logging.properties
- 添加语句:
java.util.logging.ConsoleHandler.encoding = GBK
- 重启tomcat,查看日志数据即可
- 打开
- 修改
Tomcat启动
- 双击
startup.bat
文件 bin
目录下换出cmd,执行startup
常见的启动故障:
- 没有正确配置好
JAVA_HOME
,导致tomcat一闪而过
Tomcat的资源部署
直接部署
eg:
- 写ip+端口 --> 相当于找到了webapps目录
localhost:8080/test
- 如果你想访问
test
文件夹下的1.txt
。 只用写相对路径,http://localhost:8080/test/1.txt
- 如果想访问
test
文件夹里面的2.png
,怎么写呢?http://localhost:8080/test/2.png
注意:
不能将文件直接放置在webapps目录下。需要放在webapps目录下的文件夹内。
虚拟映射
不在webapps目录这种方式叫做虚拟映射。虚拟地映射到Tomcat的webapps目录下。
conf/Catalina/localhost
(掌握)- 新建一个
.xml
的配置文件 - 在
.xml
的文件(test1.xml
)里面配置context的节点信息
eg:
- 新建一个
第一行是一个标识,表示这是一个xml
<?xml version="1.0" encoding="UTF-8"?>第二行表示在D盘有一个叫test_Photo的目录
<Context docBase="D:\test_Photo"/>
- 访问流程
localhost:8080/{xml的名称}
- 相当于会找到了
docBase
指定的文件夹
- 相当于会找到了
localhost:8080/{xml的名称}/{相对于docBase的相对路径}
- eg:
服务器最终会把url的路径映射到本地磁盘的一个路径上面
conf/server.xml
(了解)
-
需要在
Host
节点下配置Context节点/app452-----Context
<Context path="/app452" docBase="D:\test_Photo" />
http://localhost:8080/{path}/{文件相对于docBase的相对路径}
- eg:
http://localhost:8080/app452/2.jpg
- eg:
Tomcat的设置
- 设置默认端口号
- 对于
http
协议来说,默认端口号是80
端口号。如果你也希望访问你的tomcat时,也不携带端口号,你只需要设置你的tomcat监听80端口号即可。 - 在
conf/server.xml
中配置
- 对于
<Connector port="80" protocol="HTTP/1.1"connectionTimeout="20000"redirectPort="8443" />
- 设置缺省应用
- tomcat中存在着一个缺省应用,如果没有找到匹配的应用时,则将该请求交给缺省应用来处理。
- 具体步骤:
- 如果希望配置一个
ROOT
应用,那么webapps
目录下新建一个ROOT
目录 conf/Catalina/localhost
目录下新建一个ROOT.xml
- 如果希望配置一个
ROOT
应用下的资源文件在访问时,不需要携带应用的名称
以下为ROOT.xml的示例代码:<?xml version="1.0" encoding="UTF-8"?>
<Context docBase="D:\test_Photo"/>
虚拟映射也可以配置一个ROOT.xml
,如果虚拟映射和直接部署都有,那么则是虚拟映射优先级高
- 设置欢迎页面(缺省页面)
-
比如:访问
http://localhost
,可以显示出一个页面,那么访问的是哪个页面:-
没有应用名,说明访问的是
ROOT
应用 -
没有页面,说明访问的是欢迎页面(
conf/web.xml
文件中有配置)- 表示的是:如果请求没有指明具体访问的是哪个页面,那么会在当前应用下依次去查找是否存在该文件,如果存在,则加载;如果不存在,则返回404
-
eg:
现在在chrome里面输入localhost,直接访问到我的D:\app3
的1.jpg
的图片,那么分为几个步骤?
-
修改端口号,改成8080端口
-
虚拟映射
-
在
/conf/web.xml
下修改welcome-file-list
加上一个1.jpg