目录
Tomcat服务器
Tomcat是HTTP的服务器,用于接收HTTP 请求,分析请求得出响应,然后将响应返回给浏览器
Tomcat的安装目录
/webapps目录内,存放Tomcat服务器内的所有web程序,其内的Root目录是默认的web应用程序,默认访问应用程序使用的URL为http://127.0.0.1:8080
配置Tomcat的服务端口
启动Tomcat
双击bin目录下的startup
出现这个表示成功启动,乱码原因:Tomcat使用UTF-8编码,而windows使用GBK
浏览器输入http://127.0.0.1:8080/,就可以看到Tomcat的欢迎界面
静态文档和动态文档
静态文档指的是在用户浏览的过程中,web呈现的页面不会有任何的改变,是固定死的;而动态文档是可以动态生成的
部署静态文档
浏览器输入http://127.0.0.1:8080/hello.html,就可以在浏览器查看这个文件
理论上其他用户就可以访问这个网址,看到这个界面;但是当前我们自己的IP是私有IP地址,不可以在网络上传播,需要借助外网IP
这就要使用到我们Tomcat提供的API,也即是servlet
servlet
maven
Maven 是一个项目管理工具,可以对 Java 项目进行自动化的构建和依赖管理;我们的代码要依赖很多第三方库,Maven可以帮助我们自动管理依赖
使用idea创建maven项目
例如配置MysqL的相关依赖,打开https://mvnrepository.com/,maven中央仓库,选择MysqL的版本,复制maven内容
拷贝maven的内容到pom.xml中
如果没有自动从中央仓库下载依赖,可以手动刷新,启动下载
servlet程序
Tomcat 作为服务器,负责接收客户请求,并做出响应
Tomcat把接收到的请求传送给Servlet,并将 Servlet 的响应传送回给客户;而Servlet是一种运行在支持Java语言的服务器上的组件
创建Servlet的流程
1、创建maven程序
2、引入servlet的依赖
Apache Tomcat® - Which Version Do I Want?
根据Tomcat的版本,从maven中央仓库选择对应servlet的版本,拷贝maven内容到代码中,idea从中央仓库下载依赖
3、 创建目录结构
我们需要在当前的目录结构上新增些结构
web.xml中拷贝以下内容
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<display-name> Archetype Created Web Application</display-name>
</web-app>
4、编写servlet代码
@WebServlet("/hi")//当url路径包含hi目录时,才会触发这个类
public class Hello extends HttpServlet {
//继承HttpServlet类,这个类包含的方法之一就是doGet(),表示服务器在接收到Get请求之后,执行的操作
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws servletexception, IOException {
//HttpServletRequest:请求类 HttpServletResponse:响应类
//Tomcat服务器的控制台的内容
System.out.println("服务器hello");
//2、当服务器接收到请求之后,做出的响应
resp.getWriter().write("hello");
}
}
5、打包,将这个maven程序打包,部署到Tomcat服务器上
在pom.xml中做如下修改
<!-- 将程序打包为war包-->
<packaging>war</packaging>
<!-- 程序打包之后的名称-->
<build>
<finalName>
hellotest
</finalName>
</build>
打包支持war包和jar包,war包可以说是服务于Tomcat的,不仅包含.class文件,还包含css,js和其他配置文件;而jar包 包含.class文件
双击maven操作界面的packet,进行打包
6、将包部署到Tomcat服务器上
将war包拷贝到Tomcat服务器上的webapps目录里
启动Tomcat服务器
7、检验是否成功
URL包含两级路径,输入http://127.0.0.1:8080/hellotest/hi
页面呈现
这里的第一级路径(context path)是"/hellotest",就是打包时,pom.xml中的名称
第二级目录(Servlet path)是"/hi",就是java中的@WebServlet("/hi")语句指定的路径,这个语句将URL中的/hi目录和java类关联,只要发送的请求包含/hi目录,才会被这个类接收请求,从而发送响应
Smart Tomcat
idea的一个插件,实现将maven程序自动打包并配置到Tomcat服务器中。(不是真的会打一个war
包,拷贝到webapps目录内,smart Tomcat简化这个过程,直接让Tomcat服务器从指定路径访问了程序,实现了逻辑上的配置)
Servlet的常见错误
1、404:表示资源不存在
- 缺少第一级路径(context path)
我们以上重写的是doGet方法,也就是Get请求
一般执行Get请求的操作:
一般执行Post请求的操作:
- form表单或者ajex构造Post方法
@WebServlet("/hi")//当url路径包含hi目录时,才会触发这个类
public class Hello extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws servletexception, IOException {
//HttpServletRequest:请求类 HttpServletResponse:响应类
//Tomcat服务器的控制台的内容
System.out.println("服务器hello");
//2、当服务器接收到请求之后,做出的响应
resp.getWriter().write("hello");
}
}
当前是Post方法,我们直接输入http://localhost:8080/hello/hi,执行的是Get方法,方法不匹配
3、 500:服务器出现异常 String ret=null;
resp.getWriter().write(ret.length());
比如以上这种,空指针异常
4、无法访问此网站
Tomcat服务器启动问题
Servlet的API
servlet 3.0 API由以下4个包组成:
1、javax.servlet包:定义了开发独立于协议的服务器的小程序的接口和类
2、javax.servlet.Http包:定义了开发采用HTTP通信的服务器的小程序的接口和类
3、javax.servlet.annotation包:定义了9个注解类型和两个枚举类型
4、javax.servlet.descriptor包:定义了以编程方式访问Web英语程序配置信息的类型
javax.servlet包
这个包定义了独立于任何协议的一般Servlet接口和类
狭义的Servlet是指Java语言实现的一个接口,广义的Servlet是指任何实现了这个Servlet接口的类,一般情况下,人们将Servlet理解为后者
接口 | 说明 |
Servlet | 所有Servlet的根接口 |
ServletRequest | 客户请求的接口 |
ServletRespons | 服务器响应的接口 |
servletcontextlistener | 监听web应用程序的监听器接口 |
ServletContextAttributedListener | 监听web应用程序属性的监听器接口 |
Requestdispatcher | 将请求转发给其他资源 |
ServletConfig | Servlet类使用的过滤器配置对象 |
常用的类和接口:
1、Servlet 接口:Servlet API中的核心接口,每一个Servlet 程序必须直接或者间接的使用这个接口
我们介绍它的3个方法:
- init(ServletConfig config):这个方法由Tomcat调用,完成Servlet 初始化并且提供服务
- service(HttpServletRequest req, HttpServletResponse resp) throws servletexception, IOException ):对每一个用户请求,Tomcat调用这个方法,Tomcat允许Servlet 程序为请求提供响应,而计算响应的逻辑就是service()方法实现的
- destory():这个方法由Tomcat调用,指示Servlet 程序清除本身,释放的资源并准备结束服务
2、ServletConfig 接口:为用户提供了Servlet 的配置信息
3、GenericServlet 类: 这个抽象类实现了ServletConfig 接口和Servlet接口,提供了Servlet接口中处理 service()外的所有方法,同时也增加了几个日志操作的方法,可以提供扩展这个类并实现 service()方法来创建任何类型的 servlet
javax.servlet.Http包
介绍几个重要的类和接口
1、HttpServlet 类
这个抽象类用于实现针对 HTTP协议 的servlet,扩展了GenericServlet类,实现了service ()方法,而service()是用来处理客户请求的
protected void service(HttpServletRequest req, HttpServletResponse resp) throws servletexception, IOException { super.service(req, resp); }
查看service()方法的源码,这个方法可以处理GET,POST,PUT等请求,根据方法名执行对应的doXXX方法
protected void service(HttpServletRequest req, HttpServletResponse resp) throws servletexception, IOException {
String method = req.getmethod();
long lastModified;
if (method.equals("GET")) {
lastModified = this.getLastModified(req);
if (lastModified == -1L) {
this.doGet(req, resp);
} else {
long ifModifiedSince = req.getDateHeader("If-Modified-Since");
if (ifModifiedSince < lastModified) {
this.maybeSetLastModified(resp, lastModified);
this.doGet(req, resp);
} else {
resp.setStatus(304);
}
}
} else if (method.equals("HEAD")) {
lastModified = this.getLastModified(req);
this.maybeSetLastModified(resp, lastModified);
this.doHead(req, resp);
} else if (method.equals("POST")) {
this.doPost(req, resp);
} else if (method.equals("PUT")) {
this.doPut(req, resp);
} else if (method.equals("DELETE")) {
this.doDelete(req, resp);
} else if (method.equals("OPTIONS")) {
this.doOptions(req, resp);
} else if (method.equals("TRACE")) {
this.doTrace(req, resp);
} else {
String errMsg = lStrings.getString("http.method_not_implemented");
Object[] errArgs = new Object[]{method};
errMsg = messageformat.format(errMsg, errArgs);
resp.sendError(501, errMsg);
}
}
HttpServlet类是抽象类,可以通过继承这个类,重写service()方法,它会自动判断请求类型,从而调用对应方法,但是根据请求计算响应,逻辑还是doGet()方法等实现
所以我们直接重写doGet()方法处理GET请求,重写doPost()方法,处理Post请求
@WebServlet("/ok")//当url中第二级路径是/ok,才会触发到这个类,才可以处理请求
public class ServletAPI extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws servletexception, IOException {
//重写doGet方法,用于处理HTTP协议的GET请求
//1、接收请求
//2、根据请求计算响应
int a =10;
//3、将响应返回给服务器
resp.getWriter().write(a+"ok");
}
}
这里看似是ServletAPI类扩展了HttpServlet类,实际上是 ServletAPI类 实现了Servlet接口,(因为HttpServlet这个抽象类继承自GenericServlet 类,GenericServlet类实现了ServletConfig 接口和Servlet接口)
所以是:ServletAPI类实现了Servlet接口,重写了doGet()方法
Tomcat将请求传递给ServletAPI类,Tomcat调用Servlet接口的service()方法,service()方法内部调用doGet()方法,调用的是ServletAPI 类重写的doGet()方法,就涉及到了多态
2、HttpServeltRequest接口
扩展了ServletRequest接口,并提供了一些方法获取到HTTP请求的内容
3、HttpServeltResponse接口
扩展了ServletResponse接口,并提供了一些方法针对HTTP协议返回响应
Servlet的生命周期
Servlet作为一个在容器中运行的组件,有一个创建到销毁的过程,这个过程被称作Servlet的生命周期
Tomcat的运行过程
接收请求
1、Tomcat初始化
Tomcat会在指定的目录中找到要加载资源的 servlet
2、Tomcat部署的是war包,存入的是.class文件和其他的css,js等文件,那么对于.class文件,就需要根据反射机制为需要使用的类创建实例化对象,这个对象本质上实现了Servlet 这个根接口
3、对于servlet 接口的实例,Tomcat要调用 servlet 接口的init()方法,完成类的初始化并准备提供服务
4、如果是启动HTTP的服务器,那么Tomcat创建TCP 的socket,监听8080端口,等待客户端连接;这个等待接收的过程,是基于多线程实现的
5、如果以上监听8080端口的环节正常结束,那么会给每一个servlet实例调用destory()方法,关闭相关资源;这里的正常结束,比如被别的线程结束,但是如果直接关闭了Tomcat,就可能来不及调用destory()
处理请求
1、根据socket对象的信息(字符串),构造基于HTTP协议的请求,并创建一个空的HTTP响应
2、根据HTTP请求中的信息,找到URL,也即是所请求访问资源的地址
如果这个地址在我们电脑存在,那么表示请求访问的资源是静态资源,直接将对应内容输出即可;
否则,对应的就是动态页面;Tomcat调用Servlet 接口 的service()方法,service()方法执行被重写的doXXX()方法,产生响应。涉及到了多态
Servlet的生命周期
我们将一个Servlet 类的实例,经历init(),service(),destory()三个状态的时间,称之为 Servlet的生命周期;对于一个类,init()仅且执行多次,service()可能执行多次,destory()最多执行一次(可能被异常关闭)
HttpServlet 类的使用
一个servlet 程序也可以部署静态文件,放在webapp目录即可
浏览器使用Tomcat加载demo.html这个静态页面,然后这个静态页面发送Post请求,被服务器接收,做出响应
出现上述的乱码,是因为编码方式的问题
idea默认使用UTF-8编码,windows默认使用GBK编码,需要统一编码
就是设置header的content-type属性
@WebServlet("/method")
public class ServletText extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws servletexception, IOException {
resp.setContentType("text/html;charset=utf-8");//指定响应的格式
resp.getWriter().write("响应 ok");
}
}
HttpServletRequest类
@WebServlet("/request")
public class HttpServletRequestApi extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws servletexception, IOException {
StringBuilder builder = new StringBuilder();
builder.append(req.getProtocol());//返回请求所使用的协议名称和版本
builder.append('\n');
builder.append(req.getmethod());//返回请求使用的方法
builder.append('\n');
builder.append(req.getRequestURI());//获取请求的资源路径
builder.append('\n');
builder.append(req.getRequestURL().toString());//获取请求的统一资源定位符(绝对路径)
builder.append('\n');
builder.append(req.getcontextpath());//获取指示请求上下文的路径
builder.append('\n');
builder.append(req.getQueryString());//获取QueryString字段内容
builder.append('\n');
builder.append(req.getCharacterEncoding());//获取body的字符编码
builder.append("\n");
Enumeration<String> headerNames = req.getHeaderNames();//返回所有请求头的头名 也就是key
while (headerNames.hasMoreElements()) {
String des = headerNames.nextElement();//key
builder.append(des).append(" ");
builder.append(req.getHeader(des));//根据key值得到对应的value
builder.append('\n');
}
//读取body内容,返回一个字节流
ServletInputStream in = req.getInputStream();
int len = 0;
byte[] elem = new byte[1024];
while ((len = in.read(elem)) != -1) {
builder.append(new String(elem, 0, len, StandardCharsets.UTF_8));
}
resp.getWriter().write(builder.toString());
}
}
创建请求
运行结果
URI: 统一资源标识符。用来唯一标识资源,是一种语义上的抽象概念。
URL: 统一资源定位符。用来定位唯一的资源, 必须提供足够的定位信息。
URN: 统一资源名称。定义了资源的身份(命名)。
简单比喻 - URI唯一标识一个人(例如身份证), URL定义了如何访问到这个人(例如家庭地址),URN用名字标识一个人(假设所有人名字都不一样的情况下)
URL和URN都是URI的子集
post请求的数据格式:
body的数据组织形式Content-Type有三种:
1、application/x-www-form-urlencoded; 就是键值对的形式,和url的queryString格式相同;也是默认的格式userid=123&pass=908
2、application/json {userid:123,pass:908}
3、multipart/from-data:文件上传,下载的格式
对于json格式的body,可以使用第三方库:jackson来获取数据内容
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script >
//创建post请求 body部分设置为json格式
$.ajax({
type: 'post',
url:"jsontext",
contentType:'application/json',
data:JSON.stringify({ //将js数据的对象 转化为一个json格式的字符串
name:'123',password:'456'//这个是一个js对象
}),
success: function(body){
console.log(body);
}
});
抓包观察,body部分的数据格式
class type{
public int name;
public int password;
//属性名要匹配
}
@WebServlet("/jsontext")
public class json extends HttpServlet {
//1、创建jackson的对象
// ObjectMapper类是Jackson库的主要类。它提供一些功能将转换成Java对象匹配JSON结构
ObjectMapper objectMapper = new ObjectMapper();
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws servletexception, IOException {
//2、读取body内容,解析成为对应对象
type ret = objectMapper.readValue(req.getInputStream(), type.class);//转化为了Type对象
//根据type.class,也就是反射,json的name 和password,匹配到type的两个属性
resp.getWriter().write("name :" + ret.name + "password :" + ret.password);
}
}
@WebServlet("/QueryString")
public class QueryString extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws servletexception, IOException {
resp.setContentType("text/html;charset=utf-8");
String name= req.getParameter("name");
//获取参数的值,如果不存在返回null,也就是jqueryString中name=123,这里就返回123
String password= req.getParameter("password");
resp.getWriter().write("name: "+name+ " password: "+password);
//结果:name=123 password=456
}
}
HttpServletResponse类
@WebServlet("/demo")
public class read extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws servletexception, IOException {
resp.setHeader("Refresh", "1");//设置一个Header内的键值对,如果name已经存在,进行覆盖
//结果:每隔一秒,刷新页面
resp.getWriter().write("time"+ System.currentTimeMillis());//按照文本格式,将数据写回客户端
resp.setStatus(302);//设置状态码
resp.addHeader("location","https://www.sogou.com");//设置一个Header内的键值对,如果name已经存在,不进行覆盖
//结果:重定位
//重定位,可以简化
resp.sendRedirect("https://www.sogou.com");
}
}
原文地址:https://www.jb51.cc/wenti/3287190.html
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。