当前位置: 首页 > news >正文

JavaWeb项目-----博客系统

一.设计数据库

1.创建数据库

create database if not exists java108_blog_system character set utf8;
drop table if exists user;
drop table if exists blog;

2.创建博客列表

create table blog(blogId int primary key auto_increment,title varchar(20),content varchar(4006),userId int,postTime datetime
);

3.创建用户列表

create table user(
userId int primary key auto_increment,
username varchar(64) unique,
password varchar(64)
);

4.确认表创建成功

insert into user values(1,"zhangsan","123"),(2,"lisi","123");
insert into blog values(1,"这是我的第一篇博客","从今天开始我要好好写代码",1,"2024-07-14 19:00:00");
insert into blog values(2,"这是我的第二篇博客","从昨天开始我要好好写代码",2,"2024-07-14 19:00:01");
insert into blog values(3,"这是我的第三篇博客","从明天开始我要好好写代码",3,"2024-07-14 19:00:02");

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

二.封装数据库

创建包Dao用来放数据库代码
在这里插入图片描述

1.创建Dbuc类

数据库建立连接

package Dao;import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;public class Dbuc {private static DataSource dataSource = null;private static DataSource getDataSource(){if(dataSource==null){synchronized (Dbuc.class){if(dataSource==null){dataSource=new MysqlDataSource();((MysqlDataSource) dataSource).setUrl("jdbc:mysql://127.0.0.1/java108_blog_system?characterEncoding=utf8&useSSL=false");((MysqlDataSource)dataSource).setUser("root");
//                    ((MysqlDataSource)dataSource).setUser("java108");((MysqlDataSource)dataSource).setPassword("123456");}}}return dataSource;}public static Connection getConnect() throws SQLException {return getDataSource().getConnection();}public static void close(Connection connection, PreparedStatement preparedStatement, ResultSet resultSet) throws SQLException {if(resultSet!=null){resultSet.close();}if(connection!=null){connection.close();}if(preparedStatement!=null){preparedStatement.close();}}}

2.创建博客类

public class Blog {public int blogId;public String  title;public String content;public int  userId;@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")public Timestamp postTime;@Overridepublic String toString() {return "Blog{" +"blogId=" + blogId +", title='" + title + '\'' +", content='" + content + '\'' +", userId=" + userId +", postTime=" + postTime +'}';}}

3.创建用户类

package Dao;public class User {public int  userId;public String username;public String  password;@Overridepublic String toString() {return "User{" +"userId=" + userId +", username='" + username + '\'' +", password='" + password + '\'' +'}';}
}

4.封装博客增删查改

package Dao;import javax.xml.transform.Result;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;public class BlogDao {public void insert(Blog blog) throws SQLException {Connection connection = Dbuc.getConnect();String sql = "insert into blog values(null,?,?,?,now())";PreparedStatement preparedStatement = connection.prepareStatement(sql);preparedStatement.setString(1,blog.title);preparedStatement.setString(2,blog.content);preparedStatement.setInt(3,blog.userId);preparedStatement.executeUpdate();Dbuc.close(connection,preparedStatement,null);}public List<Blog> getBlogs() throws SQLException {List<Blog> list1= new ArrayList<>();Connection connection = Dbuc.getConnect();String sql = "select* from blog order by postTime desc";PreparedStatement preparedStatement = connection.prepareStatement(sql);ResultSet resultSet= preparedStatement.executeQuery();while(resultSet.next()){Blog blog = new Blog();blog.blogId = resultSet.getInt("blogId");blog.title=resultSet.getString("title");blog.content=resultSet.getString("content");blog.userId=resultSet.getInt("userId");blog.postTime=resultSet.getTimestamp("postTime");list1.add(blog);}Dbuc.close(connection,preparedStatement,resultSet);return list1;}
public Blog getBlog(int blogId) throws SQLException {Connection connection = Dbuc.getConnect();String sql = "select* from blog where  blogId=?";PreparedStatement preparedStatement = connection.prepareStatement(sql);preparedStatement.setInt(1,blogId);ResultSet resultSet= preparedStatement.executeQuery();if(resultSet.next()){Blog blog = new Blog();blog.blogId = resultSet.getInt("blogId");blog.title=resultSet.getString("title");blog.content=resultSet.getString("content");blog.userId=resultSet.getInt("userId");blog.postTime=resultSet.getTimestamp("postTime");return blog;}Dbuc.close(connection,preparedStatement,resultSet);return null;
}
public void delete(int blogId) throws SQLException {Connection connection = Dbuc.getConnect();String sql = "delete from blog where blogId=?";PreparedStatement preparedStatement = connection.prepareStatement(sql);preparedStatement.setInt(1,blogId);preparedStatement.executeUpdate();Dbuc.close(connection,preparedStatement,null);
}
}

5.封装用户类增删查改

package Dao;import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;public class UserDao {public User getUserById(int userId) throws SQLException {Connection connection = Dbuc.getConnect();String  sql = "select* from user where userId=?";PreparedStatement preparedStatement = connection.prepareStatement(sql);preparedStatement.setInt(1,userId);ResultSet resultSet = preparedStatement.executeQuery();if(resultSet.next()){User user = new User();user.userId=resultSet.getInt("userId");user.password=resultSet.getString("password");user.username=resultSet.getString("username");return user;}Dbuc.close(connection,preparedStatement,resultSet);return null;}public User getUserByName(String username) throws SQLException {Connection connection = Dbuc.getConnect();String  sql = "select* from user where username=?";PreparedStatement preparedStatement = connection.prepareStatement(sql);preparedStatement.setString(1,username);ResultSet resultSet = preparedStatement.executeQuery();if(resultSet.next()){User user = new User();user.userId=resultSet.getInt("userId");user.password=resultSet.getString("password");user.username=resultSet.getString("username");return user;}Dbuc.close(connection,preparedStatement,resultSet);return null;}
}

三.博客详情页

package api;import Dao.Blog;
import Dao.BlogDao;
import Dao.User;
import com.fasterxml.jackson.databind.ObjectMapper;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;
import java.sql.SQLException;
import java.util.List;@WebServlet("/blog")
public class BlogServlet extends HttpServlet {private ObjectMapper objectMapper = new ObjectMapper();@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {BlogDao  blogDao = new BlogDao();String blogId = req.getParameter("blogId");if(blogId==null){List<Blog> blogs = null;try {blogs = blogDao.getBlogs();} catch (SQLException e) {throw new RuntimeException(e);}String res = objectMapper.writeValueAsString(blogs);resp.setContentType("appliaction/jason;charset=utf8");resp.getWriter().write(res);}else{Blog blog = null;try {blog = blogDao.getBlog(Integer.parseInt(blogId));} catch (SQLException e) {throw new RuntimeException(e);}String str = objectMapper.writeValueAsString(blog);resp.setContentType("application/json;charset=utf8");resp.getWriter().write(str);}}

如果前端没有传入指定id那么展示全部内容,如果传入指定id查询指定用户博客。

在这里插入图片描述
通过抓包观察:
在这里插入图片描述

2.检测用户是否登录

如果用户未登录是不能跳转到博客列表的页面

@Overrideprotected void doPost(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;}User user = (User) session.getAttribute("user");if (user == null) {resp.setContentType("text/html; charset=utf8");resp.getWriter().write("用户未登录! 无法发布博客!");return;}req.setCharacterEncoding("utf8");String title = req.getParameter("title");String content = req.getParameter("content");if (title == null || content == null || "".equals(title) || "".equals(content)) {resp.setContentType("text/html; charset=utf8");resp.getWriter().write("标题或者正文为空");return;}Blog blog = new Blog();blog.title=title;blog.userId=user.userId;blog.content=content;BlogDao blogDao = new BlogDao();try {blogDao.insert(blog);} catch (SQLException e) {throw new RuntimeException(e);}resp.sendRedirect("blog_list.html");}

主要功能是处理博客发布相关的操作。首先,它会检查用户是否登录,通过获取用户会话(HttpSession),如果会话不存在或者从会话中获取不到代表用户的User对象,就会向客户端返回“用户未登录! 无法发布博客!”的提示并终止方法执行。如果用户已登录,它会从POST请求中获取博客的标题(title)和内容(content),并且对获取到的标题和内容进行验证,如果标题或者内容为空(null或者空字符串),则向客户端返回“标题或者正文为空”的提示并终止方法。如果标题和内容都有效,它会创建一个Blog对象,将从请求中获取到的标题和内容以及从用户对象中获取到的用户ID设置到Blog对象的属性中。然后通过BlogDao将博客对象插入到数据库中。最后,如果博客插入成功,将客户端重定向到blog_list.html页面,展示博客列表的页面。

在这里插入图片描述

在这里插入图片描述

3.用户登录

package api;import Dao.User;
import Dao.UserDao;
import utils.CloudSmsUtil;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;
import java.sql.SQLException;
@WebServlet("/login")
public class LoginSevlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {req.setCharacterEncoding("utf8");String usename = req.getParameter("username");String password=req.getParameter("password");String phone = req.getParameter("phone");String code = req.getParameter("code");if(usename==null||password==null||"".equals(usename)||"".equals(password)||"".equals(phone)||"".equals(code)){resp.setContentType("text/html;charset=utf8");resp.getWriter().write("传过来数值错误");return;}String inoutCode = CloudSmsUtil.PHONE_CODE_MAP.get(phone);if (!code.equals(inoutCode)) {resp.setContentType("text/html;charset=utf8");resp.getWriter().write("验证码错误");return;}UserDao userDao = new UserDao();User user = null;try {user = userDao.getUserByName(usename);} catch (SQLException e) {throw new RuntimeException(e);}if(user==null){resp.setContentType("text/html;charset=utf8");resp.getWriter().write("查无此人");return;}if(!password.equals(user.password)){resp.setContentType("text/html;charset=utf8");resp.getWriter().write("密码错误");return;}HttpSession httpSession = req.getSession(true);httpSession.setAttribute("user",user);resp.sendRedirect("blog_list.html");}
package utils;import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;import java.util.HashMap;
import java.util.Map;public class CloudSmsUtil {private final static String accessKeyId = "LTAI5tEqaD59ckPYDhhxJ3ZF";private final static String accessKeySecret = "x6aD71AB7NmKhlayqhGIN1nt44M0TG";private final static String showStartNoticeTemplate = "SMS_474960284";private final static String signName = "我的学习路";/**ali固定配置参数begin*///短信API产品名称static final String product="Dysmsapi";//短信API产品域名static final String domain="dysmsapi.aliyuncs.com";/**ali固定配置参数end*/public final static Map<String, String> PHONE_CODE_MAP = new HashMap<>();public static boolean sendCheckCode(String phone, String code) {JSONObject params = new JSONObject();params.put("code", code);return  aliSmsSendMsg(showStartNoticeTemplate, phone, params);}private static boolean aliSmsSendMsg(String templateCode, String phone, JSONObject params) {//		System.out.println("alibaba-phone:" + phone + "-code:" + code);System.out.println("配置信息");System.out.println("accessKeyId:" + accessKeyId);System.out.println("accessKeySecret:" + accessKeySecret);System.out.println("signName:" + signName);System.out.println("templateCode:" + templateCode);try {//设置超时时间System.setProperty("sun.net.client.defaultConnectTimeout", "10000");System.setProperty("sun.net.client.defaultReadTimeout", "10000");//初始化ascClientIClientProfile profile= DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessKeySecret);DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", product, domain);IAcsClient acsClient=new DefaultAcsClient(profile);//组装请求对象SendSmsRequest request=new SendSmsRequest();//使用post提交request.setMethod(MethodType.POST);//待发送的手机号request.setPhoneNumbers(phone);//短信签名request.setSignName(signName);//短信模板IDrequest.setTemplateCode(templateCode);/** 可选:模板中的变量替换JSON串,* 如模板内容为"亲爱的${name},您的验证码为${code}"时,* 此处的值为{"name":"Tom","code":"1454"}*   \  反斜杠为转义字符,使得输出双引号*/request.setTemplateParam(params.toString());//可选:outId为提供给业务方扩展字段,最终在短信回执消息中将此值带回给调用者//request.setOutId("1454");SendSmsResponse response=acsClient.getAcsResponse(request);System.out.println(response.getCode() + ":" + response.getMessage());if(response.getCode() != null && response.getCode().equals("OK")) {//请求成功System.out.println("发送成功!");return true;}else {System.out.println(StrUtil.format("发送失败!{}", response.getCode() + ":" + response.getMessage()));return false;}} catch (ServerException e) {e.printStackTrace();return false;} catch (ClientException e) {e.printStackTrace();return false;}}
}
package api;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("/logout")
public class LogouServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {HttpSession httpSession = req.getSession(false);if(httpSession==null){resp.sendRedirect("login.html");return;}httpSession.removeAttribute("user");resp.sendRedirect("login.html");}
}
package api;import Dao.User;
import Dao.UserDao;
import cn.hutool.core.util.RandomUtil;
import utils.CloudSmsUtil;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;
import java.sql.SQLException;@WebServlet("/sendCode")
public class SendSmsCodeSevlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {req.setCharacterEncoding("utf8");String phone = req.getParameter("phone");String code = RandomUtil.randomNumbers(4);boolean b = CloudSmsUtil.sendCheckCode(phone, code);
//        resp.setContentType("application/json;charset=utf8");if (b) {System.out.println("[发送验证码]-----------------------验证码为:"+ code);CloudSmsUtil.PHONE_CODE_MAP.put(phone, code);resp.getWriter().write("1");} else {resp.getWriter().write("0");}}@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doPost(req, resp);}
}

在这里插入图片描述

在这里插入图片描述

四.新增博客

package Dao;import javax.xml.transform.Result;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;public class BlogDao {public void insert(Blog blog) throws SQLException {Connection connection = Dbuc.getConnect();String sql = "insert into blog values(null,?,?,?,now())";PreparedStatement preparedStatement = connection.prepareStatement(sql);preparedStatement.setString(1,blog.title);preparedStatement.setString(2,blog.content);preparedStatement.setInt(3,blog.userId);preparedStatement.executeUpdate();Dbuc.close(connection,preparedStatement,null);}public List<Blog> getBlogs() throws SQLException {List<Blog> list1= new ArrayList<>();Connection connection = Dbuc.getConnect();String sql = "select* from blog order by postTime desc";PreparedStatement preparedStatement = connection.prepareStatement(sql);ResultSet resultSet= preparedStatement.executeQuery();while(resultSet.next()){Blog blog = new Blog();blog.blogId = resultSet.getInt("blogId");blog.title=resultSet.getString("title");blog.content=resultSet.getString("content");blog.userId=resultSet.getInt("userId");blog.postTime=resultSet.getTimestamp("postTime");list1.add(blog);}Dbuc.close(connection,preparedStatement,resultSet);return list1;}
public Blog getBlog(int blogId) throws SQLException {Connection connection = Dbuc.getConnect();String sql = "select* from blog where  blogId=?";PreparedStatement preparedStatement = connection.prepareStatement(sql);preparedStatement.setInt(1,blogId);ResultSet resultSet= preparedStatement.executeQuery();if(resultSet.next()){Blog blog = new Blog();blog.blogId = resultSet.getInt("blogId");blog.title=resultSet.getString("title");blog.content=resultSet.getString("content");blog.userId=resultSet.getInt("userId");blog.postTime=resultSet.getTimestamp("postTime");return blog;}Dbuc.close(connection,preparedStatement,resultSet);return null;
}
public void delete(int blogId) throws SQLException {Connection connection = Dbuc.getConnect();String sql = "delete from blog where blogId=?";PreparedStatement preparedStatement = connection.prepareStatement(sql);preparedStatement.setInt(1,blogId);preparedStatement.executeUpdate();Dbuc.close(connection,preparedStatement,null);
}
}

在这里插入图片描述

五.获取个人ID

package api;import Dao.Blog;
import Dao.BlogDao;
import Dao.User;
import Dao.UserDao;
import com.fasterxml.jackson.databind.ObjectMapper;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;
import java.sql.SQLException;@WebServlet("/user")
public class UserServlet extends HttpServlet {private ObjectMapper objectMapper = new ObjectMapper();@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String blogId = req.getParameter("blogId");if (blogId == null) {HttpSession session = req.getSession(false);if (session == null) {User user = new User();String respJson = objectMapper.writeValueAsString(user);resp.setContentType("application/json; charset=utf8");resp.getWriter().write(respJson);return;}User user = (User) session.getAttribute("user");if (user == null) {user = new User();String respJson = objectMapper.writeValueAsString(user);resp.setContentType("application/json; charset=utf8");resp.getWriter().write(respJson);return;}String respJson = objectMapper.writeValueAsString(user);resp.setContentType("application/json; charset=utf8");resp.getWriter().write(respJson);} else {BlogDao blogDao = new BlogDao();Blog blog = null;try {blog = blogDao.getBlog(Integer.parseInt(blogId));} catch (SQLException e) {throw new RuntimeException(e);}if (blog == null) {User user = new User();String respJson = objectMapper.writeValueAsString(user);resp.setContentType("application/json; charset=utf8");resp.getWriter().write(respJson);return;}UserDao userDao = new UserDao();User user = null;try {user = userDao.getUserById(blog.userId);} catch (SQLException e) {throw new RuntimeException(e);}if (user == null) {user = new User();String respJson = objectMapper.writeValueAsString(user);resp.setContentType("application/json; charset=utf8");resp.getWriter().write(respJson);return;}String respJson = objectMapper.writeValueAsString(user);resp.setContentType("application/json; charset=utf8");resp.getWriter().write(respJson);}}
}

在这里插入图片描述

六.总效果展示

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

七.总代码

1.代码分层

在这里插入图片描述

2.前端代码

!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><link rel="stylesheet" href="css/common.css"><link rel="stylesheet" href="css/blog_detail.css"><!-- 一定要引入 editormd 的依赖, 才能使用这里的方法 --><script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script><link rel="stylesheet" href="editor.md/css/editormd.min.css" /><script src="editor.md/lib/marked.min.js"></script><script src="editor.md/lib/prettify.min.js"></script><script src="editor.md/editormd.js"></script>
</head>
<body>
<!-- 导航栏. nav 是 导航 这个词的缩写 -->
<div class="nav"><!-- logo --><img src="image/logo2.jpg" alt=""><div class="title">我的博客系统</div><!-- 只是一个空白, 用来把后面的链接挤过去 --><!-- 这是一个简单粗暴的写法~~ --><div class="spacer"></div><a href="blog_list.html">主页</a><a href="blog_edit.html">写博客</a><!-- 这里的地址回头再说 --><a href="logout">注销</a>
</div>
<!-- 页面的主体部分 -->
<div class="container"><!-- 左侧信息 --><div class="container-left"><!-- 这个 div 表示整个用户信息的区域 --><div class="card"><!-- 用户的头像 --><img src="image/kun.jpg" alt=""><!-- 用户名 --><h3>小新要加油</h3><!-- github 地址 --><a href="https://www.github.com">github 地址</a><!-- 统计信息 --><div class="counter"><span>文章</span><span>分类</span></div><div class="counter"><span>2</span><span>1</span></div></div></div><!-- 右侧信息 --><div class="container-right"><h3>这是我的第一篇博客</h3><div class="date">2023-05-11 20:00:00</div><div class="content"><h3></h3><div class="date"></div><div id="content"></div></div></div><script src="js/app.js"></script><script>function getUrlParam(url, paramName) {const reg = new RegExp('(^|&)' + paramName + '=([^&]*)(&|$)', 'i');const result = url.slice(url.indexOf('?') + 1).match(reg);if (result !== null) {return decodeURIComponent(result[2]);}return null;}function getBlog(blogId) {$.ajax({url: 'blog?blogId=' + blogId,type: 'get',success: function(body) {// body = JSON.parse(body)// 根据拿到的响应数据, 构造页面内容.let h3 = document.querySelector('.container-right h3');h3.innerHTML = body.title;let dateDiv = document.querySelector('.container-right .date');dateDiv.innerHTML = body.postTime;editormd.markdownToHTML('content', { markdown: body.content });}});}getBlog(getUrlParam(window.location.href, 'blogId'));checkLogin();function getUser() {$.ajax({type: 'get',url: 'user' + location.search,success: function(body) {// body 就是解析后的 user 对象了.let h3 = document.querySelector('.card h3');h3.innerHTML = body.username;}})}getUser();</script>
</body>
</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>博客编辑页</title><link rel="stylesheet" href="css/common.css"><link rel="stylesheet" href="css/blog_edit.css"><script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script><!-- 引入 editor.md 的依赖 --><link rel="stylesheet" href="editor.md/css/editormd.min.css" /><script src="editor.md/lib/marked.min.js"></script><script src="editor.md/lib/prettify.min.js"></script><script src="editor.md/editormd.js"></script>
</head>
<body>
<!-- 导航栏. nav 是 导航 这个词的缩写 -->
<div class="nav"><!-- logo --><img src="image/logo2.jpg" alt=""><div class="title">我的博客系统</div><!-- 只是一个空白, 用来把后面的链接挤过去 --><!-- 这是一个简单粗暴的写法~~ --><div class="spacer"></div><a href="blog_list.html">主页</a><a href="blog_edit.html">写博客</a><!-- 这里的地址回头再说 --><a href="logout">注销</a>
</div><!-- 博客编辑页的版心 -->
<div class="blog-edit-container"><form action="blog" method="post"><!-- 标题编辑区 --><div class="title"><input type="text" id="title-input" name="title"><input type="submit" id="submit"></div><!-- 博客编辑器 --><!-- 把 md 编辑器放到这个 div 中 --><div id="editor"><textarea name="content" style="display: none"></textarea></div></form>
</div><script src="js/app.js"></script>
<script>var editor = editormd("editor", {// 这里的尺寸必须在这里设置. 设置样式会被 editormd 自动覆盖掉.width: "100%",// 设定编辑器高度height: "calc(100% - 50px)",// 编辑器中的初始内容markdown: "# 在这里写下你的留言",// 指定 editor.md 依赖的插件路径path: "editor.md/lib/"});checkLogin();
</script>
</body>
</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>博客列表页</title><link rel="stylesheet" href="css/common.css"><link rel="stylesheet" href="css/blog_list.css">
</head>
<body>
<!-- 导航栏. nav 是 导航 这个词的缩写 -->
<div class="nav"><!-- logo --><img src="image/logo2.jpg" alt=""><div class="title">我的博客系统</div><!-- 只是一个空白, 用来把后面的链接挤过去 --><!-- 这是一个简单粗暴的写法~~ --><div class="spacer"></div><a href="blog_list.html">主页</a><a href="blog_edit.html">写博客</a><!-- 这里的地址回头再说 --><a href="logout">注销</a>
</div><!-- 页面的主体部分 -->
<div class="container"><!-- 左侧信息 --><div class="container-left"><!-- 这个 div 表示整个用户信息的区域 --><div class="card"><!-- 用户的头像 --><img src="image/kun.jpg" alt=""><!-- 用户名 --><h3>勇敢的小新</h3><!-- github 地址 --><a href="https://www.github.com">github 地址</a><!-- 统计信息 --><div class="counter"><span>文章</span><span>分类</span></div><div class="counter"><span>2</span><span>1</span></div></div></div><!-- 右侧信息 --><div class="container-right"><!-- <div class="blog"><div class="title">我的第一篇博客博客博客博客</div><div class="date">2023-05-11 20:00:00</div><div class="desc">从今天起, 我要认真敲代码. Lorem ipsum dolor sit amet consectetur, adipisicing elit. Debitis repellendus voluptatum, reiciendis rem consectetur incidunt aspernatur eveniet excepturi magni quis sint, provident est at et pariatur dolorem aliquid fugit voluptatem.</div><a href="blog_detail.html?blogId=1">查看全文 &gt;&gt; </a></div> --></div>
</div>
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
<script src="js/app.js"></script>
<script>// 编写 js 代码.// 构造 http 请求, 获取到博客列表数据, 并展示到页面上.function getBlogs() {$.ajax({type: 'get',url: 'blog',success: function(body) {// 就需要根据响应的内容, 构造出 html 片段, 展示到页面上.// 由于服务器响应中已经设置了 Content-Type 为 application/json, 此时// jQuery 就能够自动的把此处响应的内容解析成 js 对象数组.let containter = document.querySelector('.container-right');debuggerfor (let blog of JSON.parse(body)) {// 根据当前这个 blog 构造出一个 html 片段.let blogDiv = document.createElement('div');blogDiv.className = 'blog';// 构造标题let titleDiv = document.createElement('div');titleDiv.className = 'title';titleDiv.innerHTML = blog.title;blogDiv.appendChild(titleDiv);// 构造发布时间let dateDiv = document.createElement('div');dateDiv.className = 'date';dateDiv.innerHTML = blog.postTime;blogDiv.appendChild(dateDiv);// 构造摘要信息let descDiv = document.createElement('div');descDiv.className = 'desc';descDiv.innerHTML = blog.content;blogDiv.appendChild(descDiv);// 构造 "查看全文" 按钮let a = document.createElement("a");a.href = 'blog_detail.html?blogId=' + blog.blogId;a.innerHTML = '查看全文 &gt;&gt;';blogDiv.appendChild(a);// 最后把拼好的 blogDiv 添加到 container 的后面containter.appendChild(blogDiv);}}});}getBlogs();checkLogin();function getUser() {$.ajax({type: 'get',url: 'user',success: function(body) {// body 就是解析后的 user 对象了.let h3 = document.querySelector('.card h3');h3.innerHTML = body.username;}})}getUser();</script>
</body>
</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>博客登录页</title><link rel="stylesheet" href="css/common.css"><link rel="stylesheet" href="css/login.css">
</head>
<body>
<!-- 导航栏. nav 是 导航 这个词的缩写 -->
<div class="nav"><!-- logo --><img src="image/logo2.jpg" alt=""><div class="title">电信ydx的博客系统</div><!-- 只是一个空白, 用来把后面的链接挤过去 --><!-- 这是一个简单粗暴的写法~~ --><div class="spacer"></div><a href="blog_list.html">主页</a><a href="blog_edit.html">写博客</a>
</div><!-- 登录页的版心 -->
<div class="login-container"><!-- 登录对话框 --><div class="login-dialog"><h3>登录</h3><!-- 使用 form 包裹一下下列内容, 便于后续给服务器提交数据 --><form action="login" method="post"><div class="row"><span>用户名</span><input type="text" id="username" name="username"></div><div class="row"><span>密码</span><input type="password" id="password" name="password"></div><div class="row"><span>手机号</span><input type="text" id="phone" name="phone"><button id="sendCode">发送验证码</button></div><div class="row" id="phoneCheckCode" style="display: none"><span>验证码</span><input type="text" id="code" name="code"></div><div class="row" id="sendPhoneCheckCode"></div><div class="row"><input type="submit" id="submit" value="登录"></div></form></div>
</div>
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
<script src="js/app.js"></script>
<script>document.getElementById('sendCode').addEventListener('click', function(event) {event.preventDefault();// 这里可以添加其他逻辑$('#sendCode').on('click', function() {var phone = $("#phone").val()$.ajax({type: 'get',url: 'sendCode?phone='+phone,success: function(body) {if (body=="0") {alert("发送失败")return} else {alert("发送成功")$("#sendCode").hide()$("#phoneCheckCode").show()return;}}});});});$(document).ready(function() {// 在这里写入需要在页面加载后执行的代码console.log('页面已加载完毕!');});</script>
</body>
</html>

3.后端代码

1.api

package api;import Dao.Blog;
import Dao.BlogDao;
import Dao.User;
import com.fasterxml.jackson.databind.ObjectMapper;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;
import java.sql.SQLException;
import java.util.List;@WebServlet("/blog")
public class BlogServlet extends HttpServlet {private ObjectMapper objectMapper = new ObjectMapper();@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {BlogDao  blogDao = new BlogDao();String blogId = req.getParameter("blogId");if(blogId==null){List<Blog> blogs = null;try {blogs = blogDao.getBlogs();} catch (SQLException e) {throw new RuntimeException(e);}String res = objectMapper.writeValueAsString(blogs);resp.setContentType("appliaction/jason;charset=utf8");resp.getWriter().write(res);}else{Blog blog = null;try {blog = blogDao.getBlog(Integer.parseInt(blogId));} catch (SQLException e) {throw new RuntimeException(e);}String str = objectMapper.writeValueAsString(blog);resp.setContentType("application/json;charset=utf8");resp.getWriter().write(str);}}@Overrideprotected void doPost(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;}User user = (User) session.getAttribute("user");if (user == null) {resp.setContentType("text/html; charset=utf8");resp.getWriter().write("用户未登录! 无法发布博客!");return;}req.setCharacterEncoding("utf8");String title = req.getParameter("title");String content = req.getParameter("content");if (title == null || content == null || "".equals(title) || "".equals(content)) {resp.setContentType("text/html; charset=utf8");resp.getWriter().write("标题或者正文为空");return;}Blog blog = new Blog();blog.title=title;blog.userId=user.userId;blog.content=content;BlogDao blogDao = new BlogDao();try {blogDao.insert(blog);} catch (SQLException e) {throw new RuntimeException(e);}resp.sendRedirect("blog_list.html");}
}
package api;import Dao.User;
import Dao.UserDao;
import utils.CloudSmsUtil;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;
import java.sql.SQLException;
@WebServlet("/login")
public class LoginSevlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {req.setCharacterEncoding("utf8");String usename = req.getParameter("username");String password=req.getParameter("password");String phone = req.getParameter("phone");String code = req.getParameter("code");if(usename==null||password==null||"".equals(usename)||"".equals(password)||"".equals(phone)||"".equals(code)){resp.setContentType("text/html;charset=utf8");resp.getWriter().write("传过来数值错误");return;}String inoutCode = CloudSmsUtil.PHONE_CODE_MAP.get(phone);if (!code.equals(inoutCode)) {resp.setContentType("text/html;charset=utf8");resp.getWriter().write("验证码错误");return;}UserDao userDao = new UserDao();User user = null;try {user = userDao.getUserByName(usename);} catch (SQLException e) {throw new RuntimeException(e);}if(user==null){resp.setContentType("text/html;charset=utf8");resp.getWriter().write("查无此人");return;}if(!password.equals(user.password)){resp.setContentType("text/html;charset=utf8");resp.getWriter().write("密码错误");return;}HttpSession httpSession = req.getSession(true);httpSession.setAttribute("user",user);resp.sendRedirect("blog_list.html");}@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {HttpSession httpSession =req.getSession(false);if(httpSession==null){resp.setStatus(403);return;}User user =(User)httpSession.getAttribute("user");resp.setStatus(200);}
}
package api;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("/logout")
public class LogouServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {HttpSession httpSession = req.getSession(false);if(httpSession==null){resp.sendRedirect("login.html");return;}httpSession.removeAttribute("user");resp.sendRedirect("login.html");}
}
package api;import Dao.User;
import Dao.UserDao;
import cn.hutool.core.util.RandomUtil;
import utils.CloudSmsUtil;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;
import java.sql.SQLException;@WebServlet("/sendCode")
public class SendSmsCodeSevlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {req.setCharacterEncoding("utf8");String phone = req.getParameter("phone");String code = RandomUtil.randomNumbers(4);boolean b = CloudSmsUtil.sendCheckCode(phone, code);
//        resp.setContentType("application/json;charset=utf8");if (b) {System.out.println("[发送验证码]-----------------------验证码为:"+ code);CloudSmsUtil.PHONE_CODE_MAP.put(phone, code);resp.getWriter().write("1");} else {resp.getWriter().write("0");}}@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doPost(req, resp);}
}
package api;import Dao.Blog;
import Dao.BlogDao;
import Dao.User;
import Dao.UserDao;
import com.fasterxml.jackson.databind.ObjectMapper;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;
import java.sql.SQLException;@WebServlet("/user")
public class UserServlet extends HttpServlet {private ObjectMapper objectMapper = new ObjectMapper();@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String blogId = req.getParameter("blogId");if (blogId == null) {HttpSession session = req.getSession(false);if (session == null) {User user = new User();String respJson = objectMapper.writeValueAsString(user);resp.setContentType("application/json; charset=utf8");resp.getWriter().write(respJson);return;}User user = (User) session.getAttribute("user");if (user == null) {user = new User();String respJson = objectMapper.writeValueAsString(user);resp.setContentType("application/json; charset=utf8");resp.getWriter().write(respJson);return;}String respJson = objectMapper.writeValueAsString(user);resp.setContentType("application/json; charset=utf8");resp.getWriter().write(respJson);} else {BlogDao blogDao = new BlogDao();Blog blog = null;try {blog = blogDao.getBlog(Integer.parseInt(blogId));} catch (SQLException e) {throw new RuntimeException(e);}if (blog == null) {User user = new User();String respJson = objectMapper.writeValueAsString(user);resp.setContentType("application/json; charset=utf8");resp.getWriter().write(respJson);return;}UserDao userDao = new UserDao();User user = null;try {user = userDao.getUserById(blog.userId);} catch (SQLException e) {throw new RuntimeException(e);}if (user == null) {user = new User();String respJson = objectMapper.writeValueAsString(user);resp.setContentType("application/json; charset=utf8");resp.getWriter().write(respJson);return;}String respJson = objectMapper.writeValueAsString(user);resp.setContentType("application/json; charset=utf8");resp.getWriter().write(respJson);}}
}

2.Dao

import com.fasterxml.jackson.annotation.JsonFormat;import java.sql.Timestamp;public class Blog {public int blogId;public String  title;public String content;public int  userId;@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")public Timestamp postTime;@Overridepublic String toString() {return "Blog{" +"blogId=" + blogId +", title='" + title + '\'' +", content='" + content + '\'' +", userId=" + userId +", postTime=" + postTime +'}';}}
package Dao;import javax.xml.transform.Result;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;public class BlogDao {public void insert(Blog blog) throws SQLException {Connection connection = Dbuc.getConnect();String sql = "insert into blog values(null,?,?,?,now())";PreparedStatement preparedStatement = connection.prepareStatement(sql);preparedStatement.setString(1,blog.title);preparedStatement.setString(2,blog.content);preparedStatement.setInt(3,blog.userId);preparedStatement.executeUpdate();Dbuc.close(connection,preparedStatement,null);}public List<Blog> getBlogs() throws SQLException {List<Blog> list1= new ArrayList<>();Connection connection = Dbuc.getConnect();String sql = "select* from blog order by postTime desc";PreparedStatement preparedStatement = connection.prepareStatement(sql);ResultSet resultSet= preparedStatement.executeQuery();while(resultSet.next()){Blog blog = new Blog();blog.blogId = resultSet.getInt("blogId");blog.title=resultSet.getString("title");blog.content=resultSet.getString("content");blog.userId=resultSet.getInt("userId");blog.postTime=resultSet.getTimestamp("postTime");list1.add(blog);}Dbuc.close(connection,preparedStatement,resultSet);return list1;}
public Blog getBlog(int blogId) throws SQLException {Connection connection = Dbuc.getConnect();String sql = "select* from blog where  blogId=?";PreparedStatement preparedStatement = connection.prepareStatement(sql);preparedStatement.setInt(1,blogId);ResultSet resultSet= preparedStatement.executeQuery();if(resultSet.next()){Blog blog = new Blog();blog.blogId = resultSet.getInt("blogId");blog.title=resultSet.getString("title");blog.content=resultSet.getString("content");blog.userId=resultSet.getInt("userId");blog.postTime=resultSet.getTimestamp("postTime");return blog;}Dbuc.close(connection,preparedStatement,resultSet);return null;
}
public void delete(int blogId) throws SQLException {Connection connection = Dbuc.getConnect();String sql = "delete from blog where blogId=?";PreparedStatement preparedStatement = connection.prepareStatement(sql);preparedStatement.setInt(1,blogId);preparedStatement.executeUpdate();Dbuc.close(connection,preparedStatement,null);
}
}
package Dao;import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;public class Dbuc {private static DataSource dataSource = null;private static DataSource getDataSource(){if(dataSource==null){synchronized (Dbuc.class){if(dataSource==null){dataSource=new MysqlDataSource();((MysqlDataSource) dataSource).setUrl("jdbc:mysql://127.0.0.1/java108_blog_system?characterEncoding=utf8&useSSL=false");((MysqlDataSource)dataSource).setUser("root");
//                    ((MysqlDataSource)dataSource).setUser("java108");((MysqlDataSource)dataSource).setPassword("123456");}}}return dataSource;}public static Connection getConnect() throws SQLException {return getDataSource().getConnection();}public static void close(Connection connection, PreparedStatement preparedStatement, ResultSet resultSet) throws SQLException {if(resultSet!=null){resultSet.close();}if(connection!=null){connection.close();}if(preparedStatement!=null){preparedStatement.close();}}}
package Dao;public class User {public int  userId;public String username;public String  password;@Overridepublic String toString() {return "User{" +"userId=" + userId +", username='" + username + '\'' +", password='" + password + '\'' +'}';}
}
package Dao;import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;public class UserDao {public User getUserById(int userId) throws SQLException {Connection connection = Dbuc.getConnect();String  sql = "select* from user where userId=?";PreparedStatement preparedStatement = connection.prepareStatement(sql);preparedStatement.setInt(1,userId);ResultSet resultSet = preparedStatement.executeQuery();if(resultSet.next()){User user = new User();user.userId=resultSet.getInt("userId");user.password=resultSet.getString("password");user.username=resultSet.getString("username");return user;}Dbuc.close(connection,preparedStatement,resultSet);return null;}public User getUserByName(String username) throws SQLException {Connection connection = Dbuc.getConnect();String  sql = "select* from user where username=?";PreparedStatement preparedStatement = connection.prepareStatement(sql);preparedStatement.setString(1,username);ResultSet resultSet = preparedStatement.executeQuery();if(resultSet.next()){User user = new User();user.userId=resultSet.getInt("userId");user.password=resultSet.getString("password");user.username=resultSet.getString("username");return user;}Dbuc.close(connection,preparedStatement,resultSet);return null;}
}

3.utils

package utils;import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;import java.util.HashMap;
import java.util.Map;public class CloudSmsUtil {private final static String accessKeyId = "LTAI5tEqaD59ckPYDhhxJ3ZF";private final static String accessKeySecret = "x6aD71AB7NmKhlayqhGIN1nt44M0TG";private final static String showStartNoticeTemplate = "SMS_474960284";private final static String signName = "我的学习路";/**ali固定配置参数begin*///短信API产品名称static final String product="Dysmsapi";//短信API产品域名static final String domain="dysmsapi.aliyuncs.com";/**ali固定配置参数end*/public final static Map<String, String> PHONE_CODE_MAP = new HashMap<>();public static boolean sendCheckCode(String phone, String code) {JSONObject params = new JSONObject();params.put("code", code);return  aliSmsSendMsg(showStartNoticeTemplate, phone, params);}private static boolean aliSmsSendMsg(String templateCode, String phone, JSONObject params) {//		System.out.println("alibaba-phone:" + phone + "-code:" + code);System.out.println("配置信息");System.out.println("accessKeyId:" + accessKeyId);System.out.println("accessKeySecret:" + accessKeySecret);System.out.println("signName:" + signName);System.out.println("templateCode:" + templateCode);try {//设置超时时间System.setProperty("sun.net.client.defaultConnectTimeout", "10000");System.setProperty("sun.net.client.defaultReadTimeout", "10000");//初始化ascClientIClientProfile profile= DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessKeySecret);DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", product, domain);IAcsClient acsClient=new DefaultAcsClient(profile);//组装请求对象SendSmsRequest request=new SendSmsRequest();//使用post提交request.setMethod(MethodType.POST);//待发送的手机号request.setPhoneNumbers(phone);//短信签名request.setSignName(signName);//短信模板IDrequest.setTemplateCode(templateCode);/** 可选:模板中的变量替换JSON串,* 如模板内容为"亲爱的${name},您的验证码为${code}"时,* 此处的值为{"name":"Tom","code":"1454"}*   \  反斜杠为转义字符,使得输出双引号*/request.setTemplateParam(params.toString());//可选:outId为提供给业务方扩展字段,最终在短信回执消息中将此值带回给调用者//request.setOutId("1454");SendSmsResponse response=acsClient.getAcsResponse(request);System.out.println(response.getCode() + ":" + response.getMessage());if(response.getCode() != null && response.getCode().equals("OK")) {//请求成功System.out.println("发送成功!");return true;}else {System.out.println(StrUtil.format("发送失败!{}", response.getCode() + ":" + response.getMessage()));return false;}} catch (ServerException e) {e.printStackTrace();return false;} catch (ClientException e) {e.printStackTrace();return false;}}
}

相关文章:

JavaWeb项目-----博客系统

一.设计数据库 1.创建数据库 create database if not exists java108_blog_system character set utf8; drop table if exists user; drop table if exists blog;2.创建博客列表 create table blog(blogId int primary key auto_increment,title varchar(20),content varcha…...

GY-56 (VL53L0X) 激光测距

文章目录 一、GY-56 简介二、引脚功能三、通信协议1.串口协议&#xff1a; 当 GY-56 PS 焊点开放时候使用(默认)&#xff08;1&#xff09;串口通信参数&#xff08;默认波特率值 9600bps&#xff09;&#xff08;2&#xff09;模块输出格式&#xff0c;每帧包含 8-13 个字节&a…...

当今陪玩系统小程序趋势,陪玩系统源码搭建后的适用于哪些平台

一、市场规模持续扩大 随着全球游戏市场的不断膨胀&#xff0c;游戏陪玩行业正逐渐从一个新兴领域成长为游戏产业链中不可或缺的一环。据《2024年1~6月中国游戏产业报告》显示&#xff0c;今年上半年&#xff0c;国内游戏市场实际销售收入达到1472.67亿元&#xff0c;同比增长…...

qt QListWidget详解

1、概述 QListWidget 是 Qt 框架中的一个类&#xff0c;它提供了一个基于模型的视图&#xff0c;用于显示项目的列表。QListWidget 继承自 QAbstractItemView 并为项目列表提供了一个直观的接口。与 QTreeView 和 QTableView 不同&#xff0c;QListWidget 是专门为单行或多行项…...

java ssm 校园快递物流平台 校园快递管理系统 物流管理 源码 jsp

一、项目简介 本项目是一套基于SSM的校园快递物流平台&#xff0c;主要针对计算机相关专业的和需要项目实战练习的Java学习者。 包含&#xff1a;项目源码、数据库脚本、软件工具等。 项目都经过严格调试&#xff0c;确保可以运行&#xff01; 二、技术实现 ​后端技术&#x…...

西安电子科技大学考研网报审核通过了,然后呢?

报考西安电子科技大学的宝贝们&#xff0c;考研网上确认已经截止的同学们&#xff0c;不用担心&#xff01; 最近&#xff0c;有很多同学问到一个问题&#xff1a;网上确认时看到有消息说禁止使用海马体照片&#xff0c;但我明明用了海马体的照片&#xff0c;审核却通过了&…...

pandas习题 051:将字符串数据读取到 DataFrame

编码题)有以下逗号隔开和空格隔开的字符串数据,如何将它读取为 DataFrame ? data = ‘’’ a,b,c 1,3,4 2,4,5 ‘’’ data2 = ‘’’ a b c 1 13 214 2 4 15 ‘’’ Python 代码如下:import pandas as pd import iodata = a,b,c 1,3,4 2,4,5 df = pd.read_csv(io.Stri…...

改进探路者算法复现

本文所涉及所有资源均在 传知代码平台 可获取。 目录 一、背景及意义介绍 (一)背景 ࿰...

PostgreSQL 学习笔记:PostgreSQL 主从复制

PostgreSQL 笔记&#xff1a;PostgreSQL 主从复制 博客地址&#xff1a;TMDOG 的博客 在现代应用程序中&#xff0c;数据库的高可用性和扩展性是至关重要的。PostgreSQL 提供了主从复制功能&#xff0c;可以在多个数据库实例之间复制数据&#xff0c;以实现冗余和负载均衡。本…...

【系统架构设计师(第2版)】十一、未来信息综合技术

未来信息综合技术是指近年来新技术发展而提出的一些新概念、新知识、新产品&#xff0c;主要包括信息物理系统&#xff08;CPS&#xff09;、人工智能&#xff08;AI&#xff09;、机器人、边缘计算、数字孪生、云计算和大数据等技术。这些技术涉及多学科、多领域&#xff0c;具…...

Pytorch学习--神经网络--优化器

一、头文件 torch.optim.Optimizer(params, defaults) optim文档 for input, target in dataset:optimizer.zero_grad()output model(input)loss loss_fn(output, target)loss.backward()optimizer.step()二、代码 不带优化器的代码框架 import torch import torchvision…...

w~自动驾驶合集11

我自己的原文哦~ https://blog.51cto.com/whaosoft/12329152 #特斯拉的“纯视觉”路线 , 也许不是最好的 BEVTransformer占用网络技术路线的大热&#xff0c;再次将激光雷达推向风口浪尖。 激光雷达该不该被抛弃&#xff1f; 对车企来说&#xff0c;这是一个艰难的抉择&am…...

大数据新视界 -- 大数据大厂之 Impala 性能优化:解锁大数据分析的速度密码(上)(1/30)

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…...

GESP4级考试语法知识(算法概论(三))

爱因斯坦的阶梯代码&#xff1a; //算法1-12 #include<iostream> using namespace std; int main() {int n1; //n为所设的阶梯数while(!((n%21)&&(n%32)&&(n%54)&&(n%65)&&(n%70)))n; //判别是否满足一组同余式cout<<n<…...

x-cmd pkg | gum - 轻松构建美观实用的终端界面,解锁命令行新玩法

目录 简介快速上手安装使用 功能特点竞品和相关作品进一步探索 简介 gum 是由 Charm 团队于 2022 年使用 Go 开发的终端 UI 组件工具箱&#xff0c;能帮用户在终端中快速构建交互式 TUI 界面&#xff08;如表单、菜单、提示框等&#xff09;&#xff0c;简化命令行应用程序的开…...

WMS系统打通仓储全链条数据势在必行,该如何做呢

一、引言 在当今竞争激烈的商业环境中&#xff0c;高效的仓储管理对于企业的生存和发展至关重要。仓储管理系统&#xff08;WMS&#xff09;作为现代仓储管理的核心工具&#xff0c;其作用不仅仅是简单地记录库存数量和位置&#xff0c;更在于打通仓储全链条数据&#xff0c;实…...

基于Python的校园爱心帮扶管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…...

如何基于pdf2image实现pdf批量转换为图片

最近为了将pdf报告解析成为文本和图片&#xff0c;需要将大量多页的pdf文件拆分下单独的一页一页的图像&#xff0c;以便后续进行OCR和图像处理&#xff0c;因此就需要实现将pdf2image&#xff0c;本文主要结合开源的pdf2image和poppler&#xff0c;实现了pdf转换为png格式图片…...

Tomcat(1) 什么是Tomcat?

Tomcat是一个开源的Web服务器和Servlet容器&#xff0c;它实现了Java Servlet、JavaServer Pages (JSP)、WebSocket和Java EL等Java EE规范。Tomcat由Apache软件基金会维护&#xff0c;是Java应用程序的常用部署平台。 深入理解Tomcat 1. 架构 Tomcat的核心组件包括&#xf…...

商务礼仪与职场沟通

知人者智&#xff0c;自知者明。胜人者有力&#xff0c;自胜者强。知足者富&#xff0c;强行者有志&#xff0c;不失其所者久&#xff0c;死而不亡者寿。 ——《道德经&#xff08;第三十三章&#xff09;》 认知先行——意识塑造 职业化——标准化&#xff0c;规范化&#…...

练习(含atoi的模拟实现,自定义类型等练习)

一、结构体大小的计算及位段 &#xff08;结构体大小计算及位段 详解请看&#xff1a;自定义类型&#xff1a;结构体进阶-CSDN博客&#xff09; 1.在32位系统环境&#xff0c;编译选项为4字节对齐&#xff0c;那么sizeof(A)和sizeof(B)是多少&#xff1f; #pragma pack(4)st…...

CocosCreator 之 JavaScript/TypeScript和Java的相互交互

引擎版本&#xff1a; 3.8.1 语言&#xff1a; JavaScript/TypeScript、C、Java 环境&#xff1a;Window 参考&#xff1a;Java原生反射机制 您好&#xff0c;我是鹤九日&#xff01; 回顾 在上篇文章中&#xff1a;CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...

LLM基础1_语言模型如何处理文本

基于GitHub项目&#xff1a;https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken&#xff1a;OpenAI开发的专业"分词器" torch&#xff1a;Facebook开发的强力计算引擎&#xff0c;相当于超级计算器 理解词嵌入&#xff1a;给词语画"…...

学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”

2025年#高考 将在近日拉开帷幕&#xff0c;#AI 监考一度冲上热搜。当AI深度融入高考&#xff0c;#时间同步 不再是辅助功能&#xff0c;而是决定AI监考系统成败的“生命线”。 AI亮相2025高考&#xff0c;40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕&#xff0c;江西、…...

rnn判断string中第一次出现a的下标

# coding:utf8 import torch import torch.nn as nn import numpy as np import random import json""" 基于pytorch的网络编写 实现一个RNN网络完成多分类任务 判断字符 a 第一次出现在字符串中的位置 """class TorchModel(nn.Module):def __in…...

Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?

Redis 的发布订阅&#xff08;Pub/Sub&#xff09;模式与专业的 MQ&#xff08;Message Queue&#xff09;如 Kafka、RabbitMQ 进行比较&#xff0c;核心的权衡点在于&#xff1a;简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...

AirSim/Cosys-AirSim 游戏开发(四)外部固定位置监控相机

这个博客介绍了如何通过 settings.json 文件添加一个无人机外的 固定位置监控相机&#xff0c;因为在使用过程中发现 Airsim 对外部监控相机的描述模糊&#xff0c;而 Cosys-Airsim 在官方文档中没有提供外部监控相机设置&#xff0c;最后在源码示例中找到了&#xff0c;所以感…...

LRU 缓存机制详解与实现(Java版) + 力扣解决

&#x1f4cc; LRU 缓存机制详解与实现&#xff08;Java版&#xff09; 一、&#x1f4d6; 问题背景 在日常开发中&#xff0c;我们经常会使用 缓存&#xff08;Cache&#xff09; 来提升性能。但由于内存有限&#xff0c;缓存不可能无限增长&#xff0c;于是需要策略决定&am…...

【MATLAB代码】基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),附源代码|订阅专栏后可直接查看

文章所述的代码实现了基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),针对传感器观测数据中存在的脉冲型异常噪声问题,通过非线性加权机制提升滤波器的抗干扰能力。代码通过对比传统KF与MCC-KF在含异常值场景下的表现,验证了后者在状态估计鲁棒性方面的显著优…...

MinIO Docker 部署:仅开放一个端口

MinIO Docker 部署:仅开放一个端口 在实际的服务器部署中,出于安全和管理的考虑,我们可能只能开放一个端口。MinIO 是一个高性能的对象存储服务,支持 Docker 部署,但默认情况下它需要两个端口:一个是 API 端口(用于存储和访问数据),另一个是控制台端口(用于管理界面…...