2.1 Web Server
Web Server也叫网页服务器,作用是发布资源,并提供对外的服务,所以也叫中间件,它只能对特定的磁盘内容进行发布,可以发布静态资源(例如html)和动态资源(例如应用程序)
2.2 JAVA EE
JAVA EE是一堆技术的总称,提供了一些难题的解决方案,只是方案,没有实现,也就是说是一堆接口
- Servlet:Server Applet,就是服务端上的小程序,用于动态的生成页面
- JDBC:用于操作数据库
- JSP:用于方便的编写页面代码
- JTA:用于解决事务控制的方案
- EJB:和SPRING是基本相似的,一直在比较着进步,EJB国内一般没人用。
- RMI:调用远程设备上的程序
2.3 Web Server分类
根据对JAVA EE支持的程度分为两大类,因为sun只提供了接口,真正实现webserver本身
- JAVA EE服务器:把除了JDBC以外的javaEE功能都实现了,JDBC由数据库厂商实现
- Weblogic
- JBoss
- geronimo
- websphere
- Web容器:只实现了servlet和jsp
- Tomcat
- jetty
2.4 Tomcat安装
- exe文件:但是只是解压,没有任何添加
- rar文件:尽量不要存放在含有中文的目录下
- 配置环境变量:
- CATALINA_HOME:E:\Program Files\apache-tomcat-7.0.100
- JAVA_HOME:E:\Program Files (x86)\Java\jdk1.8.0_221\bin
- JRE_HOME:E:\Program Files (x86)\Java\jre1.8.0_221
2.5 Tomcat目录结构
- bin:存放启动关闭脚本
- startup.bat:
- 启动脚本,启动后浏览器输入http://localhost:8080,可以看到页面
- 右上角关闭时,不一定每次都能正确关闭,再次启动可能会失败,需要人为杀掉虚拟机进程java.exe
- shutdown.bat:关闭脚本
- startup.bat:
- conf:存放配置文件
- lib:存放Tomcat所依赖的jar包
- logs:存放日志,catalina.log为控制台日志
- temp:临时的数据文件,里面东西可以删,文件夹不能删
- webapps:存放web应用,里面就是想对外发布的资源
- ROOT:输入url和端口号,但是没有输入uri(具体资源)时,默认进到ROOT打开index.jsp
- work:存放JSP被编译成的.class文件的存放位置。例:ROOT下的index.jsp被编译成index_jsp.class后存放于work\Catalina\localhost_\org\apache\jsp中
2.6 server.xml配置文件详解
<?xml version="1.0" encoding="UTF-8"?>
<!--根节点为Server,其实就是启了一个ServerSocket,一个Server就是是一个ServerSocket的实例,这个ServerSocket用于监听8005端口,用于接收shutdown命令关闭tomcat -->
<Server port="8005" shutdown="SHUTDOWN">
<Listener className="org.apache.catalina.startup.VersionLoggerListener" />
<Listener SSLEngine="on"
className="org.apache.catalina.core.AprLifecycleListener" />
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
<GlobalNamingResources>
<Resource auth="Container" description="User database that can be updated and saved"
factory="org.apache.catalina.users.MemoryUserDatabaseFactory" name="UserDatabase"
pathname="conf/tomcat-users.xml" type="org.apache.catalina.UserDatabase" />
</GlobalNamingResources>
<!--Service表示能够处理请求的一个服务 -->
<Service name="Catalina">
<!--Connector表示一个Service可以处理多种请求,tomcat启动后会先启动server,再启动service, 再启动多个Connector,用于监听不同的端口 -->
<!--此处表示tomcat启动8080端口,只用于处理http协议的请求, 超时时间为20000ms,即连接请求等待超过这个时间,没有被处理的请求,返回超时 -->
<!-- 如果为https协议, 转发到端口8443,https为安全协议,会对请求的表单中加密,如果想使用https服务, 需要自己写证书(jdk/bin/keytool.exe可以生成证书) -->
<Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1"
redirectPort="8443" />
<!--AJP是一个不是很常用的协议 -->
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
<!--Engine处理Connector收到的请求,将请求发给Host进行处理,先将uri中的主机地址与所有Host挨个匹配,如果都匹配不到转发给名为localhost的Host进行处理 -->
<Engine defaultHost="localhost" name="Catalina">
<Realm className="org.apache.catalina.realm.LockOutRealm">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase" />
</Realm>
<Host appBase="webapps" autoDeploy="true" name="localhost"
unpackWARs="true">
<Valve className="org.apache.catalina.valves.AccessLogValve"
directory="logs" pattern="%h %l %u %t "%r" %s %b" prefix="localhost_access_log"
suffix=".txt" />
</Host>
<!--可以新加一个Host这样可以当访问本机ip时,如果使用不同的域名,会访问不同的资源,这种配置方法也叫配置虚拟主机, 一个Host就是一个虚拟的主机 -->
<!--例如:zhidao.baidu.com和baidu.com其实都是同样的ip只不过域名不同 -->
<!--系统解析域名时会先访问文件C:\Windows\System32\drivers\etc\hosts,如果没有对应的域名解析,才会去DNS服务器找,为了不让DNS服务器解析我们的域名,
修改hosts文件 -->
<!--在tomcat根目录下创建ceshi文件夹,这个文件夹下也必须再创建个文件夹,例wsh,里面放入你的资源例index.html,此时可以通过浏览器输入http://www.wsh.com:8080/wsh/index.html访问该资源 -->
<Host name="www.wsh.com" appBase="ceshi" unpackWARs="true"
autoDeploy="true" />
</Engine>
</Service>
</Server>
2.7 tomcat项目部署
2.7.1 部署的方式
- 静态部署:tomcat必须重启
- 动态部署:tomcat无需重启
2.7.2 三种静态部署方式
- 直接往webapps放资源
- 修改server.xml:这样部署允许你使用webapps以外的磁盘资源
<!--重启tomcat后,在浏览器上输入http://localhost:8080/hello/index.html进行访问-->
<Host appBase="webapps" autoDeploy="true" name="localhost"
unpackWARs="true">
<!--即在Host中加入Context节点,注意path后必须有"/", 否则报错-->
<!--下面配置相当于建立了一个目录的映射,如果浏览器中访问/hello那么意味着访问服务器上的"D:/workspace"-->
<Context path="/hello" docBase="D:/workspace" debug="0"
privileged="true"></Context>
<Valve className="org.apache.catalina.valves.AccessLogValve"
directory="logs" pattern="%h %l %u %t "%r" %s %b" prefix="localhost_access_log"
suffix=".txt" />
</Host>
- conf\Catalina\localhost下建立hello.xml:也允许将资源放在webapps外部
<!--重启tomcat后,在浏览器上输入http://localhost:8080/hello/index.html进行访问-->
<?xml version="1.0" encoding="UTF-8"?>
<Context path="/hello" docBase="D:/workspace" debug="0"
privileged="true"></Context>
2.7.3 动态部署:必须在tomcat管理界面完成
- 配置密码:修改D:\apache-tomcat-7.0.81\conf\tomcat-users.xml
<?xml version='1.0' encoding='utf-8'?>
<tomcat-users>
<!--role标签标示开启决策,以下为各决策权限-->
<!--
manager-gui - allows access to the HTML GUI and the status pages
manager-script - allows access to the text interface and the status pages
manager-jmx - allows access to the JMX proxy and the status pages
manager-status - allows access to the status pages only
-->
<role rolename="manager-gui" />
<role rolename="manager-script" />
<!--user标签标示建立用户分配角色-->
<user username="tomcat" password="tomcat" roles="manager-gui,manager-script" />
</tomcat-users>
- 进入管理界面:
http://localhost:8080
- Manager App
- 填写页面内容:其实就是修改配置文件,增加Context
- ontext Path (required):/oldlu
- WAR or Directory URL:D:\oldlu
- 点击deploy
- 通过浏览器访问D:\oldlu下的1.html
http://localhost:8080/oldlu/1.html
2.8 手动实现Tomcat
- Tomcat处理流程
- MyRequest:用于接收HTTP请求,并转为MyRequest对象
import java.io.IOException;
import java.io.InputStream;
public class MyRequest {
private String requestMethod;
private String requestUrl;
public MyRequest(InputStream inputStream) throws IOException {
byte[] buffer = new byte[1024];
int len = 0;
String str = null;
if((len=inputStream.read(buffer))>0){
str = new String(buffer,0,length);
}
// GET / HTTP/1.1
String data = str.split("\n")[0];
String[] params = data.split(" ");
this.requestMethod = params[0];
this.requestUrl = params[1];
}
public String getRequestMethod() {
return requestMethod;
}
public void setRequestMethod(String requestMethod) {
this.requestMethod = requestMethod;
}
public String getRequestUrl() {
return requestUrl;
}
public void setRequestUrl(String requestUrl) {
this.requestUrl = requestUrl;
}
}
- MyResponse:用于返回HTTP响应
import java.io.IOException;
import java.io.OutputStream;
public class MyResponse {
private OutputStream outputStream;
public MyResponse(OutputStream outputStream) {
this.outputStream = outputStream;
}
//用于返回响应给浏览器
public void write(String str) throws IOException {
StringBuilder builder = new StringBuilder();
builder.append("HTTP/1.1 200 OK\n")
.append("Content-Type:text/html\n")
.append("\r\n")
.append("<html>")
.append("<body>")
.append("<h1>"+str+"</h1>")
.append("</body>")
.append("</html>");
this.outputStream.write(builder.toString().getBytes());
this.outputStream.flush();
this.outputStream.close();
}
}
- MyMapping:配置uri与Servlet映射关系
import java.util.HashMap;
public class MyMapping {
public static HashMap<String,String> mapping = new HashMap<String,String>();
static{
mapping.put("/mytomcat","MyServlet");
}
public HashMap<String,String> getMapping(){
return mapping;
}
}
- MyHttpServlet:接口或抽象类,这样就可以利用多态,调用不同Servlet时,doGet有不同的实现。service方法判断调用哪个请求方法
import java.io.IOException;
public abstract class MyHttpServlet {
public static final String METHOD_GET = "GET";
public static final String METHOD_POST = "GET";
public abstract void doGet(MyRequest request, MyResponse response) throws IOException;
public abstract void doPost(MyRequest request, MyResponse response) throws IOException;
public void service(MyRequest request, MyResponse response) throws IOException {
if (METHOD_GET.equals(request.getRequestMethod())) {
doGet(request, response);
} else if (METHOD_POST.equals(request.getRequestMethod())) {
doPost(request, response);
}
}
}
- MyServlet:具体的请求方法的实现
import java.io.IOException;
public class MyServlet extends MyHttpServlet{
@Override
public void doGet(MyRequest request, MyResponse response) throws IOException {
response.write("get tomcat");
}
@Override
public void doPost(MyRequest request, MyResponse response) throws IOException {
response.write("post tomcat");
}
}
- MyServer:建立长连接,接收请求后分派给指定的Servlet
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class MyServer {
public static void startServer(int port) throws IOException, ClassNotFoundException, IllegalAccessException, InstantiationException {
ServerSocket ss = new ServerSocket(port);
while (true) {
Socket s = ss.accept();
MyRequest request = new MyRequest(s.getInputStream());
MyResponse response = new MyResponse(s.getOutputStream());
String clazz = new MyMapping().getMapping().get(request.getRequestUrl());
if (clazz != null) {
Class<MyHttpServlet> myHttpServletClass = (Class<MyHttpServlet>) Class.forName(clazz);
MyHttpServlet myHttpServlet = myHttpServletClass.newInstance();
myHttpServlet.service(request, response);
}
}
}
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, IOException {
startServer(8080);
}
}