DAY14.1 Java核心基础
JavaWeb
javaWeb 是指的是java提供了一系列组件来开发web应用程序,基于java网络编程
Socket、Servlet、Filter底层都是网络编程,进行了封装,我们只需要调用相关方法使用即可
Tomcat介绍
Tomcat是一个web容器,开发好的程序放入Tomcat里面就可以直接运行了,客户端就可以访问
单独的程序是无法直接运行的,必须依赖web容器
Web容器以内的资源可以允许外部直接访问,Web容器以外的资源无法直接访问
常见的Web容器:Tomcat、Jboss、Weblogic
Tomcat安装之后的包的作用:

bin:各种脚本,比如启动和关闭Tomcat
conf:配置文件,可以设置端口等...信息
lib:相关的jar包,比如servlet...
logs:运行日志文件
temp:临时文件
webapps:需要运行的程序,资源
work:JSP转换之后的servlet文件
实际开发中不需要在这启动,在开发的时候可以导入到IDEA里面
创建Web项目:

编辑配置,找到相应的tomcat配置

根据路径访问主路径下面的img.png图片呢,可以访问到

需要注意
应用程序上下文可以删除,这样就直接可以在端口后面加路径了,http://localhost:3030/img.png

WEB-INF里面的文件无法通过浏览器路径访问

导入Servlet依赖
xml
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
创建一个测试接口
java
@WebServlet("/test")
public class Test extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setCharacterEncoding("GBK");
resp.getWriter().write("Hello World,这是Tomcat!");
}
}
添加工件:

需要注意我这里将这个上下文给取消了,这样访问的时候就没有相应工件的代码了
只需要在端口后面加 /路径 即可

启动tomcat
浏览器访问

可以看见访问到接口test的内容了
重点:
手写一个Tomcat容器
java网络编程、Socket
要求:手写一个 Web 应用服务器,不能使用 Servlet,要求使用 Socket 来编程
- 可以响应 Get 请求
- 打印请求信息
- 判断请求的资源是否存在,若不存在,给出 404 错误提示
- 若资源存在,返回该资源
- 并且有默认的资源页面
- 要求客户端使用浏览器进行访问
思路:
- 需要有一个对象来持续接收端口的请求
- 还需要有一个对象来封装以及处理接收到的请求
- 还有一个对象来封装返回的结果
创建一个HttpRequest对象来接收接收到的请求
关键点:
- 通过服务器accept ()接收到的socket对象获取到inputStream传入对象
- 处理inputSteam,获取到访问路径的uri,存入到该对象的uri中
- inputSteam读取到的数据为

