文章目录
前言
servlet是后端用来链接前端的API ,但是光靠一个servlet不能构造一个网站的,网站需要有服务器 -Tomcat-需要前端代码,需要后端 ,前端给后端发送数据一般是通过俩种方式 , 第一种from表单方式 ,第二种通过Ajax方式 ,通常发送请求的格式规定为JSon格式,前端通过JS将JSON数据格式转换为字符串,而后端通过Jackson完成JSON与对象的转换,一般而言后端还经常要与数据库建立链接这个用的是JDBC技术, 而后端给前端接送前端的请求框架就是servlet有三个核心类
补充知识
URI : 唯一资源标识符
URL : 唯一资源定位符
query String 查询字符串
query String 中的键值对, key是允许被重复的
query String 中的键值对都是程序员自己定义的
前端发送JSON 请求 - 用 ajax 需要引入 jquery第三方库
servlet 与spring的定位是一样的 , spring从根本上来说是对servlet的封装
Servlet中的API
servlet的生命周期
其中,init( ),service( ),destroy( )是Servlet生命周期的方法。代表了Servlet从“出生”到“工作”再到“死亡 ”的过程。
init( )
当Servlet第一次被请求时,Servlet容器就会开始调用这个方法来初始化一个Servlet对象出来,这个方法在后续请求中不会在被Servlet容器调用,就像人只能“出生”一次一样。我们可以利用init(
)方法来执行相应的初始化工作。
service( )方法
每当请求Servlet时,Servlet容器就会调用这个方法。就第一次请求时,Servlet容器会先调用init()方法初始化一个Servlet对象出来,然后调用它的service( )方法进行工作,在后续的请求中,Tomcat只会调用service方法了。
destory()
当要销毁Servlet时,Servlet容器就会调用这个方法,在卸载应用程序或者关闭Servlet容器时,便会启动这个方法 , 一般在这个方法中会写一些清除代码。但是这个方法不可靠,因为Servlet不一定是正常关闭的
HTTPServlet
httpServlet中的核心方法有doXXX方法 ,主要用来接收客户端给服务器发送的请求
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("/hello")
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html; charset=utf8");
resp.getWriter().write("这是一个 doGet 方法");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().write("doPost");
}
@Override
protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().write("doPut");
}
@Override
protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().write("doDelete");
}
}
HTTPServletRequest与HTTPServletResponse
表示一个http请求 - 能够处理各种http 请求报文中的信息
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.util.Enumeration;
@WebServlet("/showRequest")
public class ShowRequest extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
StringBuilder result = new StringBuilder();
result.append(req.getProtocol());
result.append("<br>");
result.append(req.getMethod());
result.append("<br>");
result.append(req.getRequestURI());
result.append("<br>");
result.append(req.getQueryString());
result.append("<br>");
result.append(req.getContextPath());
result.append("<br>");
result.append("=========================<br>");
Enumeration<String> headerNames = req.getHeaderNames();
while (headerNames.hasMoreElements()) {
String headerName = headerNames.nextElement();
String headerValue = req.getHeader(headerName);
result.append(headerName + ": " + headerValue + "<br>");
}
// 在响应中设置上 body 的类型. 方便浏览器进行解析
resp.setContentType("text/html;charset=utf8");
resp.getWriter().write(result.toString());
}
}
Jackson的使用
// 使用 jackson, 最核心的对象就是 ObjectMapper
// 通过这个对象, 就可以把 json 字符串解析成 java 对象; 也可以把一个 java 对象转成一个 json 格式字符串.
private ObjectMapper objectMapper = new ObjectMapper();
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 通过 post 请求的 body 传递过来一个 json 格式的字符串.
User user = objectMapper.readValue(req.getInputStream(), User.class);
System.out.println("username=" + user.username + ", password=" + user.password);
resp.getWriter().write("ok");
}
项目编写
前端部分,要注意打开路径,
不要使用本地打开,要用Tomcat中的路径打开,这个前端部分的代码是放在WEB-INF目录下面的
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>登录页面</title>
</head>
<body>
<form action="login" method="post">
<input type="text" name="username">
<input type="password" name="password">
<input type="submit" value="登录">
</form>
</body>
</html>
登录时的校验程序
package login;
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 javax.servlet.http.HttpSession;
import java.io.IOException;
// 这个类用来实现登录时的校验.
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1. 先从请求中拿到用户名和密码.
// 为了保证读出来的参数也能支持中文, 要记得设置请求的编码方式是 utf8
req.setCharacterEncoding("utf8");
String username = req.getParameter("username");
String password = req.getParameter("password");
// 2. 验证用户名密码是否正确
if (username == null || password == null || username.equals("") || password.equals("")) {
resp.setContentType("text/html; charset=utf8");
resp.getWriter().write("当前输入的用户名或密码不能为空!");
return;
}
// 此处假定用户名只能是 zhangsan 或者 lisi. 密码都是 123
// 正常的登录逻辑, 验证用户名密码都是从数据库读取的.
if (!username.equals("zhangsan") && !username.equals("lisi")) {
// 用户名有问题
resp.setContentType("text/html; charset=utf8");
resp.getWriter().write("用户名或密码有误");
return;
}
if (!password.equals("123")) {
// 密码有问题
resp.setContentType("text/html; charset=utf8");
resp.getWriter().write("用户名或密码有误");
return;
}
// 3. 用户名和密码验证 ok, 接下来就创建一个会话.
// 当前用户处于未登录的状态, 此时请求的 cookie 中没有 sessionId
// 此处的 getSession 是无法从服务器的 哈希表 中找到该 session 对象的.
// 由于此处把参数设为 true 了, 所以就允许 getSession 在查询不到的时候, 创建新的 session 对象和 sessionId
// 并且会自动的把这个 sessionId 和 session 对象存储的 哈希表 中.
// 同时返回这个 session 对象, 并且在接下来的响应中会自动把这个 sessionId 返回给客户端浏览器.
HttpSession session = req.getSession(true);
// 接下来可以让刚刚创建好的 session 对象存储咱们自定义的数据. 就可以在这个对象中存储用户的身份信息.
session.setAttribute("username", username);
// 4. 登录成功之后, 自动跳转到 主页
resp.sendRedirect("index");
}
}
登录完成后生成的页面
package login;
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 javax.servlet.http.HttpSession;
import java.io.IOException;
// 这个 Servlet 用来动态的生成主页面.
@WebServlet("/index")
public class IndexServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 此处禁止创建会话. 如果没找到, 认为用户是未登录的状态!!
// 如果找到了才认为是登录状态.
HttpSession session = req.getSession(false);
if (session == null) {
// 未登录状态
resp.setContentType("text/html; charset=utf8");
resp.getWriter().write("当前用户未登录!");
return;
}
String username = (String) session.getAttribute("username");
if (username == null) {
// 虽然有会话对象, 但是里面没有必要的属性, 也认为是登录状态异常.
resp.setContentType("text/html; charset=utf8");
resp.getWriter().write("当前用户未登录!");
return;
}
// 如果上述检查都 ok, 接下来就直接生成一个动态页面.
resp.setContentType("text/html; charset=utf8");
resp.getWriter().write("欢迎你! " + username);
}
}
实验结果
总结流程
① 先约定好前后端交互的接口- 比如JSON格式
② 进行后端接受请求代码编写响应,利用jackson解析前端传过来的请求
③ 看是否需要链接数据库 - 需要的话就编写数据库代码,利用JDBC实现与数据库的交互
④ 编写前端代码,构造请求,利用JS解析JSON格式数据,并构造好请求发送给后端 ,并将写好的前端放到maven中的WEB-INF中
⑤ 利用浏览器验证整个项目