Servlet接口实现类
新建module
添加framework support
写一个Servlet类
- HttpServlet是一个抽象类,他的爸爸实现了Servlet接口
- 抽象类作用:降低接口实现类对接口实现过程难度
- 将接口中不需要使用抽象方法教给抽象类进行完成
- 这样接口实现类只需要对接口需要的方法进行重写
- Servlet接口有五个方法,其中只有一个对我们的类有帮助
- oneServlet->(abstract)HttpServlet->(abstract)GenericServlet->servlet接口
- 爷爷辈实现了四个方法,留了需要用的作为抽象方法
package com.example.ServletTest;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class OneServlet extends HttpServlet {
//请求方式有7种,我们只需要用get方法和post方法
//这里需要重写
//通过父类决定在何种情况下调用子类中方法-------【设计模式】---模板设计模式
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("这是Get方式");
super.doGet(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("这是Post方式");
super.doPost(req, resp);
}
}
找到web.xml
为网站登录时的URL重命名
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--servlet接口实现类类路径地址交给Tomcat-->
<servlet>
<servlet-name>oneServlet</servlet-name>
<servlet-class>com.example.ServletTest.OneServlet</servlet-class>
</servlet>
<!--设置别名-->
<servlet-mapping>
<servlet-name>oneServlet</servlet-name>
<url-pattern>/one</url-pattern>
</servlet-mapping>
</web-app>
此时将网站重命名为one
此时可以得知使用的get方法
Servlet接口实现类
- servlet接口来自于servlet规范下一个接口,这个接口存在http服务器提供jar包
- Tomcat服务器下lib文件有一个servlet-api.jar存放servlet接口(javax.servlet.servlet接口)
- servlet规范中任务,Http服务器能调用的【动态资源文件】必须是一个servlet接口实现类
添加Servlet对象,右键-New-Servlet
就不需要像上面一样手动写了
注意Java EE 6+的勾要取消掉
此时再取别名
我们比较两种情况
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>MyServlet</servlet-name>
<servlet-class>com.example.Servlet_Period.MyServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>MyServlet</servlet-name>
<url-pattern>/Test</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>TwoServlet</servlet-name>
<servlet-class>com.example.Servlet_Period.TwoServlet</servlet-class>
<!--给一个大于零的数就可以了-->
<load-on-startup>3</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>TwoServlet</servlet-name>
<url-pattern>/Test2</url-pattern>
</servlet-mapping>
</web-app>
我们在建立TwoServlet的时候,采用的自启动方式
比较两种情况
package com.example.Servlet_Period;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;
public class MyServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("MyServlet Get Method");
}
public MyServlet() {
System.out.println("MyServlet Create");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("MyServlet Post Method");
}
}
package com.example.Servlet_Period;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
@WebServlet(name = "TwoServlet", value = "/TwoServlet")
public class TwoServlet extends HttpServlet {
public TwoServlet() {
System.out.println("TwoServlet create");
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("TwoServlet Get Method");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("TwoServlet Post Method");
}
}
刚启动Tomcat时,就会创建TwoServlet
此时输入MyServlet的别名Test,将会创建MyServlet对象,调用Get方法
输入TwoServlet别名Test2,将不会会创建TwoServlet对象,因为之前已经创建了,不会再创新的,但还是会调用Get方法
HttpServletResponse接口
- HttpservletResponse接口实现类由Http服务器负责提供
- HttpservletResponse接口负责将doGet/doPost方法执行结果写入到[【响应体】交给浏览器
习惯将该接口修饰的对象叫做【响应对象】
package com.example.ServletResponse;
public class OneServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("doGet Creates");
String result = "Yao Ming";//执行结果
int money = 50;
//通过响应对象获得输出流
PrintWriter out = resp.getWriter();
//通过二进制写入响应体中
out.write(result);
out.println();
out.println(money);
out.write(money);
}
//Tomcat把响应包推送给了浏览器
}
推送回去之后,我们可以看到,输出String对象正常
输出println正常,输出write里面给一个数字,那么会被当做asc码输出,所以之后还是用print比较稳妥
再注意一点就是编码问题和HTML标记的使用
都要对ContentType进行设置
package com.example.ServletResponse;
public class ThreeServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String result2 = "Java<br/>MySQL<br/>HTML<br/>";
String result3 = "姚明";
//response.setContentType("text/html");
response.setContentType("text/html;charset=utf-8");
//response.setCharacterEncoding("GB2312");也可以这样设置编码集
PrintWriter out = response.getWriter();
out.println(result2);
out.println(result3);
}
}
浏览器在接收到响应包之后,如果发现响应头中存在location属性,自动通过地址栏向location指定网站发送请求
package com.example.ServletResponse;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;
import java.io.PrintWriter;
public class ThreeServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//通过响应对象,将地址赋值给响应头中location属性
String result2 = "http://www.baidu.com";
//会链接到新的链接
response.sendRedirect(result2);
}
}
HttpServletRequest接口
HttpservletRequest接口负责在doGet/doPost方法运行时读取ttp请求协议包中信息
习惯将该接口修饰的对象叫做【请求对象】
作用:
- 可以读取Http请求协议包中【请求行】信息
- 可以读取保存在Http请求协议包中【请求头】或则【请求体】中请求参数信息
- 可以代替浏览器向Http服务器申请资源文件调用
我们来看一个例子
读取【请求行】的相关信息
package com.example.ServletRequest;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;
public class ServletRequestTest extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//通过请求对象,读取【请求行】中的uri和url对象
String uri = request.getRequestURI().toString();
String url = request.getRequestURL().toString();
//通过请求对象,读取【请求行】中的method对象
String method = request.getMethod();
System.out.println("URI:" + uri);
System.out.println("Method:" + method);
System.out.println("URL:" + url);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
URI:/Request/Test
Method:GET
URL:http://localhost:8080/Request/Test
我们再来看看如何获取请求对象
首先有一个MyServlet对象
package com.example.ServletRequest;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;
import java.util.Enumeration;
public class MyServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//通过请求对象获得【请求头】中【所有请求参数名称】
Enumeration<String> Paras = request.getParameterNames();
while (Paras.hasMoreElements()) {
String paraName = Paras.nextElement();
System.out.println("ParameterName is " + paraName);
String value = request.getParameter(paraName);
System.out.println("ParameterValue is " + value);
}
}
}
该对象重命名为Two了
再写一个Two.html的文件
给一个超链接
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<center>
<a href="/Request/Two?username=mike&password=333">通过超链接访问TwoServlet并携带请求参数</a>
</center>
</body>
</html>
超链接的位置就是URI,然后接一个问号,以及传username和password
此时点击超链接,可以得到参数
ParameterName is username
ParameterValue is mike
ParameterName is password
ParameterValue is 333
比较GET和POST
浏览器以GET方式发送请求,请求参数保存在==【请求头】,在Http请求协议包到达Http服务器之后,第一件事就是进行解码请求头二进制内容由Tomcat负责解码,Tomcat默认使用【utf-8】字符集,可以解释一切国家文字
浏览器以POST方式发送请求,请求参数保存在【请求体】==,在Http请求协议包到达Http服务器之后,第一件事就是进行解码请求体二进制内容由当前请求对象(request)负责解码。request默认使用[ISO-8859-1]字符集,一个东欧语系字符集此时如果请求体参数内容是中文,将无法解码只能得到乱码
在Post请求方式下,在读取请求体内容之前,应该通知请求对象使用utf-8字符集对请求体内容进行一次重新解码
新建一个Three.html文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="Request/Two" method="get">
请求参数<input type="text" name="username"></br>
<input type="submit" value="get方式访问">
</form>
<form action="Request/Two" method="post">
请求参数<input type="text" name="username"></br>
<input type="submit" value="post方式访问">
</form>
</body>
</html>
这里设置好了两种请求方式
不解码的话就会是这样
所以必须解码
完整如下
package com.example.ServletRequest;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;
import java.util.Enumeration;
public class MyServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//通过请求对象获得【请求头】中【所有请求参数名称】
Enumeration<String> Paras = request.getParameterNames();
while (Paras.hasMoreElements()) {
String paraName = Paras.nextElement();
System.out.println("ParameterName is " + paraName);
String value = request.getParameter(paraName);
System.out.println("ParameterValue is " + value);
}
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//解码的语句一定要写
request.setCharacterEncoding("utf-8");
Enumeration<String> Paras = request.getParameterNames();
while (Paras.hasMoreElements()) {
String paraName = Paras.nextElement();
System.out.println("ParameterName is " + paraName);
String value = request.getParameter(paraName);
System.out.println("ParameterValue is " + value);
}
}
}
请求对象和响应对象生命周期
- 在Http服务器接收到浏览器发送的【Http请求协议包】之后,
自动为当前的【Http请求协议包】生成一个【请求对象】和一个【响应对象】 - 在Http服务器调用docet/doPost方法时,负责将【请求对象】和【响应对象】作为实参传递到方法,确保doGet/doPost正确执行
- 在Http服务器准备推送Http响应协议包之前,负责将本次请求关联的【请求对象】和【响应对象】销毁卸磨杀驴
结束时间:2021-06-30