在学Servlet API 之前,一定要先学好 HTTP 协议 和 Servlet 的基本使用
HTTP 协议
Servlet 基本使用
1. HttpServlet
我们想要构造GET请求还是容易的,直接在地址栏输入就行,可是我们POST请求就不行了,他是隐藏的,我们需要用到 ajax或form表单
我这里就用 ajax 举个例子:
Servlet代码
import javax@H_404_139@.servlet@H_404_139@.servletexception@H_404_139@;
import javax@H_404_139@.servlet@H_404_139@.annotation@H_404_139@.WebServlet@H_404_139@;
import javax@H_404_139@.servlet@H_404_139@.http@H_404_139@.HttpServlet@H_404_139@;
import javax@H_404_139@.servlet@H_404_139@.http@H_404_139@.HttpServletRequest@H_404_139@;
import javax@H_404_139@.servlet@H_404_139@.http@H_404_139@.HttpServletResponse@H_404_139@;
import java@H_404_139@.io@H_404_139@.IOException@H_404_139@;
@WebServlet@H_404_139@("/method"@H_404_139@)
public class MethodServlet extends HttpServlet @H_404_139@{
@Override
protected void doPost@H_404_139@(HttpServletRequest req@H_404_139@, HttpServletResponse resp@H_404_139@) throws servletexception@H_404_139@, IOException @H_404_139@{
resp@H_404_139@.setContentType@H_404_139@("text/html; charset=utf8"@H_404_139@)@H_404_139@;
resp@H_404_139@.getWriter@H_404_139@(@H_404_139@)@H_404_139@.write@H_404_139@("POST 响应"@H_404_139@)@H_404_139@;
@H_404_139@}
@H_404_139@}
ajax代码
(记得导入jqurey),且这个html文件要放在webapp下
@H_404_139@<body@H_404_139@>
@H_404_139@<script src=@H_404_139@"jquery.js@H_404_139@"@H_404_139@>@H_404_139@</script@H_404_139@>
@H_404_139@<script@H_404_139@>
$@H_404_139@.ajax@H_404_139@(@H_404_139@{
type: 'post'@H_404_139@,
url: 'method'@H_404_139@,
success: function@H_404_139@(body@H_404_139@)@H_404_139@{
console@H_404_139@.log@H_404_139@(body@H_404_139@)@H_404_139@;
@H_404_139@}
@H_404_139@}@H_404_139@)@H_404_139@;
@H_404_139@</script@H_404_139@>
@H_404_139@</body@H_404_139@>
页面响应:
解析:
处理乱码
还有需要注意一点的是:
写上这串代码就是为了防止页面出现乱码,因为我们浏览器是 GBK,而这里都是utf8,用这串代码告诉浏览器用utf8来读,统一编码格式,防止出现乱码
如果我们没有这串代码:
我们发现构造POST请求还挺麻烦的,有没有更快更方便的方式,当然是有的,有Postman这样一个工具:
核新方法
方法名称 | 调用时机 |
---|---|
init | 在 HttpServlet 实例化之后被调用一次 |
destory | 在 HttpServlet 实例不再使用的时候调用一次 |
service | 收到 HTTP 请求的时候调用 |
doGet | 收到 GET 请求的时候调用(由 service 方法调用) |
doPost | 收到 POST 请求的时候调用(由 service 方法调用) |
doPut/doDelete/doOptions/… | 收到其他请求的时候调用(由 service 方法调用) |
我们很少会用到 init / destory / service,这里就需要说说Servlet的"生命周期"了:
Servlet"生命周期"
Servlet"生命周期"主要分为三个阶段:
1,初始化阶段
//调用init()方法2,响应客户请求阶段
//调用service()方法3,终止阶段
//调用destroy()方法
1:init:
初始化阶段,对象创建好之后,就会执行到,用户可以重写这个方法,来执行一些初始化逻辑2:service:
在处理请求阶段来调用,每一次来个请求都要调用一次service3:destroy:
退出主循环,tomcat结束之前会调用,用来释放资源
2. HttpServletRequest
HttpServletRequest 对应到一个 HTTP 请求,他请求里面有啥,这里就有啥,所以要想学好这个,学好 HTTP请求就轻松了
核心方法
方法 | 描述 |
---|---|
String getProtocol() | 返回请求协议的名称和版本。 |
String getmethod() | 返回请求的 HTTP 方法的名称,例如,GET、POST 或 PUT。 |
String getRequestURI() | 从协议名称直到 HTTP 请求的第一行的查询字符串中,返回该请求的 URL 的一部分。 |
String getcontextpath() | 返回指示请求上下文的请求 URI 部分。 |
String getQueryString() | 返回包含在路径后的请求 URL 中的查询字符串。 |
Enumeration getParameterNames() | 返回一个 String 对象的枚举,包含在该请求中包含的参数的名称。 |
String getParameter(String name) | 以字符串形式返回请求参数的值,或者如果参数不存在则返回null。 |
String[] getParameterValues(String name) | 返回一个字符串对象的数组,包含所有给定的请求参数的值,如果参数不存在则返回 null。 |
Enumeration getHeaderNames() | 返回一个枚举,包含在该请求中包含的所有的头名。 |
String getHeader(Stringname) | 以字符串形式返回指定的请求头的值。 |
String getCharacterEncoding() | 返回请求主体中使用的字符编码的名称。 |
String getContentType() | 返回请求主体的 MIME 类型,如果不知道类型则返回 null。 |
int getContentLength() | 以字节为单位返回请求主体的长度,并提供输入流,或者如果长度未知则返回 -1。 |
InputStream getInputStream() | 用于读取请求的 body 内容. 返回一个 InputStream 对象 |
打印请求信息
我这里就打印 GET 请求了:
import javax@H_404_139@.servlet@H_404_139@.servletexception@H_404_139@;
import javax@H_404_139@.servlet@H_404_139@.annotation@H_404_139@.WebServlet@H_404_139@;
import javax@H_404_139@.servlet@H_404_139@.http@H_404_139@.HttpServlet@H_404_139@;
import javax@H_404_139@.servlet@H_404_139@.http@H_404_139@.HttpServletRequest@H_404_139@;
import javax@H_404_139@.servlet@H_404_139@.http@H_404_139@.HttpServletResponse@H_404_139@;
import java@H_404_139@.io@H_404_139@.IOException@H_404_139@;
import java@H_404_139@.util@H_404_139@.Enumeration@H_404_139@;
@WebServlet@H_404_139@("/showRequest"@H_404_139@)
public class ShowRequestServlet extends HttpServlet @H_404_139@{
@Override
protected void doGet@H_404_139@(HttpServletRequest req@H_404_139@, IOException @H_404_139@{
StringBuilder stringBuilder = new StringBuilder@H_404_139@(@H_404_139@)@H_404_139@;
stringBuilder@H_404_139@.append@H_404_139@("<h3>首行部分</h3>"@H_404_139@)@H_404_139@;
stringBuilder@H_404_139@.append@H_404_139@(req@H_404_139@.getProtocol@H_404_139@(@H_404_139@)@H_404_139@)@H_404_139@;
stringBuilder@H_404_139@.append@H_404_139@("<br>"@H_404_139@)@H_404_139@; //换行
stringBuilder@H_404_139@.append@H_404_139@(req@H_404_139@.getmethod@H_404_139@(@H_404_139@)@H_404_139@)@H_404_139@;
stringBuilder@H_404_139@.append@H_404_139@("<br>"@H_404_139@)@H_404_139@;
stringBuilder@H_404_139@.append@H_404_139@(req@H_404_139@.getRequestURI@H_404_139@(@H_404_139@)@H_404_139@)@H_404_139@;
stringBuilder@H_404_139@.append@H_404_139@("<br>"@H_404_139@)@H_404_139@;
stringBuilder@H_404_139@.append@H_404_139@(req@H_404_139@.getcontextpath@H_404_139@(@H_404_139@)@H_404_139@)@H_404_139@;
stringBuilder@H_404_139@.append@H_404_139@("<br>"@H_404_139@)@H_404_139@;
stringBuilder@H_404_139@.append@H_404_139@(req@H_404_139@.getQueryString@H_404_139@(@H_404_139@)@H_404_139@)@H_404_139@;
stringBuilder@H_404_139@.append@H_404_139@("<br>"@H_404_139@)@H_404_139@;
stringBuilder@H_404_139@.append@H_404_139@("<h3>header 部分</h3>"@H_404_139@)@H_404_139@;
//枚举类
Enumeration@H_404_139@<String@H_404_139@> headerNames = req@H_404_139@.getHeaderNames@H_404_139@(@H_404_139@)@H_404_139@;
while@H_404_139@(headerNames@H_404_139@.hasMoreElements@H_404_139@(@H_404_139@)@H_404_139@)@H_404_139@{
String headerName = headerNames@H_404_139@.nextElement@H_404_139@(@H_404_139@)@H_404_139@;
String headerValue = req@H_404_139@.getHeader@H_404_139@(headerName@H_404_139@)@H_404_139@;
stringBuilder@H_404_139@.append@H_404_139@(headerName+": "+headerValue+"<br>"@H_404_139@)@H_404_139@;
@H_404_139@}
//注意统一格式
resp@H_404_139@.setContentType@H_404_139@("text/html; charset=utf8"@H_404_139@)@H_404_139@;
resp@H_404_139@.getWriter@H_404_139@(@H_404_139@)@H_404_139@.write@H_404_139@(stringBuilder@H_404_139@.toString@H_404_139@(@H_404_139@)@H_404_139@)@H_404_139@;
@H_404_139@}
@H_404_139@}
获取 GET 请求中的参数
import javax@H_404_139@.servlet@H_404_139@.servletexception@H_404_139@;
import javax@H_404_139@.servlet@H_404_139@.annotation@H_404_139@.WebServlet@H_404_139@;
import javax@H_404_139@.servlet@H_404_139@.http@H_404_139@.HttpServlet@H_404_139@;
import javax@H_404_139@.servlet@H_404_139@.http@H_404_139@.HttpServletRequest@H_404_139@;
import javax@H_404_139@.servlet@H_404_139@.http@H_404_139@.HttpServletResponse@H_404_139@;
import java@H_404_139@.io@H_404_139@.IOException@H_404_139@;
@WebServlet@H_404_139@("/getParameter"@H_404_139@)
public class GetParameterServlet extends HttpServlet @H_404_139@{
@Override
protected void doGet@H_404_139@(HttpServletRequest req@H_404_139@, IOException @H_404_139@{
//预期这样一个请求: /getParameter?userId=123&classId=456
String userId = req@H_404_139@.getParameter@H_404_139@("userId"@H_404_139@)@H_404_139@;
String classId = req@H_404_139@.getParameter@H_404_139@("classId"@H_404_139@)@H_404_139@;
resp@H_404_139@.getWriter@H_404_139@(@H_404_139@)@H_404_139@.write@H_404_139@("userId=" + userId + ",classId=" + classId@H_404_139@)@H_404_139@;
@H_404_139@}
@H_404_139@}
我们通过浏览器加上query string,在刷新
此时就说明了服务器已经获取到了客户端传过来的参数了
获取 POST 请求中的参数
POST 请求的参数一般都是通过 body 传递给服务器的,但是我们知道前面学 HTTP请求的时候,POST中 body中的数据格式有很多种,我这里举几个例子:
form格式
Servlet代码:
import javax@H_404_139@.servlet@H_404_139@.servletexception@H_404_139@;
import javax@H_404_139@.servlet@H_404_139@.annotation@H_404_139@.WebServlet@H_404_139@;
import javax@H_404_139@.servlet@H_404_139@.http@H_404_139@.HttpServlet@H_404_139@;
import javax@H_404_139@.servlet@H_404_139@.http@H_404_139@.HttpServletRequest@H_404_139@;
import javax@H_404_139@.servlet@H_404_139@.http@H_404_139@.HttpServletResponse@H_404_139@;
import java@H_404_139@.io@H_404_139@.IOException@H_404_139@;
@WebServlet@H_404_139@("/postGetParameter"@H_404_139@)
public class PostGetParameterServlet extends HttpServlet @H_404_139@{
@Override
protected void doPost@H_404_139@(HttpServletRequest req@H_404_139@, IOException @H_404_139@{
String userId = req@H_404_139@.getParameter@H_404_139@("userId"@H_404_139@)@H_404_139@;
String classId = req@H_404_139@.getParameter@H_404_139@("classId"@H_404_139@)@H_404_139@;
resp@H_404_139@.getWriter@H_404_139@(@H_404_139@)@H_404_139@.write@H_404_139@("userId="+userId+",classId="+classId@H_404_139@)@H_404_139@;
@H_404_139@}
@H_404_139@}
前端代码:
@H_404_139@<form action=@H_404_139@"postGetParameter@H_404_139@" method=@H_404_139@"POST@H_404_139@"@H_404_139@>
@H_404_139@<input type=@H_404_139@"text@H_404_139@" name=@H_404_139@"userId@H_404_139@"@H_404_139@>
@H_404_139@<input type=@H_404_139@"text@H_404_139@" name=@H_404_139@"classId@H_404_139@"@H_404_139@>
@H_404_139@<input type=@H_404_139@"submit@H_404_139@" value=@H_404_139@"提交@H_404_139@"@H_404_139@>
@H_404_139@</form@H_404_139@>
注意路径啥的一定要写对
当点击提交时我们用抓包工具观察一下:
Json格式
如果是 json 格式,如果我们手动来解析,是非常困难的,因为我们知道 json 是可以嵌套的,由于他们是以键值对的形式出现,就是说键对应的值也可以是一个 json 格式的
Jackson导入
所以,这里我们需要导入第三方库来解决,有很多,我这里使用的是 Jackson(因为他是 Spring 官方推荐的,后续我们学Spring 也会用到),还是一样去 中央仓库上下
官网:https://mvnrepository.com/
<!-- https://mvnrepository@H_404_139@.com/artifact/com@H_404_139@.fasterxml@H_404_139@.jackson@H_404_139@.core/jackson-databind -->
@H_404_139@<dependency@H_404_139@>
@H_404_139@<groupId@H_404_139@>com@H_404_139@.fasterxml@H_404_139@.jackson@H_404_139@.core</groupId>
@H_404_139@<artifactId@H_404_139@>jackson-databind</artifactId>
@H_404_139@<version@H_404_139@>2.13.0</version>
</dependency>
Servlet代码:
import com@H_404_139@.fasterxml@H_404_139@.jackson@H_404_139@.databind@H_404_139@.ObjectMapper@H_404_139@;
import javax@H_404_139@.servlet@H_404_139@.servletexception@H_404_139@;
import javax@H_404_139@.servlet@H_404_139@.annotation@H_404_139@.WebServlet@H_404_139@;
import javax@H_404_139@.servlet@H_404_139@.http@H_404_139@.HttpServlet@H_404_139@;
import javax@H_404_139@.servlet@H_404_139@.http@H_404_139@.HttpServletRequest@H_404_139@;
import javax@H_404_139@.servlet@H_404_139@.http@H_404_139@.HttpServletResponse@H_404_139@;
import java@H_404_139@.io@H_404_139@.IOException@H_404_139@;
class User@H_404_139@{
//当前这俩属性都设置成 public,如果设为了private,就要提供 getter and setter 效果也一样
public int userId@H_404_139@;
public int classId@H_404_139@;
@H_404_139@}
@WebServlet@H_404_139@("/postJson"@H_404_139@)
public class PostJsonServlet extends HttpServlet @H_404_139@{
//1.创建一个 jackson 核心对象
private ObjectMapper objectMapper = new ObjectMapper@H_404_139@(@H_404_139@)@H_404_139@;
@Override
protected void doPost@H_404_139@(HttpServletRequest req@H_404_139@, IOException @H_404_139@{
//2.读取 body 中的请求,然后使用 ObjectMapper 来解析成需要的对象.
//readValue 就是把 JSON 格式的字符串,转成 java 的对象
//第一个参数,表示那个字符串进行转换,这个参数可以填写成一个 String,也可以填一个 InputStream 对象,还可以填一个 File
// 第二个参数,表示要把这个 JSON 格式的字符串,转成哪个 Java 对象
User user = objectMapper@H_404_139@.readValue@H_404_139@(req@H_404_139@.getInputStream@H_404_139@(@H_404_139@)@H_404_139@,User@H_404_139@.class@H_404_139@)@H_404_139@;
resp@H_404_139@.getWriter@H_404_139@(@H_404_139@)@H_404_139@.write@H_404_139@("userId: "+user@H_404_139@.userId+",classId: "+user@H_404_139@.classId@H_404_139@)@H_404_139@;
@H_404_139@}
@H_404_139@}
前端代码:
@H_404_139@<!DOCTYPE html@H_404_139@>
@H_404_139@<html lang=@H_404_139@"en@H_404_139@"@H_404_139@>
@H_404_139@<head@H_404_139@>
@H_404_139@<Meta charset=@H_404_139@"UTF-8@H_404_139@"@H_404_139@>
@H_404_139@<Meta http-equiv=@H_404_139@"X-UA-Compatible@H_404_139@" content=@H_404_139@"IE=edge@H_404_139@"@H_404_139@>
@H_404_139@<Meta name=@H_404_139@"viewport@H_404_139@" content=@H_404_139@"width=device-width,initial-scale=1.0@H_404_139@"@H_404_139@>
@H_404_139@<title@H_404_139@>Document@H_404_139@</title@H_404_139@>
@H_404_139@</head@H_404_139@>
@H_404_139@<body@H_404_139@>
@H_404_139@<input type=@H_404_139@"text@H_404_139@" id=@H_404_139@"userId@H_404_139@"@H_404_139@>
@H_404_139@<input type=@H_404_139@"text@H_404_139@" id=@H_404_139@"classId@H_404_139@"@H_404_139@>
@H_404_139@<input type=@H_404_139@"button@H_404_139@" value=@H_404_139@"提交@H_404_139@" id=@H_404_139@"submit@H_404_139@"@H_404_139@>
<!-- 要想构造一个 json 格式的请求,就不再使用 form 而是使用 ajax 了 -->
@H_404_139@<script src=@H_404_139@"jquery.js@H_404_139@"@H_404_139@>@H_404_139@</script@H_404_139@>
@H_404_139@<script@H_404_139@>
let userIdInput = document@H_404_139@.querySelector@H_404_139@('#userId'@H_404_139@)@H_404_139@;
let classIdInput = document@H_404_139@.querySelector@H_404_139@('#classId'@H_404_139@)@H_404_139@;
let button = document@H_404_139@.querySelector@H_404_139@('#submit'@H_404_139@)@H_404_139@;
button@H_404_139@.onclick = function@H_404_139@(@H_404_139@) @H_404_139@{
$@H_404_139@.ajax@H_404_139@(@H_404_139@{
type: 'post'@H_404_139@,
url: 'postJson'@H_404_139@,
contentType: 'application/json'@H_404_139@,
data: JSON@H_404_139@.stringify@H_404_139@(@H_404_139@{
userId: userIdInput@H_404_139@.value@H_404_139@,
classId: classIdInput@H_404_139@.value
@H_404_139@}@H_404_139@)@H_404_139@,
success: function@H_404_139@(body@H_404_139@) @H_404_139@{
console@H_404_139@.log@H_404_139@(body@H_404_139@)@H_404_139@;
@H_404_139@}
@H_404_139@}@H_404_139@)@H_404_139@;
@H_404_139@}
@H_404_139@</script@H_404_139@>
@H_404_139@</body@H_404_139@>
@H_404_139@</html@H_404_139@>
解析代码:
2.1 - Postman安装
Postman构造 POST 请求,JSON格式什么的是比上面更加方便的
官网下载链接:https://www.postman.com/
进入Postman
可能出现的问题:
有些人可能进这个软件之后会发现一片空白,什么反应都没有,但是任务管理器上又成功启动了的
解决办法:
变量: POSTMAN_disABLE_GPU
值: true
最后重启Postman即可
使用教程
POST请求格式
我先在 IDEA 编写好 Servlet 代码,使用 POST 请求
import javax@H_404_139@.servlet@H_404_139@.servletexception@H_404_139@;
import javax@H_404_139@.servlet@H_404_139@.annotation@H_404_139@.WebServlet@H_404_139@;
import javax@H_404_139@.servlet@H_404_139@.http@H_404_139@.HttpServlet@H_404_139@;
import javax@H_404_139@.servlet@H_404_139@.http@H_404_139@.HttpServletRequest@H_404_139@;
import javax@H_404_139@.servlet@H_404_139@.http@H_404_139@.HttpServletResponse@H_404_139@;
import java@H_404_139@.io@H_404_139@.IOException@H_404_139@;
@WebServlet@H_404_139@("/method"@H_404_139@)
public class MethodServlet extends HttpServlet @H_404_139@{
@Override
protected void doPost@H_404_139@(HttpServletRequest req@H_404_139@, IOException @H_404_139@{
resp@H_404_139@.setContentType@H_404_139@("text/html; charset=utf8"@H_404_139@)@H_404_139@;
resp@H_404_139@.getWriter@H_404_139@(@H_404_139@)@H_404_139@.write@H_404_139@("POST 响应"@H_404_139@)@H_404_139@;
@H_404_139@}
@H_404_139@}
启动 服务器:
选择想要的格式,我这里用的 POST 请求,就选POST方式,输入你要访问的地址,最后点击send,
这样就不用再去编写代码来实现 POST 请求了,非常方便
例如我还可以编写 JSON 格式
POST 请求,Json 格式
首先写好 Servlet 代码
import com@H_404_139@.fasterxml@H_404_139@.jackson@H_404_139@.databind@H_404_139@.ObjectMapper@H_404_139@;
import javax@H_404_139@.servlet@H_404_139@.servletexception@H_404_139@;
import javax@H_404_139@.servlet@H_404_139@.annotation@H_404_139@.WebServlet@H_404_139@;
import javax@H_404_139@.servlet@H_404_139@.http@H_404_139@.HttpServlet@H_404_139@;
import javax@H_404_139@.servlet@H_404_139@.http@H_404_139@.HttpServletRequest@H_404_139@;
import javax@H_404_139@.servlet@H_404_139@.http@H_404_139@.HttpServletResponse@H_404_139@;
import java@H_404_139@.io@H_404_139@.IOException@H_404_139@;
class User@H_404_139@{
//当前这俩属性都设置成 public,classId: "+user@H_404_139@.classId@H_404_139@)@H_404_139@;
@H_404_139@}
@H_404_139@}
启动服务器:
非常方便!!!
3. HttpServletResponse
Servlet 中的 doXXX 方法的目的就是根据请求计算得到相应,然后把响应的数据设置到HttpServletResponse 对象中.
然后 Tomcat 就会把这个 HttpServletResponse 对象按照 HTTP 协议的格式,转成一个字符串,并通过Socket 写回给浏览器.
核心方法
方法 | 描述 |
---|---|
void setStatus(int sc) | 为该响应设置状态码。 |
void setHeader(String name,String value) | 设置一个带有给定的名称和值的 header. 如果 name 已经存在,则覆盖旧的值. |
void addHeader(Stringname,String value) | 添加一个带有给定的名称和值的 header. 如果 name 已经存在,不覆盖旧的值,并列添加新的键值对 |
void setContentType(String type) | 设置被发送到客户端的响应的内容类型。 |
void setCharacterEncoding(String charset) | 设置被发送到客户端的响应的字符编码(MIME 字符集)例如,UTF-8。 |
void sendRedirect(String location) | 使用指定的重定向位置 URL 发送临时重定向响应到客户端。 |
PrintWriter getWriter() | 用于往 body 中写入文本格式数据. |
OutputStream getoutputStream() | 用于往 body 中写入二进制格式数据. |
注意:
1: 响应对象是服务器要返回给浏览器的内容,这里的重要信息都是程序猿设置的. 因此上面的方法都是 “写” 方法.
2: 对于状态码/响应头的设置要放到 getWriter / getoutputStream 之前. 否则可能设置失效.
设置状态码
import javax@H_404_139@.servlet@H_404_139@.servletexception@H_404_139@;
import javax@H_404_139@.servlet@H_404_139@.annotation@H_404_139@.WebServlet@H_404_139@;
import javax@H_404_139@.servlet@H_404_139@.http@H_404_139@.HttpServlet@H_404_139@;
import javax@H_404_139@.servlet@H_404_139@.http@H_404_139@.HttpServletRequest@H_404_139@;
import javax@H_404_139@.servlet@H_404_139@.http@H_404_139@.HttpServletResponse@H_404_139@;
import java@H_404_139@.io@H_404_139@.IOException@H_404_139@;
@WebServlet@H_404_139@("/status"@H_404_139@)
public class StatusServlet extends HttpServlet @H_404_139@{
@Override
protected void doGet@H_404_139@(HttpServletRequest req@H_404_139@, IOException @H_404_139@{
resp@H_404_139@.setStatus@H_404_139@(404@H_404_139@)@H_404_139@;
resp@H_404_139@.getWriter@H_404_139@(@H_404_139@)@H_404_139@.write@H_404_139@("hello"@H_404_139@)@H_404_139@;
@H_404_139@}
@H_404_139@}
通过抓包工具观察一下:
可能有的人就会疑问了,这个404页面好像不是这样的?
那是因为服务器返回的状态码,只是在告诉浏览器,当前是个啥状态,他是不会影响显示在 body 中的内容的,就像我以哔哩哔哩
为例子:
他是可以自己设置的
自动刷新
import javax@H_404_139@.servlet@H_404_139@.servletexception@H_404_139@;
import javax@H_404_139@.servlet@H_404_139@.annotation@H_404_139@.WebServlet@H_404_139@;
import javax@H_404_139@.servlet@H_404_139@.http@H_404_139@.HttpServlet@H_404_139@;
import javax@H_404_139@.servlet@H_404_139@.http@H_404_139@.HttpServletRequest@H_404_139@;
import javax@H_404_139@.servlet@H_404_139@.http@H_404_139@.HttpServletResponse@H_404_139@;
import java@H_404_139@.io@H_404_139@.IOException@H_404_139@;
@WebServlet@H_404_139@("/autoRefresh"@H_404_139@)
public class AutoRefreshServlet extends HttpServlet @H_404_139@{
@Override
protected void doGet@H_404_139@(HttpServletRequest req@H_404_139@, IOException @H_404_139@{
resp@H_404_139@.setHeader@H_404_139@("Refresh"@H_404_139@,"1"@H_404_139@)@H_404_139@;
resp@H_404_139@.getWriter@H_404_139@(@H_404_139@)@H_404_139@.write@H_404_139@("timeStamp: "+System@H_404_139@.currentTimeMillis@H_404_139@(@H_404_139@)@H_404_139@)@H_404_139@;
@H_404_139@}
@H_404_139@}
他是一秒刷新的时间戳
重定向
import javax@H_404_139@.servlet@H_404_139@.servletexception@H_404_139@;
import javax@H_404_139@.servlet@H_404_139@.annotation@H_404_139@.WebServlet@H_404_139@;
import javax@H_404_139@.servlet@H_404_139@.http@H_404_139@.HttpServlet@H_404_139@;
import javax@H_404_139@.servlet@H_404_139@.http@H_404_139@.HttpServletRequest@H_404_139@;
import javax@H_404_139@.servlet@H_404_139@.http@H_404_139@.HttpServletResponse@H_404_139@;
import java@H_404_139@.io@H_404_139@.IOException@H_404_139@;
@WebServlet@H_404_139@("/redirect"@H_404_139@)
public class RedirectServlet extends HttpServlet @H_404_139@{
@Override
protected void doGet@H_404_139@(HttpServletRequest req@H_404_139@, IOException @H_404_139@{
//我们在这里返回一个 302 重定向响应,就会自动跳转到火狐
resp@H_404_139@.setStatus@H_404_139@(302@H_404_139@)@H_404_139@;
resp@H_404_139@.setHeader@H_404_139@("Location"@H_404_139@,"https://home.firefoxchina.cn/"@H_404_139@)@H_404_139@;
@H_404_139@}
@H_404_139@}
简写方式:
import javax@H_404_139@.servlet@H_404_139@.servletexception@H_404_139@;
import javax@H_404_139@.servlet@H_404_139@.annotation@H_404_139@.WebServlet@H_404_139@;
import javax@H_404_139@.servlet@H_404_139@.http@H_404_139@.HttpServlet@H_404_139@;
import javax@H_404_139@.servlet@H_404_139@.http@H_404_139@.HttpServletRequest@H_404_139@;
import javax@H_404_139@.servlet@H_404_139@.http@H_404_139@.HttpServletResponse@H_404_139@;
import java@H_404_139@.io@H_404_139@.IOException@H_404_139@;
@WebServlet@H_404_139@("/redirect"@H_404_139@)
public class RedirectServlet extends HttpServlet @H_404_139@{
@Override
protected void doGet@H_404_139@(HttpServletRequest req@H_404_139@, IOException @H_404_139@{
resp@H_404_139@.sendRedirect@H_404_139@("https://home.firefoxchina.cn/"@H_404_139@)@H_404_139@;
@H_404_139@}
@H_404_139@}
实现一个 web 表白墙
我们要实现的这个案例,他不同于`我们之前写前端的时候数据不能保存,这个表白墙就需要实现数据做到"持久化"存储,我这里用数据库来存储信息
1. 准备工作
1: 创建Maven项目
2: 创建必要的 目录,WEB-INF,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>
3:调整 pom.xml
引入依赖:
@H_404_139@<dependencies@H_404_139@>
<!-- https://mvnrepository@H_404_139@.com/artifact/javax@H_404_139@.servlet/javax@H_404_139@.servlet-api -->
@H_404_139@<dependency@H_404_139@>
@H_404_139@<groupId@H_404_139@>javax@H_404_139@.servlet</groupId>
@H_404_139@<artifactId@H_404_139@>javax@H_404_139@.servlet-api</artifactId>
@H_404_139@<version@H_404_139@>3.1.0</version>
@H_404_139@<scope@H_404_139@>provided</scope>
</dependency>
<!-- https://mvnrepository@H_404_139@.com/artifact/com@H_404_139@.fasterxml@H_404_139@.jackson@H_404_139@.core/jackson-databind -->
@H_404_139@<dependency@H_404_139@>
@H_404_139@<groupId@H_404_139@>com@H_404_139@.fasterxml@H_404_139@.jackson@H_404_139@.core</groupId>
@H_404_139@<artifactId@H_404_139@>jackson-databind</artifactId>
@H_404_139@<version@H_404_139@>2.12.6.1</version>
</dependency>
<!-- 引入 MysqL 驱动包 -->
<!-- https://mvnrepository@H_404_139@.com/artifact/MysqL/MysqL-connector-java -->
@H_404_139@<dependency@H_404_139@>
@H_404_139@<groupId@H_404_139@>MysqL</groupId>
@H_404_139@<artifactId@H_404_139@>MysqL-connector-java</artifactId>
@H_404_139@<version@H_404_139@>5.1.49</version>
</dependency>
</dependencies>
4: 将之前表白墙拷贝到 webapp目录中,同时也要引入 jquery
@H_404_139@<!DOCTYPE html@H_404_139@>
@H_404_139@<html lang=@H_404_139@"en@H_404_139@"@H_404_139@>
@H_404_139@<head@H_404_139@>
@H_404_139@<Meta charset=@H_404_139@"UTF-8@H_404_139@"@H_404_139@>
@H_404_139@<Meta http-equiv=@H_404_139@"X-UA-Compatible@H_404_139@" content=@H_404_139@"IE=edge@H_404_139@"@H_404_139@>
@H_404_139@<Meta name=@H_404_139@"viewport@H_404_139@" content=@H_404_139@"width=device-width,initial-scale=1.0@H_404_139@"@H_404_139@>
@H_404_139@<title@H_404_139@>Document@H_404_139@</title@H_404_139@>
@H_404_139@</head@H_404_139@>
@H_404_139@<body@H_404_139@>
@H_404_139@<style@H_404_139@>
* @H_404_139@{
margin@H_404_139@: 0@H_404_139@;
padding@H_404_139@: 0@H_404_139@;
Box-sizing@H_404_139@: border-Box@H_404_139@;
@H_404_139@}
.container @H_404_139@{
width@H_404_139@: 100%@H_404_139@;
@H_404_139@}
h3 @H_404_139@{
text-align@H_404_139@: center@H_404_139@;
padding@H_404_139@: 30px 0@H_404_139@;
font-size@H_404_139@: 24px@H_404_139@;
@H_404_139@}
p @H_404_139@{
text-align@H_404_139@: center@H_404_139@;
color@H_404_139@: rgb@H_404_139@(62@H_404_139@, 54@H_404_139@, 54@H_404_139@)@H_404_139@;
padding@H_404_139@: 10px 0@H_404_139@;
@H_404_139@}
.row @H_404_139@{
width@H_404_139@: 400px@H_404_139@;
height@H_404_139@: 50px@H_404_139@;
margin@H_404_139@: 0 auto@H_404_139@;
display@H_404_139@: flex@H_404_139@;
justify-content@H_404_139@: center@H_404_139@;
align-items@H_404_139@: center@H_404_139@;
@H_404_139@}
.row span @H_404_139@{
width@H_404_139@: 60px@H_404_139@;
font-size@H_404_139@: 20px@H_404_139@;
@H_404_139@}
.row input @H_404_139@{
width@H_404_139@: 300px@H_404_139@;
height@H_404_139@: 40px@H_404_139@;
line-height@H_404_139@: 40px@H_404_139@;
font-size@H_404_139@: 20px@H_404_139@;
text-indent@H_404_139@: 0.5em@H_404_139@;
/* 去掉输入框的轮廓线 */
outline@H_404_139@: none@H_404_139@;
@H_404_139@}
.row #submit @H_404_139@{
width@H_404_139@: 300px@H_404_139@;
height@H_404_139@: 40px@H_404_139@;
font-size@H_404_139@: 20px@H_404_139@;
line-height@H_404_139@: 40px@H_404_139@;
margin@H_404_139@: 0 auto@H_404_139@;
color@H_404_139@: white@H_404_139@;
background-color@H_404_139@: rgb@H_404_139@(203@H_404_139@, 66@H_404_139@, 157@H_404_139@)@H_404_139@;
/* 去掉边框 */
border@H_404_139@: none@H_404_139@;
border-radius@H_404_139@: 10px@H_404_139@;
@H_404_139@}
.row #submit:active @H_404_139@{
background-color@H_404_139@: gray@H_404_139@;
@H_404_139@}
@H_404_139@</style@H_404_139@>
@H_404_139@<div class=@H_404_139@"container@H_404_139@"@H_404_139@>
@H_404_139@<h3@H_404_139@>表白墙@H_404_139@</h3@H_404_139@>
@H_404_139@<p@H_404_139@>输入后点击提交,会将信息显示在表格中@H_404_139@</p@H_404_139@>
@H_404_139@<div class=@H_404_139@"row@H_404_139@"@H_404_139@>
@H_404_139@<span@H_404_139@>谁: @H_404_139@</span@H_404_139@>
@H_404_139@<input type=@H_404_139@"text@H_404_139@"@H_404_139@>
@H_404_139@</div@H_404_139@>
@H_404_139@<div class=@H_404_139@"row@H_404_139@"@H_404_139@>
@H_404_139@<span@H_404_139@>对谁: @H_404_139@</span@H_404_139@>
@H_404_139@<input type=@H_404_139@"text@H_404_139@"@H_404_139@>
@H_404_139@</div@H_404_139@>
@H_404_139@<div class=@H_404_139@"row@H_404_139@"@H_404_139@>
@H_404_139@<span@H_404_139@>说: @H_404_139@</span@H_404_139@>
@H_404_139@<input type=@H_404_139@"text@H_404_139@"@H_404_139@>
@H_404_139@</div@H_404_139@>
@H_404_139@<div class=@H_404_139@"row@H_404_139@"@H_404_139@>
@H_404_139@<button id=@H_404_139@"submit@H_404_139@"@H_404_139@>提交@H_404_139@</button@H_404_139@>
@H_404_139@</div@H_404_139@>
@H_404_139@</div@H_404_139@>
@H_404_139@<script@H_404_139@>
// 当用户点击 submit,就会获取到 input 中的内容,从而把内容构造成一个 div,插入到页面末尾.
let submitBtn = document@H_404_139@.querySelector@H_404_139@('#submit'@H_404_139@)@H_404_139@;
submitBtn@H_404_139@.onclick = function@H_404_139@(@H_404_139@) @H_404_139@{
// 1. 获取到 3 个 input 中的内容.
let inputs = document@H_404_139@.querySelectorAll@H_404_139@('input'@H_404_139@)@H_404_139@;
let from = inputs@H_404_139@[0@H_404_139@]@H_404_139@.value@H_404_139@;
let to = inputs@H_404_139@[1@H_404_139@]@H_404_139@.value@H_404_139@;
let msg = inputs@H_404_139@[2@H_404_139@]@H_404_139@.value@H_404_139@;
if @H_404_139@(from == '' || to == '' || msg == ''@H_404_139@) @H_404_139@{
// 用户还没填写完,暂时先不提交数据.
return@H_404_139@;
@H_404_139@}
// 2. 生成一个新的 div,内容就是 input 里的内容. 把这个新的 div 加到页面中.
let div = document@H_404_139@.createElement@H_404_139@('div'@H_404_139@)@H_404_139@;
div@H_404_139@.innerHTML = from + ' 对 ' + to + ' 说: ' + msg@H_404_139@;
div@H_404_139@.className = 'row'@H_404_139@;
let container = document@H_404_139@.querySelector@H_404_139@('.container'@H_404_139@)@H_404_139@;
container@H_404_139@.appendChild@H_404_139@(div@H_404_139@)@H_404_139@;
// 3. 清空之前输入框的内容.
for @H_404_139@(let i = 0@H_404_139@; i < inputs@H_404_139@.length@H_404_139@; i++@H_404_139@) @H_404_139@{
inputs@H_404_139@[i@H_404_139@]@H_404_139@.value = ''@H_404_139@;
@H_404_139@}
@H_404_139@}
@H_404_139@</script@H_404_139@>
@H_404_139@</body@H_404_139@>
@H_404_139@</html@H_404_139@>
2. 约定前后端交互接口
所谓 “前后端交互接口” 是进行 Web 开发中的关键环节.
具体来说,就是允许页面给服务器发送哪些 HTTP 请求,并且每种请求预期获取什么样的 HTTP 响 应.
1. 获取全部留言
我们期望浏览器给服务器发送一个 GET /message 这样的请求,就能返回当前一共有哪些留言记
录. 结果以 json 的格式返回过来.
2. 发表新留言
3. 数据存入数据库
我们用数据库来存放信息
创建 messages 表;
drop table if exists messages@H_404_139@;
create table messages @H_404_139@(@H_404_139@`from@H_404_139@` varchar@H_404_139@(1000@H_404_139@)@H_404_139@, @H_404_139@`to@H_404_139@` varchar@H_404_139@(1000@H_404_139@)@H_404_139@, @H_404_139@`message@H_404_139@` varchar@H_404_139@(3000@H_404_139@)@H_404_139@)@H_404_139@;
4.创建 DBUtil 类
用来和数据库交互的,我用的是之前讲过的 JDBC
Mysql 的JDBC 编程
import com@H_404_139@.MysqL@H_404_139@.jdbc@H_404_139@.jdbc2@H_404_139@.optional@H_404_139@.MysqLDataSource@H_404_139@;
import javax@H_404_139@.sql@H_404_139@.DataSource@H_404_139@;
import java@H_404_139@.sql@H_404_139@.Connection@H_404_139@;
import java@H_404_139@.sql@H_404_139@.PreparedStatement@H_404_139@;
import java@H_404_139@.sql@H_404_139@.ResultSet@H_404_139@;
import java@H_404_139@.sql@H_404_139@.sqlException@H_404_139@;
public class DBUtil @H_404_139@{
private static final String URL = "jdbc:MysqL://127.0.0.1:3306/java102?characterEncoding=utf8&useSSL=false"@H_404_139@;
private static final String USERNAME = "root"@H_404_139@;
private static final String PASSWORD = ""@H_404_139@;//自己的密码
private volatile static DataSource dataSource = null@H_404_139@;
private static DataSource getDataSource@H_404_139@(@H_404_139@) @H_404_139@{
if @H_404_139@(dataSource == null@H_404_139@) @H_404_139@{
synchronized @H_404_139@(DBUtil@H_404_139@.class@H_404_139@) @H_404_139@{
if @H_404_139@(dataSource == null@H_404_139@) @H_404_139@{
dataSource = new MysqLDataSource@H_404_139@(@H_404_139@)@H_404_139@;
@H_404_139@(@H_404_139@(MysqLDataSource@H_404_139@)dataSource@H_404_139@)@H_404_139@.setUrl@H_404_139@(URL@H_404_139@)@H_404_139@;
@H_404_139@(@H_404_139@(MysqLDataSource@H_404_139@)dataSource@H_404_139@)@H_404_139@.setUser@H_404_139@(USERNAME@H_404_139@)@H_404_139@;
@H_404_139@(@H_404_139@(MysqLDataSource@H_404_139@)dataSource@H_404_139@)@H_404_139@.setPassword@H_404_139@(PASSWORD@H_404_139@)@H_404_139@;
@H_404_139@}
@H_404_139@}
@H_404_139@}
return dataSource@H_404_139@;
@H_404_139@}
public static Connection getConnection@H_404_139@(@H_404_139@) throws sqlException @H_404_139@{
return getDataSource@H_404_139@(@H_404_139@)@H_404_139@.getConnection@H_404_139@(@H_404_139@)@H_404_139@;
@H_404_139@}
public static void close@H_404_139@(Connection connection@H_404_139@, PreparedStatement statement@H_404_139@, ResultSet resultSet@H_404_139@) @H_404_139@{
if @H_404_139@(resultSet != null@H_404_139@) @H_404_139@{
try @H_404_139@{
resultSet@H_404_139@.close@H_404_139@(@H_404_139@)@H_404_139@;
@H_404_139@} catch @H_404_139@(sqlException e@H_404_139@) @H_404_139@{
e@H_404_139@.printstacktrace@H_404_139@(@H_404_139@)@H_404_139@;
@H_404_139@}
@H_404_139@}
if @H_404_139@(statement != null@H_404_139@) @H_404_139@{
try @H_404_139@{
statement@H_404_139@.close@H_404_139@(@H_404_139@)@H_404_139@;
@H_404_139@} catch @H_404_139@(sqlException e@H_404_139@) @H_404_139@{
e@H_404_139@.printstacktrace@H_404_139@(@H_404_139@)@H_404_139@;
@H_404_139@}
@H_404_139@}
if @H_404_139@(connection != null@H_404_139@) @H_404_139@{
try @H_404_139@{
connection@H_404_139@.close@H_404_139@(@H_404_139@)@H_404_139@;
@H_404_139@} catch @H_404_139@(sqlException e@H_404_139@) @H_404_139@{
e@H_404_139@.printstacktrace@H_404_139@(@H_404_139@)@H_404_139@;
@H_404_139@}
@H_404_139@}
@H_404_139@}
@H_404_139@}
5. 服务器端代码
创建 Message 类
class Message @H_404_139@{
public String from@H_404_139@;
public String to@H_404_139@;
public String message@H_404_139@;
@H_404_139@}
创建 MessageServlet 类
import com@H_404_139@.fasterxml@H_404_139@.jackson@H_404_139@.databind@H_404_139@.ObjectMapper@H_404_139@;
import javax@H_404_139@.servlet@H_404_139@.servletexception@H_404_139@;
import javax@H_404_139@.servlet@H_404_139@.annotation@H_404_139@.WebServlet@H_404_139@;
import javax@H_404_139@.servlet@H_404_139@.http@H_404_139@.HttpServlet@H_404_139@;
import javax@H_404_139@.servlet@H_404_139@.http@H_404_139@.HttpServletRequest@H_404_139@;
import javax@H_404_139@.servlet@H_404_139@.http@H_404_139@.HttpServletResponse@H_404_139@;
import java@H_404_139@.io@H_404_139@.IOException@H_404_139@;
import java@H_404_139@.sql@H_404_139@.Connection@H_404_139@;
import java@H_404_139@.sql@H_404_139@.PreparedStatement@H_404_139@;
import java@H_404_139@.sql@H_404_139@.ResultSet@H_404_139@;
import java@H_404_139@.sql@H_404_139@.sqlException@H_404_139@;
import java@H_404_139@.util@H_404_139@.ArrayList@H_404_139@;
import java@H_404_139@.util@H_404_139@.List@H_404_139@;
@WebServlet@H_404_139@("/message"@H_404_139@)
public class MessageServlet extends HttpServlet @H_404_139@{
//用于转换 JSON 字符串
private ObjectMapper objectMapper = new ObjectMapper@H_404_139@(@H_404_139@)@H_404_139@;
@Override
protected void doPost@H_404_139@(HttpServletRequest req@H_404_139@, IOException @H_404_139@{
// 处理提交消息请求
Message message = objectMapper@H_404_139@.readValue@H_404_139@(req@H_404_139@.getInputStream@H_404_139@(@H_404_139@)@H_404_139@, Message@H_404_139@.class@H_404_139@)@H_404_139@;
// 通过 ContentType 来告知页面,返回的数据是 json 格式.
// 有了这样的声明,此时 jquery ajax 就会自动的帮我们把字符串转成 js 对象.
// 如果没有,jquery ajax 就只是当成字符串来处理的~~
save@H_404_139@(message@H_404_139@)@H_404_139@;
resp@H_404_139@.setContentType@H_404_139@("application/json; charset=utf8"@H_404_139@)@H_404_139@;
resp@H_404_139@.getWriter@H_404_139@(@H_404_139@)@H_404_139@.write@H_404_139@("{ \"ok\": true }"@H_404_139@)@H_404_139@;
@H_404_139@}
@Override
protected void doGet@H_404_139@(HttpServletRequest req@H_404_139@, IOException @H_404_139@{
// 获取到消息列表. 只要把消息列表中的内容整个的都返回给客户端即可
// 此处需要使用 ObjectMapper 把 Java 对象,转成 JSON 格式字符串~
List@H_404_139@<Message@H_404_139@> messages = load@H_404_139@(@H_404_139@)@H_404_139@;
String jsonString = objectMapper@H_404_139@.writeValueAsstring@H_404_139@(messages@H_404_139@)@H_404_139@;
System@H_404_139@.out@H_404_139@.println@H_404_139@("jsonString: " + jsonString@H_404_139@)@H_404_139@;
resp@H_404_139@.setContentType@H_404_139@("application/json; charset=utf8"@H_404_139@)@H_404_139@;
resp@H_404_139@.getWriter@H_404_139@(@H_404_139@)@H_404_139@.write@H_404_139@(jsonString@H_404_139@)@H_404_139@;
@H_404_139@}
private void save@H_404_139@(Message message@H_404_139@) @H_404_139@{
// 把一条消息保存到数据库中
Connection connection = null@H_404_139@;
PreparedStatement statement = null@H_404_139@;
try @H_404_139@{
// 1. 和数据库建立连接
connection = DBUtil@H_404_139@.getConnection@H_404_139@(@H_404_139@)@H_404_139@;
// 2. 构造 sql
String sql = "insert into messages values(?,?,?)"@H_404_139@;
statement = connection@H_404_139@.prepareStatement@H_404_139@(sql@H_404_139@)@H_404_139@;
statement@H_404_139@.setString@H_404_139@(1@H_404_139@, message@H_404_139@.from@H_404_139@)@H_404_139@;
statement@H_404_139@.setString@H_404_139@(2@H_404_139@, message@H_404_139@.to@H_404_139@)@H_404_139@;
statement@H_404_139@.setString@H_404_139@(3@H_404_139@, message@H_404_139@.message@H_404_139@)@H_404_139@;
// 3. 执行 sql
statement@H_404_139@.executeUpdate@H_404_139@(@H_404_139@)@H_404_139@;
@H_404_139@} catch @H_404_139@(sqlException e@H_404_139@) @H_404_139@{
e@H_404_139@.printstacktrace@H_404_139@(@H_404_139@)@H_404_139@;
@H_404_139@} finally @H_404_139@{
DBUtil@H_404_139@.close@H_404_139@(connection@H_404_139@, statement@H_404_139@, null@H_404_139@)@H_404_139@;
@H_404_139@}
@H_404_139@}
private List@H_404_139@<Message@H_404_139@> load@H_404_139@(@H_404_139@) @H_404_139@{
// 从数据库中获取到所有的消息
List@H_404_139@<Message@H_404_139@> messages = new ArrayList@H_404_139@<@H_404_139@>@H_404_139@(@H_404_139@)@H_404_139@;
Connection connection = null@H_404_139@;
PreparedStatement statement = null@H_404_139@;
ResultSet resultSet = null@H_404_139@;
try @H_404_139@{
connection = DBUtil@H_404_139@.getConnection@H_404_139@(@H_404_139@)@H_404_139@;
String sql = "select * from messages"@H_404_139@;
statement = connection@H_404_139@.prepareStatement@H_404_139@(sql@H_404_139@)@H_404_139@;
resultSet = statement@H_404_139@.executeQuery@H_404_139@(@H_404_139@)@H_404_139@;
while @H_404_139@(resultSet@H_404_139@.next@H_404_139@(@H_404_139@)@H_404_139@) @H_404_139@{
Message message = new Message@H_404_139@(@H_404_139@)@H_404_139@;
message@H_404_139@.from = resultSet@H_404_139@.getString@H_404_139@("from"@H_404_139@)@H_404_139@;
message@H_404_139@.to = resultSet@H_404_139@.getString@H_404_139@("to"@H_404_139@)@H_404_139@;
message@H_404_139@.message = resultSet@H_404_139@.getString@H_404_139@("message"@H_404_139@)@H_404_139@;
messages@H_404_139@.add@H_404_139@(message@H_404_139@)@H_404_139@;
@H_404_139@}
@H_404_139@} catch @H_404_139@(sqlException throwables@H_404_139@) @H_404_139@{
throwables@H_404_139@.printstacktrace@H_404_139@(@H_404_139@)@H_404_139@;
@H_404_139@} finally @H_404_139@{
DBUtil@H_404_139@.close@H_404_139@(connection@H_404_139@, resultSet@H_404_139@)@H_404_139@;
@H_404_139@}
return messages@H_404_139@;
@H_404_139@}
@H_404_139@}
6. 调整前端页面
@H_404_139@<script src=@H_404_139@"jquery.js@H_404_139@"@H_404_139@>@H_404_139@</script@H_404_139@>
@H_404_139@<script@H_404_139@>
//加入 ajax 的代码,此处要加入的逻辑有两个部分
//点击提交按钮的时候,ajax 要构造数据发送给服务器
//页面加载的时候,从服务器获取消息列表,并在界面上显示
function getMessages@H_404_139@(@H_404_139@)@H_404_139@{
$@H_404_139@.ajax@H_404_139@(@H_404_139@{
type: "get"@H_404_139@,
url: "message"@H_404_139@,
success: function @H_404_139@(body@H_404_139@)@H_404_139@{
//当前 body 已经是一个 js 对象数组了,ajax 会根据响应的 content type 来自动进行解析.
//如果服务器返回的 content type 已经是 application/json 了,ajax 就会把 body 自动转成 js 的对象
//如果客户端没有自动转,也可以通过 JSON.parse() 这个函数来手动转换
//依次来取数组中的每个元素
let container = document@H_404_139@.querySelector@H_404_139@('.container'@H_404_139@)@H_404_139@;
for@H_404_139@(let message of body@H_404_139@)@H_404_139@{
let div = document@H_404_139@.createElement@H_404_139@('div'@H_404_139@)@H_404_139@;
div@H_404_139@.innerHTML = message@H_404_139@.from + ' 对 ' + message@H_404_139@.to + ' 说: ' + message@H_404_139@.message@H_404_139@;
div@H_404_139@.className = 'row'@H_404_139@;
container@H_404_139@.appendChild@H_404_139@(div@H_404_139@)@H_404_139@;
@H_404_139@}
@H_404_139@}
@H_404_139@}@H_404_139@)@H_404_139@;
@H_404_139@}
//加上函数调用
getMessages@H_404_139@(@H_404_139@)@H_404_139@;
// 当用户点击 submit,内容就是 input 里的内容. 把这个新的 div 加到页面中.
let div = document@H_404_139@.createElement@H_404_139@('div'@H_404_139@)@H_404_139@;
div@H_404_139@.innerHTML = from + ' 对 ' + to + ' 说: ' + msg@H_404_139@;
div@H_404_139@.className = 'row'@H_404_139@;
let container = document@H_404_139@.querySelector@H_404_139@('.container'@H_404_139@)@H_404_139@;
container@H_404_139@.appendChild@H_404_139@(div@H_404_139@)@H_404_139@;
// 3. 清空之前输入框的内容.
for @H_404_139@(let i = 0@H_404_139@; i < inputs@H_404_139@.length@H_404_139@; i++@H_404_139@) @H_404_139@{
inputs@H_404_139@[i@H_404_139@]@H_404_139@.value = ''@H_404_139@;
@H_404_139@}
//4. 把当前获取到的输入框的内容,构造成一个 HTTP POST 请求,通过 ajax 发给服务器body
let body = @H_404_139@{
from: from@H_404_139@,
to: to@H_404_139@,
message: msg
@H_404_139@}@H_404_139@;
$@H_404_139@.ajax@H_404_139@(@H_404_139@{
type: "post"@H_404_139@,
contentType: "application/json;charset=utf8"@H_404_139@,
data: JSON@H_404_139@.stringify@H_404_139@(body@H_404_139@)@H_404_139@,
success: function @H_404_139@(body@H_404_139@)@H_404_139@{
alert@H_404_139@("消息发送成功!"@H_404_139@)@H_404_139@;
@H_404_139@}@H_404_139@,
error: function @H_404_139@(@H_404_139@)@H_404_139@{
alert@H_404_139@("消息发送失败!"@H_404_139@)@H_404_139@;
@H_404_139@}
@H_404_139@}@H_404_139@)
@H_404_139@}
@H_404_139@</script@H_404_139@>
@H_404_139@</body@H_404_139@>
@H_404_139@</html@H_404_139@>
7. 实现效果
这样就算我们刷新,他的数据就不会消失了,做到了"持久保存"
上传文件
方法 | 描述 |
---|---|
Part getPart(String name) | 获取请求中给定 name 的文件 |
Collection getParts() | 获取所有的文件 |
Part类方法
方法 | 描述 |
---|---|
String getSubmittedFileName() | 获取提交的文件名 |
String getContentType() | 获取提交的文件类型 |
long getSize() | 获取文件的大小 |
void write(String path) | 把提交的文件数据写入磁盘文件 |
代码示例
1. 创建 upload.html,放到 webapp 目录中.
@H_404_139@<form action=@H_404_139@"upload@H_404_139@" enctype=@H_404_139@"multipart/form-data@H_404_139@" method=@H_404_139@"POST@H_404_139@"@H_404_139@>
@H_404_139@<input type=@H_404_139@"file@H_404_139@" name=@H_404_139@"MyImage@H_404_139@"@H_404_139@>
@H_404_139@<input type=@H_404_139@"submit@H_404_139@" value=@H_404_139@"提交图片@H_404_139@"@H_404_139@>
@H_404_139@</form@H_404_139@>
2. 创建 UploadServlet 类
import javax@H_404_139@.servlet@H_404_139@.http@H_404_139@.HttpServlet@H_404_139@;
import javax@H_404_139@.servlet@H_404_139@.http@H_404_139@.HttpServletRequest@H_404_139@;
import javax@H_404_139@.servlet@H_404_139@.http@H_404_139@.HttpServletResponse@H_404_139@;
import javax@H_404_139@.servlet@H_404_139@.http@H_404_139@.Part@H_404_139@;
import java@H_404_139@.io@H_404_139@.IOException@H_404_139@;
@MultipartConfig
@WebServlet@H_404_139@("/upload"@H_404_139@)
public class UploadServlet extends HttpServlet @H_404_139@{
@Override
protected void doPost@H_404_139@(HttpServletRequest req@H_404_139@, IOException @H_404_139@{
Part part = req@H_404_139@.getPart@H_404_139@("MyImage"@H_404_139@)@H_404_139@;
System@H_404_139@.out@H_404_139@.println@H_404_139@(part@H_404_139@.getSubmittedFileName@H_404_139@(@H_404_139@)@H_404_139@)@H_404_139@;
System@H_404_139@.out@H_404_139@.println@H_404_139@(part@H_404_139@.getContentType@H_404_139@(@H_404_139@)@H_404_139@)@H_404_139@;
System@H_404_139@.out@H_404_139@.println@H_404_139@(part@H_404_139@.getSize@H_404_139@(@H_404_139@)@H_404_139@)@H_404_139@;
part@H_404_139@.write@H_404_139@("d:/hahaha.jpg"@H_404_139@)@H_404_139@;
resp@H_404_139@.setContentType@H_404_139@("text/html; charset=utf8"@H_404_139@)@H_404_139@;
resp@H_404_139@.getWriter@H_404_139@(@H_404_139@)@H_404_139@.write@H_404_139@("上传成功!"@H_404_139@)@H_404_139@;
@H_404_139@}
@H_404_139@}
注意:
1:需要给 UploadServlet 加上 @MultipartConfig 注解. 否则服务器代码无法使用 getPart 方法
2: getPart 的 参数 需要和 form 中 input 标签的 name 属性对应.
3: 客户端一次可以提交多个文件. (使用多个 input 标签). 此时服务器可以通过 getParts 获取所有的Part 对象.
3. 部署程序:
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。