java从入门到精通二十三(Servlet)
Servlet 说明
首先我们需要了解浏览器访问服务器
我们这里还是以tomcat作为服务器参考对象。
①:Tomcat将http请求文本接收并解析,然后封装成HttpServletRequest类型的request对象,所有的HTTP头数据读可以通过request对象调用对应的方法查询到。
②:Tomcat同时会要响应的信息封装为HttpServletResponse类型的response对象,通过设置response属性就可以控制要输出到浏览器的内容,然后将response交给tomcat,tomcat就会将其变成响应文本的格式发送给浏览器
就那我么部署的项目来说。我们开启服务后。然后我们通过一段链接来访问我们的服务器然后得到响应数据。
http://localhost/login.html
localhost后面还有个80这里省略了。
我们可以根据localhost:80端口号找到tomcat服务器,然后后面的路径分别指定了访问项目路径和访问的内容。
我们在访问tomcat的时候会有一个默认的servlet数据处理。
我们也可以在web.xml查看内容。
我们没有创建Servlet类,里面的一些处理以及默认参数都是按照服务端默认数据进行,我们需要大致了解这些过程。
另外我们需要了解到如果我们在java中运用这个技术,就可以做出动态web开发。
Servlet初步入门尝试
我们运用maven在idea里面添加Servlet依赖坐标
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
然后我们创建一个类,来实现Servlet接口,并重写接口当中所有方法。
package jgd;
import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import java.io.IOException;
@WebServlet("/demo1")
public class ServletDemo01 implements Servlet {
public void init(ServletConfig servletConfig) throws ServletException {
}
public ServletConfig getServletConfig() {
return null;
}
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
//Servlet被访问的时候service会自动执行
System.out.println("servlet hello world");
}
public String getServletInfo() {
return null;
}
public void destroy() {
}
}
上面的注解说明了访问路径。
启动!
对的什么也没有,我们来看控制台。
我们执行后,service方法被调用了。
Servlet由web服务器创建,Servlet方法由web服务器调用
我们自定义的Servlet,必须实现Servlet接口并复写其方法,而Servlet接口中有service方法
ServletDemo1实现了Servlet接口,所以类中必然会重写service方法供Tomcat Web服务器进行调用
service方法中有ServletRequest和ServletResponse两个参数,ServletRequest封装的是请求数据,ServletResponse封装的是响应数据,后期我们可以通过这两个参数实现前后端的数据交互
Servlet生命周期
在Java中对象的生命周期指一个对象从被创建到被销毁的整个过程。
我们可以将Servlet大致划分为四个阶段
1:加载和实例化,我们的默认情况下,没有自己指定值的话,Servlet在被第一次被访问的时候,会由容器创建Servlet对象。
默认情况,Servlet会在第一次访问被容器创建,但是如果创建Servlet比较耗时的话,那么第一个访问的人等待的时间就比较长,用户的体验就比较差,那么我们能不能把Servlet的创建放到服务器启动的时候来创建,具体如何来配置
@WebServlet(urlPatterns = “/demo1”,loadOnStartup = 1)
loadOnstartup的取值有两类情况
(1)负整数:第一次访问时创建Servlet对象
(2)0或正整数:服务器启动时创建Servlet对象,数字越小优先级越高
2:初始化,继加载和实例化之后然后Servlet的init()方法会实现初始化对象。初始化完成的工作就是加载配置文件,创建连接等初始化工作。初始化的方法只会执行一次。
3:请求处理,每次请求Servlet都会自动调用service请求进行处理。
4:服务终止,当需要释放内存或者容器关闭时,容器就会调用Servlet实例的==destroy()==方法完成资源的释放。在destroy()方法调用之后,容器会释放这个Servlet实例,该实例随后会被Java的垃圾收集器所回收
测试用例
package jgd;
import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import java.io.IOException;
@WebServlet(urlPatterns = "/demo2", loadOnStartup = 1)
public class ServletDemo02 implements Servlet {
public void init(ServletConfig servletConfig) throws ServletException {
// 初始化方法
// 1:调用时机:默认情况下Servlet被第一次访问的时候调用
// 2:调用次数:只会被调用一次
System.out.println("init");
}
public ServletConfig getServletConfig() {
return null;
}
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
//每次Servlet被访问的时候service会自动执行
System.out.println("servlet hello world");
}
public String getServletInfo() {
return null;
}
/**
* 销毁方法
* 2:调用次数:1次
* 1:调用时机:内存或者服务器关闭的时候,Servlet对象会被销毁
*/
public void destroy() {
System.out.println("destory---");
}
}
Servlet方法说明和体系结构
方法说明
在上文中已经说明了三个方法。初始化,服务,以及销毁。
1:初始化方法,只执行一次,默认在Servlet被第一次访问执行。
init(ServletConfig servletConfig)
2:服务方法,每次Servlet被访问的时候会默认访问,主要用于编写处理的访问逻辑.
void service(ServletRequest servletRequest, ServletResponse servletResponse)
3:销毁方法,Servlet被销毁的时候,该方法被调用。在内存释放或者服务器关闭的时候销毁Servlet。需要进行正常的关闭,如果关掉java进程就来不及等到对象被销毁。
destroy()
4:获取Servlet信息,一般的话不怎么用,给它返回空字符串和空就可以
String getServletInfo()
5:获取ServletConfig对象
ServletConfig getServletConfig()
我们研究一下如何获取到这个对象,我们可以这样做。主要是扩大作用范围。看看就明白了。
package jgd;
import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import java.io.IOException;
/*
Servlet方法说明演示
*/
@WebServlet(urlPatterns = "/demo3", loadOnStartup = 1)
public class ServletDemo02 implements Servlet {
private ServletConfig servletConfig;
public void init(ServletConfig servletConfig) throws ServletException {
// 初始化方法
// 1:调用时机:默认情况下Servlet被第一次访问的时候调用
// 2:调用次数:只会被调用一次
System.out.println("init");
//将servletConfig值赋给了局部变量
this.servletConfig=servletConfig;
}
public ServletConfig getServletConfig() {
return servletConfig;
}
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
//每次Servlet被访问的时候service会自动执行
System.out.println("servlet hello world");
}
public String getServletInfo() {
return null;
}
/**
* 销毁方法
* 2:调用次数:1次
* 1:调用时机:内存或者服务器关闭的时候,Servlet对象会被销毁
*/
public void destroy() {
System.out.println("destory---");
}
}
该对象在init方法的参数中有,而Tomcat Web服务器在创建Servlet对象的时候会调用init方法,必定会传入一个ServletConfig对象,我们只需要将服务器传过来的ServletConfig进行返回即可
体系结构说明
之前写的Servlet类都是来自继承,并且需要重写方法等等。
了解到的体系结构
因为我们将来开发B/S架构的web项目,都是针对HTTP协议,所以我们自定义Servlet,会通过继承HttpServlet
所以我们来操作一下。尝试继承这个类。
package jgd;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/demo4")
public class ServletDemo4 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// super.doGet(req, resp);
System.out.println("get...");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// super.doPost(req, resp);
System.out.println("post...");
}
}
这里个方法分别可以代表get和post的处理逻辑。根据不同的请求方式来调用相应的方法以及做出方法提里面的处理逻辑。
在继承HttpServlet时,为什么只重写doGet和doPost
get方法我们就直接在浏览器地址栏访问到项目,如果是post我么就可以去编写一个表单,然后提交到对应web项目地址。
我们现在运行这个项目。直接访问地址。
这里成功输出了get。
然后我们写一个表单,表单的action路径要指定到你的项目路径,也就是Servlet路径。
不妨用之前那个表单
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>欢迎注册</title>
<link href="register.css" rel="stylesheet">
</head>
<body>
<div class="form-div">
<div class="reg-content">
<h1>欢迎注册</h1>
<span>已有帐号?</span> <a href="#">登录</a>
</div>
<form id="reg-form" action="/demo4" method="post">
<table>
<tr>
<td>用户名</td>
<td class="inputs">
<input name="username" type="text" id="username">
<br>
<span id="username_err" class="err_msg" style="display: none">用户名不太受欢迎</span>
</td>
</tr>
<tr>
<td>密码</td>
<td class="inputs">
<input name="password" type="password" id="password">
<br>
<span id="password_err" class="err_msg" style="display: none">密码格式有误</span>
</td>
</tr>
<tr>
<td>手机号</td>
<td class="inputs"><input name="tel" type="text" id="tel">
<br>
<span id="tel_err" class="err_msg" style="display: none">手机号格式有误</span>
</td>
</tr>
</table>
<div class="buttons">
<input value="注 册" type="submit" id="reg_btn">
</div>
<br class="clear">
</form>
</div>
<script>
//1. 验证用户名是否符合规则
//1.1 获取用户名的输入框
var usernameInput = document.getElementById("username");
//1.2 绑定onblur事件 失去焦点
usernameInput.onblur = checkUsername;
function checkUsername() {
//1.3 获取用户输入的用户名
var username = usernameInput.value.trim();
//1.4 判断用户名是否符合规则:长度 6~12,单词字符组成
var reg = /^w{6,12}$/;
var flag = reg.test(username);
//var flag = username.length >= 6 && username.length <= 12;
if (flag) {
//符合规则
document.getElementById("username_err").style.display = 'none';
} else {
//不合符规则
document.getElementById("username_err").style.display = '';
}
return flag;
}