可以通过读取的第一个和第二个空格取出访问的路径/index.html
java
//处理请求
int index1,index2;
index1= buffer.indexOf(" ");
index2 = buffer.indexOf(" ",index1+1);
uri = buffer.substring(index1+1,index2);
HttpRequest代码:
java
public class HttpRequest {
private InputStream inputStream;
private String uri;
public String getUri() {
return uri;
}
public HttpRequest(InputStream inputStream) {
this.inputStream = inputStream;
}
/**
* 获取请求的路径文件
* @return
*/
public String parse() {
StringBuffer buffer = new StringBuffer(2048);
// 处理请求
int lenth =0;
byte[] bytes = new byte[2048];
try {
lenth = inputStream.read(bytes);
} catch (IOException e) {
throw new RuntimeException(e);
}
for (int j = 0; j < lenth; j++) {
// 读取请求
buffer.append((char) bytes[j]);
}
//处理请求
int index1,index2;
index1= buffer.indexOf(" ");
index2 = buffer.indexOf(" ",index1+1);
uri = buffer.substring(index1+1,index2);
System.out.println("uri:" + uri);
// 打印请求
System.out.println(buffer);
return uri;
}
}
创建一个对象用于封装返回的数据资源
关键点:
- 通过传入ServerSocket的accept()方法获取到OutputStream来创建一个HttpResponse对象
- data和code是封装状态码和静态资源
- sendStaticResource()方法可以发送静态资源
- 根据路径ServerSocket的WebContent封装的默认静态资源目录加上路径后缀得到相关的资源路径
- 然后用传入的InputStream来读取静态资源文件,封装到data中
- 用StringBuilder封装返回的内容,需要返回浏览器可以读取的形式
java
StringBuilder response = new StringBuilder();
response.append("HTTP/1.1 ").append(code).append(" Not OK\r\n");
response.append("Content-Type: text/html; charset=UTF-8\r\n");
// 修正 Content-Length 为字节长度
response.append("Content-Length: ").append(data.getBytes(StandardCharsets.UTF_8).length).append("\r\n");
response.append("\r\n");
response.append(data);
- 通过OutputStream输出到浏览器
java
this.outputStream.write(response.toString().getBytes(StandardCharsets.UTF_8));
- 访问路径为空和"/"的情况做一个处理转入到默认静态资源路径
- 如果找不到则返回一个设置好的404.html界面
HttpResponse代码:
java
public class HttpResponse {
private final OutputStream outputStream;
private String data;
private Integer code;
public HttpResponse(OutputStream outputStream, String data, Integer code) {
this.outputStream = outputStream;
this.data = data;
this.code = code;
}
public void sendStaticResource(HttpRequest httpRequest) throws UnsupportedEncodingException {
// 判断当前的请求资源,如果为/或者空,则默认设置到首页
String uri = httpRequest.getUri();
if ("/".equals(uri) || uri.isEmpty()) {
uri = "/index.html";
System.out.println("默认页面测试............");
}
// 判断文件资源是否存在,如果存在返回响应,如果不存在返回404响应
File file = new File(MyHttpServer.WebContent + uri);
byte[] bytes = new byte[(int) file.length()];
if (file.exists() && file.isFile()) {
// 读取文件内容
try {
InputStream inputStream = Files.newInputStream(file.toPath());
inputStream.read(bytes);
} catch (IOException e) {
throw new RuntimeException(e);
}
data = new String(bytes, StandardCharsets.UTF_8);
code = 200;
} else {
code = 404;
// 读取预定义的404.html文件内容
File errorFile = new File(MyHttpServer.WebContent + "/404.html");
if (errorFile.exists()) {
try (InputStream inputStream = Files.newInputStream(errorFile.toPath())) {
byte[] errorBytes = new byte[(int) errorFile.length()];
inputStream.read(errorBytes);
data = new String(errorBytes, StandardCharsets.UTF_8);
} catch (IOException e) {
// 回退到默认文本
data = "404 Not Found";
}
} else {
// 若404.html不存在则使用默认文本
data = "404 Not Found";
}
}
StringBuilder response = new StringBuilder();
response.append("HTTP/1.1 ").append(code).append(" Not Found\r\n");
response.append("Content-Type: text/html; charset=UTF-8\r\n");
// 修正 Content-Length 为字节长度
response.append("Content-Length: ").append(data.getBytes(StandardCharsets.UTF_8).length).append("\r\n");
response.append("\r\n");
response.append(data);
try {
this.outputStream.write(response.toString().getBytes(StandardCharsets.UTF_8));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
创建一个用于接收请求的ServerSocket服务器
关键点:
- 通过创建对象的时候传递进来这个端口和IP,用于创建一个ServerSocket对象
- 循环接收socket = serverSocket.accept();
- 接收到了获取一个输入流,将输出流创建一个HttpRequest对象进行处理,得到访问路径uri
- 然后格局socket获取到输出流,通过创建一个HttpResponse对象进行处理,将静态资源返回到浏览器上面
MyHttpServer代码:
java
public class MyHttpServer {
private InetSocketAddress inetSocketAddress;
public static String WebContent =System.getProperty("user.dir")+ File.separator+"Webcontent";
public MyHttpServer(InetSocketAddress inetSocketAddress) {
this.inetSocketAddress = inetSocketAddress;
}
public void start() {
// 创建一个ServerSocket来接收请求
InputStream inputStream = null;
OutputStream outputStream =null;
Socket socket = null;
try {
ServerSocket serverSocket = new ServerSocket(inetSocketAddress.getPort(), 1, inetSocketAddress.getAddress());
while (true){
System.out.println("等待接收客户端请求...");
socket = serverSocket.accept();
// 将这个输入流传递给HttpRequest,处理请求
inputStream = socket.getInputStream();
HttpRequest httpRequest = new HttpRequest(inputStream);
httpRequest.parse();
// 将这个输出流传递给HttpResponse,处理响应
outputStream = socket.getOutputStream();
HttpResponse httpResponse = new HttpResponse(outputStream, "<h1>Hello World,这个是返回结果</h1>", 404);
httpResponse.sendStaticResource(httpRequest);
System.out.println("请求处理完毕");
}
} catch (IOException e) {
throw new RuntimeException(e);
}finally {
try {
inputStream.close();
outputStream.close();
socket.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}