表白墙项目
目录
需求:
实现服务器来保存用户提交的留言。
1.第一个交互接口:当页面这里用户点击提交的时候,给服务器发送一个请求,把这次的留言信息传给服务器。(往服务器提交数据)
通过ajax来实现:
请求: 响应:
POST/message 200 ok
{ {
from:"黑", ok:1
to:"白", }
message:"喵"
}
2.第二个交互接口:当页面加载的时候,给服务器发送一个请求,把之前已经保存在服务器上的信息获取下来,并展示到页面上。(从服务器上获取数据)
请求: 响应:
GET/message 200 ok
{
{
from:"黑",
to:"白",
message:"喵"
}
}
三个关键对象:
HttpServlet
HttpServletRequest
HttpServletResponse
一.创建maven项目
二.引入依赖
引入servlet 3.1.0
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
引入jackson 最新版本
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.14.1</version>
</dependency>
引入mysql依赖
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.16</version>
</dependency>
三.构造目录
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>
四.写代码
简单网页版:
先写一个简单的后端代码,然后需要重构sayLove.html的前端代码
MessageServlet.java
class Message{
public String from;
public String to;
public String message;
}
@WebServlet("/message")
public class MessageServlet extends HttpServlet {
private ObjectMapper objectMapper = new ObjectMapper();
private List<Message> messageList = new ArrayList<Message>();
@Override
public void init() throws ServletException {
// 给 messageList 构造几个测试数据
// 这个数据的构造可以写道 init 里,也可以写道构造方法里
Message message = new Message();
message.from="黑猫";
message.to="白猫";
message.message= "喵";
messageList.add(message);
message = new Message();
message.from="1";
message.to="2";
message.message= "3";
messageList.add(message);
}
//处理:从服务器获取到消息数据
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("application/json;charset=utf-8");
objectMapper.writeValue(resp.getWriter(),messageList);
}
//处理:从客户端提交数据给服务器
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Message message = objectMapper.readValue(req.getInputStream(),Message.class);
messageList.add(message);
resp.setContentType("application/json;charset=utf-8");
resp.getWriter().write("{\"ok\":1}");
}
}
sayLove.html
添加load()函数
<!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>Document</title>
</head>
<body>
<div class="container">
<h1>表白墙</h1>
<p>输入后点击提交,会将信息显示在墙上</p>
<div class="row">
<span>谁</span>
<input type="text" class="edit">
</div>
<div class="row">
<span>对谁</span>
<input type="text" class="edit">
</div>
<div class="row">
<span>说什么</span>
<input type="text" class="edit">
</div>
<div class="row">
<input type="button" value="提交" id="submit">
</div>
</div>
<!--为了使用ajax需要导入jquery cdn-->
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
<script>
//1.在页面加载的时候,访问服务器,从服务器这边获取消息列表,并展示出来
//2.点击提交按钮的时候,把当前的数据构造一个 HTTP 请求,交给服务器
//页面加载的时候,访问服务器,从服务器这边获取消息队列,并展示出来
function load(){
$.ajax({
type:'GET',
url:'message',
success: function(data, status){
//data 是响应的body,此时的响应可能只是一个字符串格式,可以手动的进行一个解析,按照 json 格式解析成对象
let container = document.querySelector('.container');
let messages = data;
for(let message of messages){
let row = document.createElement('div');
row.className = "row";
row.innerHTML = message.from + "对" +message.to+"说:"+message.message;
container.appendChild(row);
}
}
})
}
load();
let submitButton = document.querySelector('#submit');
submitButton.onclick = function(){
let edits = document.querySelectorAll('.edit');
// console.log(edits);
let from = edits[0].value;
let to = edits[1].value;
let message = edits[2].value;
console.log(from + ',' + to + ',' + message);
if (from == '' || to == '' || message == '') {
return;
}
let row = document.createElement('div');
row.className = 'row';
row.innerHTML = from + '对' + to + '说:' + message;
let container = document.querySelector('.container');
container.appendChild(row);
for (let i = 0; i < edits.length; i++) {
edits[i].value = '';
}
//构造一个 HTTP请求,把消息发给服务器
$.ajax({
type:"POST",
url:"message",
data:JSON.stringify({from:from,to:to,message: message}),
contentType:"application/json; charset=utf-8",
success:function(data,status){
if(data.ok==1){
console.log('提交消息成功!');
}else{
console.log('提交消息失败!');
}
}
})
}
</script>
<style>
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container{
width: 400px;
margin: 0 auto;
}
h1{
text-align: center;
margin: 20px 0;
}
p{
text-align: center;
color: gray;
padding: 10px 0;
font-size: 14px;
}
.row{
height: 50px;
display: flex;
justify-content: center;
align-items: center;
}
span{
width: 120px;
font-size: 20px;
}
input{
width: 310px;
height: 40px;
font-size: 30px;
}
#submit{
width: 400px;
color: white;
background-color: orange;
border: none;
border-radius: 5px;
font-size: 25px;
}
#submit:active{
background-color: black;
}
.edit{
font-size: 18px;
padding-left: 5px;
}
</style>
</body>
</html>
运行结果:
即使刷新页面,依旧有三条消息
fiddler抓包:
输入3;3;3
服务器版:
DBUtil.java
public class DBUtil {
private static final String URL="jdbc:mysql://127.0.0.1:3306/java100?useSSL=false&characterEncoding=utf-8&serverTimezone=GMT%2B8";
private static final String USERNAME ="root";
private static final String PASSWORD = "123456";
private static volatile DataSource dataSource = null;
private static DataSource getDataSource(){
if (dataSource == null){
synchronized (DBUtil.class){
if (dataSource == null){
dataSource = new MysqlDataSource();
((MysqlDataSource)dataSource).setURL(URL);
((MysqlDataSource)dataSource).setUser(USERNAME);
((MysqlDataSource)dataSource).setPassword(PASSWORD);
}
}
}
return dataSource;
}
public static Connection getConnection() throws SQLException {
return getDataSource().getConnection();
}
public static void close(Connection connection, PreparedStatement statement, ResultSet resultSet){
if (resultSet != null){
try {
resultSet.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (statement != null){
try {
statement.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (connection != null){
try {
connection.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
MessageServlet
class Message{
public String from;
public String to;
public String message;
}
@WebServlet("/message")
public class MessageServlet extends HttpServlet {
private ObjectMapper objectMapper = new ObjectMapper();
private List<Message> messageList = new ArrayList<Message>();
// @Override
// public void init() throws ServletException {
// // 给 messageList 构造几个测试数据
// // 这个数据的构造可以写道 init 里,也可以写道构造方法里
// Message message = new Message();
// message.from="黑猫";
// message.to="白猫";
// message.message= "喵";
// messageList.add(message);
//
// message = new Message();
// message.from="1";
// message.to="2";
// message.message= "3";
// messageList.add(message);
// }
//处理:从服务器获取到消息数据
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("application/json;charset=utf-8");
List<Message> messageList = load();
objectMapper.writeValue(resp.getWriter(),messageList);
}
private List<Message> load() {
List<Message> messageList = new ArrayList<>();
System.out.println("从数据库中获取数据");
Connection connection = null;
PreparedStatement statement = null;
ResultSet resultSet = null;
try {
connection = DBUtil.getConnection();
String sql = "select * from message";
statement = connection.prepareStatement(sql);
resultSet = statement.executeQuery();
while (resultSet.next()) {
Message message = new Message();
message.from = resultSet.getString("from");
message.to = resultSet.getString("to");
message.message = resultSet.getString("message");
messageList.add(message);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtil.close(connection, statement, resultSet);
}
return messageList;
}
//处理:从客户端提交数据给服务器
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Message message = objectMapper.readValue(req.getInputStream(),Message.class);
//messageList.add(message);
save(message);
resp.setContentType("application/json;charset=utf-8");
resp.getWriter().write("{\"ok\":1}");
}
private void save(Message message) {
System.out.println("向数据库写入数据");
//1.先和数据库建立链接
Connection connection = null;
PreparedStatement statement = null;
try {
//先和数据库建立连接
connection = DBUtil.getConnection();
//构造拼装 SQL
String sql = "insert into message values (?,?,?)";
statement = connection.prepareStatement(sql);
statement.setString(1,message.from);
statement.setString(2,message.to);
statement.setString(3,message.message);
//执行 SQL
int ret = statement.executeUpdate();
if (ret == 1){
System.out.println("插入成功");
}else {
System.out.println("插入失败");
}
}catch (SQLException e){
e.printStackTrace();
}finally {
DBUtil.close(connection,statement,null);
}
}
}
sayLove.html
<!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>Document</title>
</head>
<body>
<div class="container">
<h1>表白墙</h1>
<p>输入后点击提交,会将信息显示在墙上</p>
<div class="row">
<span>谁</span>
<input type="text" class="edit">
</div>
<div class="row">
<span>对谁</span>
<input type="text" class="edit">
</div>
<div class="row">
<span>说什么</span>
<input type="text" class="edit">
</div>
<div class="row">
<input type="button" value="提交" id="submit">
</div>
</div>
<!--为了使用ajax需要导入jquery cdn-->
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
<script>
//1.在页面加载的时候,访问服务器,从服务器这边获取消息列表,并展示出来
//2.点击提交按钮的时候,把当前的数据构造一个 HTTP 请求,交给服务器
//页面加载的时候,访问服务器,从服务器这边获取消息队列,并展示出来
function load(){
$.ajax({
type:'GET',
url:'message',
success: function(data, status){
//data 是响应的body,此时的响应可能只是一个字符串格式,可以手动的进行一个解析,按照 json 格式解析成对象
let container = document.querySelector('.container');
let messages = data;
for(let message of messages){
let row = document.createElement('div');
row.className = "row";
row.innerHTML = message.from + "对" +message.to+"说:"+message.message;
container.appendChild(row);
}
}
})
}
load();
let submitButton = document.querySelector('#submit');
submitButton.onclick = function(){
let edits = document.querySelectorAll('.edit');
// console.log(edits);
let from = edits[0].value;
let to = edits[1].value;
let message = edits[2].value;
console.log(from + ',' + to + ',' + message);
if (from == '' || to == '' || message == '') {
return;
}
let row = document.createElement('div');
row.className = 'row';
row.innerHTML = from + '对' + to + '说:' + message;
let container = document.querySelector('.container');
container.appendChild(row);
for (let i = 0; i < edits.length; i++) {
edits[i].value = '';
}
//构造一个 HTTP请求,把消息发给服务器
$.ajax({
type:"POST",
url:"message",
data:JSON.stringify({from:from,to:to,message: message}),
contentType:"application/json; charset=utf-8",
success:function(data,status){
if(data.ok==1){
console.log('提交消息成功!');
}else{
console.log('提交消息失败!');
}
}
})
}
</script>
<style>
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container{
width: 400px;
margin: 0 auto;
}
h1{
text-align: center;
margin: 20px 0;
}
p{
text-align: center;
color: gray;
padding: 10px 0;
font-size: 14px;
}
.row{
height: 50px;
display: flex;
justify-content: center;
align-items: center;
}
span{
width: 120px;
font-size: 20px;
}
input{
width: 310px;
height: 40px;
font-size: 30px;
}
#submit{
width: 400px;
color: white;
background-color: orange;
border: none;
border-radius: 5px;
font-size: 25px;
}
#submit:active{
background-color: black;
}
.edit{
font-size: 18px;
padding-left: 5px;
}
</style>
</body>
</html>
运行结果:
五.打包,部署(基于tomcat实现)
补充:
1.web开发中最关键的步骤:交互接口的约定
写程序时,需要先约定好页面和服务器之间,要按照什么样的方式来交互,页面给服务器发送什么样的请求,服务器返回什么样的响应
2.web开发中,服务器起到的作用:
服务器起到处理数据和提供数据的作用。
注:其中客服端和服务器所约定的请求什么,响应什么…一个个的约定,就可以称为服务器提供的API/接口。
3.前后端交互接口约定和自定义协议的关系:
此处的“前后端交互接口”约定,这个工作就是咱们之前在讲’应用层协议‘时说到的’自定义协议‘过程。