1.什么是Servlet
Servlet是一个Java程序,是在服务器上运行以处理客户端请求并作出响应的程序
2.Servlet类的基本结构
Servlet是一个Java类。Servlet类继承HttpServlet基类,用于处理HTTP协议请求
public class HelloServlet extends HttpServlet {
/**
* 处理POST请求
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//返回给客户端信息
response.getWriter().println("This is a POST Method");
//同理request可以获取客户端发来的信息
}
/**
* 处理GET请求
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.getWriter().println("This is a GET Method");
}
}
HttpServlet源码地址:http://tomcat.apache.org/tomcat-5.5-doc/servletapi/javax/servlet/http/HttpServlet.html
为什么response.getWriter().println("")一写中文就乱码?
我们可以这样解决问题,我们打开乱码页面,按F12找到Response Headers;然后我们再打开一个不乱码界面(随意哪个都可以),找到name下面的第一个文件,单击一下
这时候我们是不是就知道为什么乱码了?就是因为发出去的的Response Headers里面没有加入content-type,所以我们在response.getWriter().println("")上面加如下代码就解决了乱码
//注意:如果我们在下面代码的前面就有response.getWriter().println(""),那依然会乱码
response.setContentType("text/html;charset=utf-8");
为什么response.getWriter().println(“xxx”)里面不可以使用"\n"换行符?
这里我们刷新一下页面,看一下Response里里面的内容就知道原因了。
3.Servlet数据交互
3.1使用Servlet获取客户端发送的数据
客户端提交的所有数据保存在HttpServletRequest request里面
这时候我们测试一下获取客户端和本地的数据
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.getWriter().println("This is a GET Method");
String s;
System.out.println("request.getHeaderNames():"+request.getHeaderNames());
System.out.println("request.getHeader(\"User-Agent\"):"+request.getHeader("User-Agent"));
System.out.println("request.getHeader(\"referer\"):"+request.getHeader("referer"));
System.out.println("request.getContentLength():"+request.getContentLength());
System.out.println("request.getContentType():"+request.getContentType());
System.out.println("request.getLocalAddr():"+request.getLocalAddr());
System.out.println("request.getRemoteAddr():"+request.getRemoteAddr());
System.out.println("request.getLocalName():"+request.getLocalName());
System.out.println("request.getRemoteHost():"+request.getRemoteHost());
System.out.println("request.getLocalPort():"+request.getLocalPort());
System.out.println("request.getRemotePort():"+request.getRemotePort());
System.out.println("request.getRequestURI():"+request.getRequestURI());
System.out.println("request.getContextPath():"+request.getContextPath());
System.out.println("request.getMethod():"+request.getMethod());
}
我们用手机测试一下localhost发送一个get请求(请求网页就是一个默认的get请求)
LOG:
Iphone 手机Safari
request.getHeaderNames():org.apache.tomcat.util.http.NamesEnumerator@135e7428
request.getHeader("User-Agent"):Mozilla/5.0 (iPhone; CPU iPhone OS 13_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.4 Mobile/15E148 Safari/604.1
request.getHeader("referer"):null
request.getContentLength():-1
request.getContentType():null
//本地服务器的IP
request.getLocalAddr():192.168.3.89
request.getRemoteAddr():192.168.3.74
//本地服务器的name
request.getLocalName():LAPTOP-1RDHOGCR
//我手机的ip地址
request.getRemoteHost():192.168.3.74
//8894是我本地服务器的端口
request.getLocalPort():8894
//显然是客户端的端口号,所以这是我手机的端口号
request.getRemotePort():64397
request.getRequestURI():/Hello-JSP/test
request.getContextPath():/Hello-JSP
request.getMethod():GET
Iphone 谷歌浏览器仿电脑登录(请求切换到桌面版网站)
request.getHeaderNames():org.apache.tomcat.util.http.NamesEnumerator@39660f9
request.getHeader("User-Agent"):Mozilla/5.0 (iPhone; CPU iPhone OS 13_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/75.0.3770.85 Mobile/15E148 Safari/605.1
request.getHeader("referer"):null
request.getContentLength():-1
request.getContentType():null
request.getLocalAddr():192.168.3.89
request.getRemoteAddr():192.168.3.74
request.getLocalName():LAPTOP-1RDHOGCR
request.getRemoteHost():192.168.3.74
request.getLocalPort():8894
request.getRemotePort():64535
request.getRequestURI():/Hello-JSP/test
request.getContextPath():/Hello-JSP
request.getMethod():GET
Android 华为自带的浏览器登录
request.getHeaderNames():org.apache.tomcat.util.http.NamesEnumerator@1b7fc9d3
request.getHeader("User-Agent"):Mozilla/5.0 (Linux; U; Android 9;zh-cn; STF-AL00 Build/HUAWEISTF-AL00) AppleWebKit/537.36 (KHTML, like Gecko)Version/4.0 Chrome/57.0.2987.132 MQQBrowser/8.1 Mobile Safari/537.36
request.getHeader("referer"):null
request.getContentLength():-1
request.getContentType():null
request.getLocalAddr():192.168.3.89
request.getRemoteAddr():192.168.3.2
request.getLocalName():LAPTOP-1RDHOGCR
request.getRemoteHost():192.168.3.2
request.getLocalPort():8894
request.getRemotePort():48470
request.getRequestURI():/Hello-JSP/test
request.getContextPath():/Hello-JSP
request.getMethod():GET
我们现在看一下这个request.getHeader(“referer”):null为什么三次都是null呢?
因为这个getHeader(“referer”):的意思是获取当前用户从哪个页面来的,也就是说如果直接访问服务器地址,是肯定为null的。但是从其他页面的链接点进来,就会有url地址,为了方便测试,我这里创建了一个连接,http://localhost:8080/Hello-JSP/test(项目端口为:8080;项目名称为"Hello-JSP";webServlet为:@WebServlet("/test")),当你们把服务开启,点我的连接进去,就会发现这个getHeader(“referer”)的值为:request.getHeader(“referer”):https://blog.csdn.net/qq_41966009/article/details/104902780
request.getHeader(“User-Agent”)代表着什么?
//Iphone 手机Safari
request.getHeader("User-Agent"):Mozilla/5.0 (iPhone; CPU iPhone OS 13_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.4 Mobile/15E148 Safari/604.1
//Iphone 谷歌浏览器仿电脑登录(请求切换到桌面版网站)
request.getHeader("User-Agent"):Mozilla/5.0 (iPhone; CPU iPhone OS 13_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/75.0.3770.85 Mobile/15E148 Safari/605.1
//Android 华为自带的浏览器登录
request.getHeader("User-Agent"):Mozilla/5.0 (Linux; U; Android 9;zh-cn; STF-AL00 Build/HUAWEISTF-AL00) AppleWebKit/537.36 (KHTML, like Gecko)Version/4.0 Chrome/57.0.2987.132 MQQBrowser/8.1 Mobile Safari/537.36
所以综上所述我们很容易得到用户手机的类型;根据ip地址禁用其登录;了解用户访问了本网站的哪个页面。了解用户通过哪个页面访问此页面的
3.2使用Servlet获取客户端提交的数据
既然是提交数据,那就要用到POST请求,所以我们假设客户端向我们发来一个POST请求,包含了name和age字段,所以我们doPost里就要这样写
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.getWriter().println("This is a POST Method");
System.out.println("request.getHeader(\"User-Agent\"):"+request.getHeader("User-Agent"));
System.out.println("request.getParameter(\"name\"):"+request.getParameter("name"));
System.out.println("request.getParameter(\"age\"):"+request.getParameter("age"));
}
这时候后端代码写好了,就需要利用到PostMan软件模拟发送POST请求了。
点击send后,可以看到log
request.getHeader("User-Agent"):PostmanRuntime/7.23.0-beta.1
request.getParameter("name"):谁都不许动我的砖
request.getParameter("age"):21
所以综上完成了使用Servlet获取客户端提交的数据
3.3使用Servlet获取客户端提交的多条数据(表单数据)
先看效果
首先页面进入register.html(源码如下)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>录入数据</title>
</head>
<body>
<h2>录入数据</h2>
<hr>
//表单提交地址为Servlet对应的URL地址,使用POST方法提交。我的项目名称为:Hello-JSP可以看下面截图
<form action="/Hello-JSP/register" method="post">
<table>
<tr>
<td align="right">用户名:</td>
<td><input type="text" name="username" value="马克"></td>
</tr>
<tr>
<td align="right">手机号码:</td>
<td><input type="text" name="cellphone" value="12354666"></td>
</tr>
<tr>
<td align="right">年龄:</td>
<td><input type="text" name="age" value="30"></td>
</tr>
<tr>
<td align="right">备注:</td>
<td><textarea cols="80" rows="7" name="remark" >是个好学生!</textarea></td>
</tr>
<tr>
<td></td>
<td><input type="submit" value="提交"></td>
</tr>
</table>
</form>
</body>
</html>
将register.html复制到/web目录下,register.html位置如下
创建一个名称为RegisterServlet的servlet,使用@WebServlet()映射到URL地址。
package jee.servlets;
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;
import java.io.PrintWriter;
@WebServlet("/register")
public class RegisterServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
String cellphone=request.getParameter("cellphone");
String username=request.getParameter("username");
String ageStr=request.getParameter("age");
int age=Integer.parseInt(ageStr);
String remark=request.getParameter("remark");
System.out.println(username+remark);
response.setContentType("text/html");
response.setCharacterEncoding("UTF-8");
PrintWriter out=response.getWriter();
out.append("<html>").append("<body>");
out.append("用户名:"+username+"</br>")
.append("手机号码"+cellphone+"</br>")
.append("年龄:"+age+"</br>")
.append("备注:"+remark+"</br>");
out.append("</body></html>");
out.flush();
}
}
重新运行一下,就可以实现使用Servlet获取客户端提交的多条数据(表单数据)
3.4使用Servlet实现页面跳转
功能说明:演示用户系统登录功能的实现,当用户登录成功时,跳转到登录成功界面,否则跳转到登录失败界面。
效果图:
输入账号面名
输入正确的账号密码后登录跳转成功
输入错误的账号密码登陆失败
这里我们可以使用两种方法实现跳转
3.4.1响应重定向
什么是响应重定向?
HTTP协议规定的一种响应重定向机制。
响应重定向的流程:
1.客户端发送请求,Servlet做出业务逻辑处理。
2.Servlet调用response.sendReadirect()方法,把要访问的目标资源作为response响应头信息发给客户端浏览器。
3.客户端浏览器重新访问服务器资源xxx.jsp,服务器再次对客户端浏览器做出响应。
3.4.2请求转发
流程:
1.客户端发送请求,Servlet做出业务逻辑处理。
2.Servlet调用forword()方法,服务器Servlet把目标资源返回给客户端浏览器。
3.4.3响应重定向和请求转发区别
- 浏览器地址栏url的区别
- 客户端发出的请求数量的区别
小结一下:
请求转发无法让客户端知道真实地址,且只能访问本服务器内的地址(访问本服务器网页);
请求转发的 / 表示当前工程的根目录
重定向是让客户端更改地址,并且可以访问所有能访问的地址(只要你电脑能访问的地址)
重定向的 / 表示服务器根目录
以下我分别使用重定向和请求转发来跳转页面
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
System.out.println("进入了/Hello-JSP/login页面");
String usename=request.getParameter("username");
String password=request.getParameter("password");
if (!usename.equals("")&&!password.equals("")) {
if (usename.equals("admin")&&password.equals("123456")){
System.out.println("登录成功");
//请求转发------相对路径
request.getRequestDispatcher("/success.html")
.forward(request,response);
// response.sendRedirect("/Hello-JSP/success.html");
}else {
System.out.println("账号密码错误");
//重定向
response.sendRedirect("/Hello-JSP/fail.html");
}
}else {
System.out.println("账号密码为空");
response.sendRedirect("/Hello-JSP/fail.html");
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
@Override
public void init() throws ServletException {
System.out.println("Servlet"+this.getServletName()+"has started.");
System.out.println("学号:2017030401姓名:谁都不许动我的砖Servlet初始化");
}
@Override
public void destroy() {
System.out.println("Servlet"+this.getServletName()+"has stopp ed.");
System.out.println("Servlet销毁");
}
}
请求转发跳转后的成功登录界面
重定向跳转后的登录失败界面
相信大家很快就会发现其中的不同,失败界面有一个html后缀,说明此时是跳转到了fail.html界面,而成功登陆的界面并没有,这就充分形象的说明了响应重定向和请求转发的区别。
4.Servlet的生命周期
Android开发有生命周期的概念,Servlet也有,上代码测试
public class LoginServlet extends HttpServlet {
@Override
public void init() throws ServletException {
System.out.println("Servlet"+this.getServletName()+"has started.");
System.out.println("学号:2017030401037 姓名:张意 Servlet初始化");
}
@Override
public void destroy() {
System.out.println("Servlet"+this.getServletName()+"has stopp ed.");
System.out.println("Servlet销毁");
}
}
通过代码测试很容易的出来结论:Servlet在页面第一次访问该Servlet的时候被创建,在Servlet服务关闭的时候被销毁