首先上一个简单的模拟服务器端的代码:
WebServer:
/**
* Created by IntelliJ IDEA.
* User: Administrator
* Date: 2019/11/18
* Time: 15:21
*/
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 1.服务器需要监听某一端口号
* 2.当请求到达对应端口号时,解析出所请求内容
* 3.在当前服务器上面搜寻对应的资源,作出响应(200,404)
*/
public class WebServer {
public static void main(String[] args) {
//监听8080端口号
try {
// 监听端口--->8080
ServerSocket serverSocket = new ServerSocket(8080);
while (true){
Socket socket = serverSocket.accept();
//请求报文就在输入流中
//在建立好的连接中,通过在服务器端的Socket对象中,获取流,来进行数据传输
//输入流中的数据其实就是请求报文
InputStream inputStream = socket.getInputStream();
//如果要发送数据,那么就从Socket对象中获取,输出流
OutputStream outputStream = socket.getOutputStream();
//将请求报文封装到request对象中
Request request = new Request(inputStream);
//url代表客户端需要请求的资源
String url = request.getRequestURL();
System.out.println(url);
//利用response对象进行响应
Response response = new Response(url,outputStream);
//作出响应
response.response();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
request:
import java.io.IOException;
import java.io.InputStream;
public class Request {
private InputStream inputStream;
public Request(InputStream inputStream) {
this.inputStream = inputStream;
}
/**
* 获取请求的资源名称
* @return
*/
//请求方式:GET url第三部分:/1.html 协议:HTTP/1.1
// GET /1.html HTTP/1.1
// Host: localhost:8080
// Connection: keep-alive
// Cache-Control: max-age=0
// Upgrade-Insecure-Requests: 1
// User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36
// Sec-Fetch-User: ?1
// Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
// Sec-Fetch-Site: none
// Sec-Fetch-Mode: navigate
// Accept-Encoding: gzip, deflate, br
// Accept-Language: zh-CN,zh;q=0.9
//Cookie是因为之前访问过8080
// Cookie: Idea-83cde6a5=014bf777-5194-49e4-923c-2f4a24d6bff9
public String getRequestURL() throws IOException {
// 创建一个数组
byte[] bytes = new byte[2048];
//写入到byte数组中的长度
StringBuffer stringBuffer = new StringBuffer();
int read = inputStream.read(bytes);
for (int i = 0; i < read; i++) {
stringBuffer.append((char) bytes[i]);
}
//完整的请求报文
//content是端口号8080监听到的字符串形式的输入流
String content = stringBuffer.toString();
System.out.println("----------------------------------------------");
//可以在浏览器中访问http://localhost:8080/src/1.html
//就能监听到浏览器发来的信息
System.out.println(content);
System.out.println("----------------------------------------------");
if(content != null && !"".equals(content)){
return getFileName(content);
}
return null;
}
/**
* 从请求报文中获取访问的资源名称请求行:请求方法 请求资源 版本
* @param content
*/
private String getFileName(String content) {
// System.out.println(content);
//找到第一个空格所在的位置
int a = content.indexOf(' ');
//第二个空格所在的位置
int b = content.indexOf(' ',a + 1);
//注意一点,里面很可能包含请求参数,去掉
String fileName = content.substring(a + 2, b);
int i = fileName.indexOf('?');
if(i != -1){
//存在参数,需要截取
return fileName.substring(0,i);
}
return fileName;
}
}
response:
import java.io.*;
public class Response {
private String url;
private OutputStream outputStream;
public Response(String url, OutputStream outputStream) {
this.url = url;
this.outputStream = outputStream;
}
public void response() throws IOException {
//io流
if (url != null) {
System.out.println(url);
File file = new File(url);
StringBuffer stringBuffer = new StringBuffer();
if (file.exists() && file.isFile()) {
//200 构建响应报文
//构建响应消息头, stringBuffer里是响应行和消息头
stringBuffer.append("HTTP/1.1 200 OK \r\n");
stringBuffer.append("Content-Type:text/html;charset=utf-8 \r\n");
stringBuffer.append("\r\n");
FileInputStream fileInputStream = new FileInputStream(file);
byte[] bytes = new byte[1024];
int length = 0;
//我们要让输出流写回给浏览器一个响应报文
outputStream.write(stringBuffer.toString().getBytes("utf-8"));
//构建响应正文,file是正文
while ((length = fileInputStream.read(bytes)) != -1) {
outputStream.write(bytes, 0, length);
}
System.out.println(bytes.toString());
return;
}
//如果文件不存在,就构建一个404状态的响应报文
stringBuffer.append("HTTP/1.1 404 Not Found \r\n");
stringBuffer.append("Content-Type:text/html;charset=utf-8 \r\n");
stringBuffer.append("\r\n");
stringBuffer.append("<h1>File Not Found 404!</h1>");
outputStream.write(stringBuffer.toString().getBytes("utf-8"));
// 404
}
}
}
E:\WangDao\Vue_project\Socket这个项目的缺点:
1.效率低。WebServer通过while(true)循环一直在监听端口8080。
2.得一直运行这个项目才有对象存在。资源利用率太低。
1Tomcat
E:\WangDao\Vue_project\Socket这个项目的缺点:
1.效率低。WebServer通过while(true)循环一直在监听端口8080。
2.得一直运行这个项目才有对象存在。资源利用率太低。
1.1服务器
服务器至少需要干什么事情:
1.监听端口
2.分析请求报文
3.构建响应报文
承载java对象
WEB服务器开发(服务器)的相关知识
WEB,在英语中web即表示网页的意思,它用于表示Internet SERVER 上供外界访问的资源。
Internet上供外界访问的Web资源分为:
静态web资源(如html 页面):指web页面中供人们浏览的数据始终是不变。
动态web资源:指web页面中供人们浏览的数据是由程序产生的,不同时间点访问web页面看到的内容各不相同。
静态web资源开发技术
Html css javascript ? 图片 音频 视频
常用动态web资源开发技术:
JSP/Servlet、ASP、PHP 等 node.js
在Java中,动态web资源开发技术统称为Javaweb,我们课程的重点也是教大家如何使用Java技术开发动态的web资源,即动态web页面。(我们关注点:后台怎么处理请求提供数据)
JavaWEB应用程序
WEB应用程序指供浏览器访问的程序,通常也简称为web应用。
一个web应用由多个静态web资源和动态web资源组成,如:
html、css、js文件
Jsp文件、java程序、支持jar包、
配置文件
……
Web应用开发好后,若想供外界访问,需要把web应用所在目录交给web服务器管理,这个过程称之为虚似目录的映射,应用在webapps目录下无需映射。
1.2现成服务器
Javaee: 企业级开发:
包括13块内容: ejb、 jdbc、 jndi,、rmi、xml、Servlet, jsp等。
Javaee最主要关注的是Servlet, jsp
Tomcat简介
Tomcat是在SUN公司推出的小型Servlet/JSP调试工具的基础上发展起来的一个优秀的Servlet容器,Tomcat本身完全用Java语言编写。目前是Apache开源软件组织的一个软件项目,它的官方网址为http://tomcat.apache.org。得到了广大开源代码志愿者的大力支持,且可以和目前大部分的主流Web服务器(Apache服务器)一起工作,它运行稳定、可靠且高效。已成为目前开发企业JavaWeb应用的最佳Servlet容器选择之一。
我们后面的Java Web学习都是基于Tomcat服务器的。
1.3安装tomcat
推荐下载Tomcat8或Tomcat9
避免中文路径
有时候并不是直接安装就能用的?
要有(环境变量): JAVA_HOME
命令行:判断JAVA_HOME在不在
E:JDK表示JAVA_HOME在我的电脑上代表的路径。
1.4Tomcat使用
是用来部署服务器的: 主要用来部署java程序
开启:startup.bat
关闭:shutdown.bat
用命令行的话:
不过,Linux的命令是:./startup.bat和./shutdown.bat
Tomcat部署vue项目:
1, 在vue项目里执行 npm run build --打包出一个dist文件(包含一个html 和多个css, js 文件)
2, 把dist里面的内容放到tomcat的webapps下的ROOT里, 启动Tomcat
注意1: 如果不是windows, 改配置:将/改成./
注意2: vue — nuxt(服务端渲染)
用vue写博客,想让别人搜到你,但是没法儿搜到,因为vue项目打包后只是一个index.html文件,这个文件里没有你博客里的任何关键词。
但有一个基于vue的框架:nuxt,别人访问你的东西,就是一个实实在在的页面,页面里是你写的东西。
注意3: 打包方式 npm run build
注意4:
我们把vue项目打包-- webapps下的ROOT
如果你要用tomcat部署vue, 那么就放到root里,
如果你不想把打包好的文件放到root中,就得改webpack的配置并重新打包。最好不要这么做。最好还是放在root下。
发现:
1.利用npm run dev启动vue_homework项目,没有那么多js和css请求
2.而利用Tomcat访问vue_homework项目,会有很多js和css请求
为什么呢?
因为2是经过打包的,打包会对资源进行整理、压缩、合并,js样式、css样式,webpack帮我们自动合并整理了,形成js文件、css文件。
看一下dist目录:
Vue项目每次打包完都只有一个index.html文件和若干js、css文件,就算页面做的很复杂,也只有这些文件,为什么?
之前将Vue时,有这么一句话:Vue 完全有能力驱动采用单文件组件和Vue生态系统支持开发复杂单页应用。
单文件组件: 一个文件描述一个组件
单页应用: 经过打包生成一个单页的html文件和一些js、css文件
1.5Tomcat: 主要给java程序用的
实际上, 主要部署java war包 (java程序经过打包, 形成一个war包, 放到tomcat, 让tomcat运行)
所谓的让Tomcat运行war包, 本质的目的? 根据我们提供的war(代码) 创建出对应的对象。
之前讲前端服务器和后端服务器的功能有很大区别:
前端服务器:项目vue_homework放到Tomcat服务器中,此时的Tomcat就相当于一个前端服务器。浏览器发送请求,Tomcat封装并返回给浏览器打包后的项目vue_homework对应的文件,由浏览器来创建这些文件(代码)中对应的vue对象。
后端服务器:Tomcat中有一个war包,Tomcat根据war包生成一些java对象在Tomcat里面,当别人来访问了,Tomcat接受这些请求,把这些请求再转化给java对象,对这个对象进行一些逻辑上的操作,比如用这个对象调用数据库连接,访问数据等操作,做完这些操作后,将得到的结果通过Tomcat封装响应报文返回给浏览器。
比如JDBC,是根据代码生成的对象帮我们取数据库中取的数据。包括承载数据,class文件、java代码都没法儿承载数据,能承载数据的是根据代码生成的对象。
现在就更容易理解静态资源和动态资源了。
相当于一个是自动贩卖机,要了就直接给,一个是人工处理,要了别人就加工,做成后给你。
打包前浏览器访问服务器的流程:
打包后浏览器访问服务器的流程。
访问http://localhost:8081/的首页是这样的:
注意:这是首页的内容,当我们点击百度、淘宝后,右侧内容会变化,只有点击后,百度、淘宝所对应的的Vue对象才会挂载到DOM树上。并不是说浏览器拿到前端代码后,进行DOM解析,一下子把所有的Vue对象都挂载到DOM树上了。
有同学问为啥要打包,原因:
打包前的项目80M-200M,打包后的项目700k。
因为打包前的项目引用了很多包,因为开发项目需要各种功能,比如:热加载(改了前端代码,在浏览器中就能反应出来)。做了很多底层的工作,所以它很大。并且它还帮我们模拟了一个前端服务器。这些功能对我们开发者而言非常有用,但是开发好了后用户用的时候没有用。而且开发环境不稳定。
而打包后只需要导入很少的包,如下只导入vue和axios。而且并不是完全导入,只是抽出这两个包中的语法,转化成js文件了。打包后的文件放在服务器中,浏览器请求时,服务器返回dist目录下的文件给浏览器,浏览器解析。
"dependencies": {
"axios": "^0.19.2",
"vue": "^2.5.2"
},
"devDependencies": {
"autoprefixer": "^7.1.2",
"babel-core": "^6.22.1",
"babel-helper-vue-jsx-merge-props": "^2.0.3",
"babel-loader": "^7.1.1",
"babel-plugin-syntax-jsx": "^6.18.0",
"babel-plugin-transform-runtime": "^6.22.0",
"babel-plugin-transform-vue-jsx": "^3.5.0",
"babel-preset-env": "^1.3.2",
"babel-preset-stage-2": "^6.22.0",
"chalk": "^2.0.1",
"copy-webpack-plugin": "^4.0.1",
"css-loader": "^0.28.0",
"extract-text-webpack-plugin": "^3.0.0",
"file-loader": "^1.1.4",
"friendly-errors-webpack-plugin": "^1.6.1",
"html-webpack-plugin": "^2.30.1",
"node-notifier": "^5.1.2",
"optimize-css-assets-webpack-plugin": "^3.2.0",
"ora": "^1.2.0",
"portfinder": "^1.0.13",
"postcss-import": "^11.0.0",
"postcss-loader": "^2.0.8",
"postcss-url": "^7.2.1",
"rimraf": "^2.6.0",
"semver": "^5.3.0",
"shelljs": "^0.7.6",
"uglifyjs-webpack-plugin": "^1.1.1",
"url-loader": "^0.5.8",
"vue-loader": "^13.3.0",
"vue-style-loader": "^3.0.1",
"vue-template-compiler": "^2.5.2",
"webpack": "^3.6.0",
"webpack-bundle-analyzer": "^2.9.0",
"webpack-dev-server": "^2.9.1",
"webpack-merge": "^4.1.0"
},
现在我们想这样整:本机8080端口既可以处理前端业务又可以处理后端业务。
即:把前端项目放在D:\developmer_tools\apache-tomcat-7.0.78\webapps\ROOT目录下
把后端代码放在:D:\developmer_tools\apache-tomcat-7.0.78\webapps目录下
这依旧是前后端不分离的。只不过是让本机上的一个Tomcat服务器既当前端服务器,又当后端服务器。
1.6怎么通过Tomcat部署java包
1.6.1Maven
前端: 包,用webpack打包
后端: 包, jar 用maven打包
把war包放进D:\developmer_tools\apache-tomcat-7.0.78\webapps目录下(这就是部署),然后点击startup.bat运行,Tomcat会把war包解压成一个文件。
解压后的文件目录下有三个文件夹:
注意:
War的目录结构:
Metainf: maven的自动生成目录
WEB-INF: 项目内容目录(WEB-INF是和我们写的代码息息相关的一些东西。)
Web.xml: war包描述文件
Classes: java代码的class文件
Lib: 项目依赖的jar包
Index.jsp: 可选项 (首页)
别的文件: 可选
1.7Tomcat目录结构
Bin: binary: 二进制文件: 一些tomcat启动关闭相关的文件
Conf: tomcat配置文件
Lib: tomcat依赖的第三方包
Logs: 日志文件, tomcat的日志文件
Temp: 临时文件
Webapps: 服务应用/服务项目
Work: tomcat的工作目录
1.8Tomcat的组成结构
Tomcat本身由一系列可配置的组件构成,其中核心组件是Servlet容器组件,它是所有其他Tomcat组件的顶层容器。每个组件都可以在Tomcat安装目录/conf/server.xml文件中进行配置,每个Tomcat组件在server.xml文件中对应一种配置元素。以下用XML的形式展示了各种Tomcat组件之间的关系
Server: 表示整个tomcat, 控制tomcat开启和关闭, 包含多个service
Service: 表示一个具体的服务, 对外的服务(暴露出端口号).
一个服务包含两部分:
Connector: 监听端口, 监听到请求之后, 封装request, response报文
,交给container处理
Container: (一个服务一个Container) 处理请求
具体表现就是一个engine
Engine: 具体处理请求, 要进一步交给host处理,一个engine可以包含多个host
Host: 站点, 虚拟主机,包含多个context
一个Tomcat就可以对应多个域名,因为一个域名对应一个host
Context: 具个的某个服务, 某个应用
Tomcat处理HTTP请求的过程localhost/test/index.jsp:
- 用户发送一个请求,被发送到当前机器的80端口号,被正在监听80端口号的coyote HTTP/1.1获得
- Connector组件将收到的请求传递给Engine组件
- Engine获得了请求地址为localhost/test/index.jsp,匹配虚拟主机
- 匹配到名为localhost的host,如果没匹配到,也将请求交给它处理,它被定义为Engine的默认虚拟主机,该host获得/test/index.jsp,匹配它所拥有的全部Context
- 匹配/test应用名对应的Context节点,Context节点获得index.jsp,它再去寻找响应的servlet
- Servlet处理完逻辑
- Context节点把执行完的结果返回给Host
- Host将结果返回给Engine
- Engine将结果返回给Connector组件
- Connector将最终的响应结果返回给客户端
1.9配置虚拟主机host
假如我们真的一个电脑申请了两个域名:localhost和localhost1,这样就可以通过访问http://localhost:8080/和http://localhost:8080/进入不同的虚拟主机host。
appBase表示默认访问路径。
但实际上我们只有http://localhost:8080/这个域名
注:http://localhost:8080/和http://localhost:8080/端口号不一定要一样,端口号是有Connector监听的,监听到请求交给Engine处理,所以一个Engine下只能有一个端口。但我们完全可以在一个Server下配置多个Service,让一个service监听8080,另一个service监听8099这样。
1.10虚拟目录映射
假如我不把项目放在D:\developmer_tools\apache-tomcat-7.0.78\webapps下,我就放在桌面,怎么让Tomcat帮我启动它呢?
Context: 具体的某个服务, 某个应用
所以按道理来讲,应该配置Context,配置完后一定要重启Tomcat。
1.10.1第一种: conf下server.xml之中host节点下面
Path是虚拟目录名称,docBase是Web应用所在目录。
1.10.2第二种: conf:
到目录:D:\developmer_tools\apache-tomcat-7.0.78\conf\Catalina\localhost下
创建一个xml, 给用户使用的应用名, 就是xml的文件名
在Tomcat6中,不再建议在server.xml文件中配置context元素,细节查看tomcat服务器关于context元素的说明。
让tomcat自动映射: tomcat服务器会自动管理webapps目录下的所有web应用,并把它映射成虚似目录。换句话说,tomcat服务器webapps目录中的web应用,外界可以直接访问。
Context元素的属性
Tomcat提供了多种配置元素的途径。当其加载一个web应用时,会:
1)到Tomcat安装目录/conf/[enginename]/[hostname]/[contextpath].xml文件中查找元素。
2) 到Tomcat安装目录/conf/server.xml文件中查找元素。只适用于单个Web应用
[contextpath]:表示单个Web应用的URL入口。如果修改为ROOT,则该应用就是默认访问的应用。
Note:若想让程序成为默认的Web应用,即访问http://localhost:8080时自动登录到Web应用的主页,可以在此处增加名字为ROOT.xml文件,其元素的path属性应该为””
1.11默认端口和页面
我们的电脑., 如果一个请求进来, 它没有带端口, 我们的电脑自动的把这个请求, 交给80端口处理
我们可以让tomcat直接监听80端口, 那么所有不带端口的请求, 都会触发到我们的tomcat中去
那么访问http://localhost就好了
1.11.1默认页面
默认加载index.html,你可以改成aaa.html
就算写两个默认页面也是从上往下解析,所以这样设置默认解析的还是index.html
web.xml文件
通过web.xml文件,可以将web应用中的:
某个web资源配置为网站首页
<welcome-file-list>
<welcome-file>hello.html</welcome-file>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
将servlet程序映射到某个url地址上
……
但凡涉及到对web资源进行配置,都需要通过web.xml文件
举例:通过web.xml文件配置网站首页。
注意:web.xml文件必须放在web应用\WEB-INF目录下。
1.12WEB开发的前景
软件开发的两种架构:c/s 和 b/s
cs,如电脑桌面上的腾讯视频
Bs:如访问网站
随着网络带宽的不断提升,云计算概念的提出,浏览器只要足够强大,c/s架构立马就会被淘汰,不仅c/s架构会被淘汰,软件最终都会消失、操作系统都可以没有,最终将会是b/s架构的天下,也就是浏览器+搜索引擎的天下。所有现在桌面软件提供的功能,最后都由网站提供,也就是说,将来打开电脑就是一个浏览器,想要什么服务,通过搜索引擎一找,就可以在网上找到相应的服务,用就是了。所以web开发人员是现在最流行的岗位。
2重点
1, 安装和启动tomcat,
2, 部署java的war 包(放到webApps下,启动Tomcat)
3, 熟悉tomcat组成结构
4, 熟悉虚拟映射
3作业:
在浏览器上
http://localhost
就能返回一个页面
把项目放到D:\developmer_tools\apache-tomcat-7.0.78\webapps\ROOT目录下,更改D:\developmer_tools\apache-tomcat-7.0.78\conf目录下的server.xml文件:
<Connector connectionTimeout="20000" port="80" protocol="HTTP/1.1" redirectPort="8443"/>