1. 项目简介
1.1 项目背景
在网络学完HTTP协议,前端学完html,css,js,后端学完Servlet开发后,做一个博客系统,巩固一下所学知识,并将所学知识运用到实际当中,以此来进一步提升对学习编程的兴趣
1.2 项目用到的技术
- 前端使用到html,css,js,使用ajax技术发送http请求,请求body的格式为json格式
- 后端使用Servlet进行开发
- 使用Mysql数据库保存数据
- 除此还引入了editor.md,editor.md是一个开源的页面markdown编辑器组件
- 采用Maven构建工具搭建项目开发环境
1.3 项目功能简单介绍
- 登陆页面:输入用户及密码,点击提交,如果用户或密码错误,会提示用户或密码错误,账号及密码正确则登陆成功,成功后跳转到博客列表页面
- 博客列表页面:博客列表页面展示所有发布过的文章,文章显示最多显示50字,如果想查看全文,则需要点击文章下的显示全文
- 博客详情页面:点击某篇文章的显示全文按钮,则会展示文章的全部内容
- 博客编辑页面:点击博客列表的写博客,会跳转到博客编辑页面,输入文章题目及文章内容点击发布文章,文章即可发布成功,发布成功后会跳转到博客列表页面,可以查看发布过的文章
- 博客注销按钮:点击博客注销按钮,则会跳转到博客登陆页面
2. 页面及功能展示
登陆页面
输入用户和密码,点击提交,登陆成功后跳转到博客列表页面
点击写博客,跳转到博客编辑页面
输入文章标题和文章内容,点击发布文章,发布成功后跳转到博客列表页面
在博客列表页面,点击刚发布文章的显示全文,就会显示刚才发布文章的全部内容
点击注销又跳转到博客登陆页面
3. 博客系统页面设计
这里附上静态页面设计的码云地址,可以点击查看,本篇文章只展示后端代码与前端ajax交互的部分,想要查看博客系统页面设计代码,请点击:个人博客系统的页面设计代码
4. 项目准备工作
创建Maven项目在pom.xml中添加项目依赖
- 后端采用Servlet开发
- 数据库使用Mysql
- jackson框架可以进行序列化和反序列化,将java对象和json字符串相互转化
- junit框架提供单元测试
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>my-blog</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.49</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.3</version>
</dependency>
<!-- 单元测试框架 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
</dependency>
</dependencies>
<build>
<finalName>my-blog</finalName>
</build>
</project>
创建与开发相关的包
引入前端资源
将前端资源都放在main/webapp目录下,前端资源从上面码云地址中获取,web.xml存放在main/webapp/WEB-INF目录下
5. 博客系统功能设计
5.1 设计数据库表
- 有用户登陆,所以有一张用户表,观察博客列表有显示用户昵称,所以用户表设计有四个字段:用户id,用户名,密码,昵称
- 有文章展示,所以有一张文章表,文章有文章id,标题,发布时间,文章内容,关联用户的外键
- 一个用户可以发布多篇文章,所以用户与文章对应关系为1:m,用户id作为文章表的外键
创建表的时候可以插入一些数据便于后续的测试
drop database if exists blog;
create database blog character set utf8mb4;
use blog;
create table user(
id int primary key auto_increment,
username varchar(20) not null unique,
password varchar(20) not null,
nickname varchar(10) not null
);
insert into user values(null,'abc','123','糯米');
create table article(
id int primary key auto_increment,
title varchar(50) not null,
`date` date,
content mediumtext,
user_id int,
foreign key (user_id) references user(id)
);
insert into article values(null,'文章1','2022-9-9','今天要好好学习',1);
insert into article values(null,'文章2','2022-9-17','今天要玩游戏',1);
5.2 工具类util
- 创建数据库工具类DBUtil,提供获取数据库连接和统一释放资源
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
//数据库工具类,提供获取数据库连接,释放资源统一代码
public class DBUtil {
//一个程序,连接一个数据库,只需要一个连接池,其中保存了多个数据库连接对象
private static MysqlDataSource ds; //静态变量,类加载时执行初始化,只执行一次
//获取连接池,内部使用,不开放
private static DataSource getDataSource(){
if(ds == null){
ds = new MysqlDataSource();
ds.setURL("jdbc:mysql://127.0.0.1:3306/blog");
ds.setUser("root");
ds.setPassword("xiaobai520..@@@");
ds.setUseSSL(false); //不安全连接,不设置会有警告
ds.setCharacterEncoding("UTF-8");
}
return ds;
}
//获取数据库连接对象,开放给外部的jdbc代码使用
public static Connection getConnection(){
try {
return getDataSource().getConnection();
} catch (SQLException e) {
throw new RuntimeException("获取数据库连接报错",e);
}
}
//释放资源,查询操作需要释放三个资源
public static void close(Connection c, Statement s, ResultSet rs){
try {
if(rs != null) rs.close();
if(s != null) s.close();
if(c != null) c.close();
} catch (SQLException e) {
throw new RuntimeException("释放数据库资源出错",e);
}
}
//更新操作释放两个资源
public static void close(Connection c,Statement s){
close(c,s,null);
}
}
- 创建Web工具类WebUtil,提供一个类专门检查用户是否登陆,还提供序列化与反序列化类,用来将java对象与json字符串相互转化
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.example.model.User;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.InputStream;
public class WebUtil {
public static User checkLogin(HttpServletRequest req){
User user = null;
HttpSession session = req.getSession(false);
user = (User) session.getAttribute("user");
return user;
}
//使用单例
private static ObjectMapper mapper = new ObjectMapper();
//反序列化:json字符串转换Java对象
//使用泛型,传一个什么类型,就返回该类型的对象
//泛型方法:方法限定符 <类型型参列表> 返回值类型 方法名
public static <T> T read(InputStream is,Class<T> clazz){
try {
return mapper.readValue(is,clazz);
} catch (IOException e) {
throw new RuntimeException("json反序列化出错",e);
}
}
//序列化:将java对象转化为json字符串
public static String write(Object o){
try {
return mapper.writeValueAsString(o);
} catch (JsonProcessingException e) {
throw new RuntimeException("json序列化出错",e);
}
}
}
5.3 实体类model
每张用户表对应有一个实体类,所以创建User和Article类,创建类的时候提供Getter和Setter方法并且重写toString方法
用户类User
public class User {
private Integer id;
private String username;
private String password;
private String nickname;
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", nickname='" + nickname + '\'' +
'}';
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
}
文章类Article
import java.util.Date;
public class Article {
private Integer id;
private String title;
private Date date; //时间
private String content;
private Integer userId;
private String dateString;//日期字符串
@Override
public String toString() {
return "Article{" +
"id=" + id +
", title='" + title + '\'' +
", date=" + date +
", content='" + content + '\'' +
", userId=" + userId +
", dateString='" + dateString + '\'' +
'}';
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public String getDateString() {
return dateString;
}
public void setDateString(String dateString) {
this.dateString = dateString;
}
}
Java对象JsonResult类
后端返回给前端的响应时返回的是json字符串,所以需要一个JsonResult类,该类的字段保存操作是否成功和要返回给前端的数据,后端在返回给前端json字符串的时候只需要将该类序列化为json字符串返回给前端,该类也得提供Getter与Setter方法并且重写toString方法
public class JsonResult {
private boolean ok;//标识执行一个操作是否成功
private Object data;//操作成功,且是一个查询操作,需要返回一些数据给前端
@Override
public String toString() {
return "JsonResult{" +
"ok=" + ok +
", data=" + data +
'}';
}
public boolean isOk() {
return ok;
}
public void setOk(boolean ok) {
this.ok = ok;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}
5.4 前后端业务处理
前后端业务逻辑的实现顺序:
- 先在前端构造ajax请求
- 再做后端业务逻辑
- 最后再前端才设置回调函数执行回调
说明:后面实现的顺序是先前端再后端,但是观看参考时,建议按照上面的逻辑顺序,因为实际开发时就是按照这个顺序来开发的
5.4.1 登陆页面功能设计
所有的请求都是使用ajax发送http请求,所以将封装的ajax函数写在一个js文件中,后续发送请求时只需将封装的ajax函数引入即可
封装的ajax函数
//封装ajax函数,args为一个js对象
//args对象属性如下:
//method:请求方法,url:请求资源路径,contenType:请求正文格式
//body:请求正文,callback:回调函数,客户端接收到响应数据后调用
function ajax(args) {
let xhr = new XMLHttpRequest();
//设置回调函数
xhr.onreadystatechange = function () {
//4:客户端接收到服务端响应
if (xhr.readyState == 4) {
//回调函数可能会使用响应的内容,作为传入参数
args.callback(xhr.status, xhr.responseText);
}
}
xhr.open(args.method, args.url);
//如果args中contentType有内容,就设置Content-Type请求头
if (args.contentType) {//js中if可以判断是否有值
xhr.setRequestHeader("Content-Type", args.contentType);
}
//如果args中body有内容,设置body请求正文
if (args.body) {
xhr.send(args.body);
} else {
xhr.send();
}
}
前端设计
- 给登陆提交按钮绑定点击事件,获取到输入的用户名和密码后,发送ajax请求
- 请求方法为post,请求url为login,后端的Servlet路径也要与此对应,设置contentType为application/json,请求body为json字符串
- json对象保存输入的用户名和密码,将json对象转化为json字符串设置到body中
- 设置回调函数,回调函数有两个参数,一个为响应状态码,一个为后端返回的响应为json字符串,后端返回的json字符串中保存操作是否成功字段
- 如果响应状态码为200,并且ok为true,则登陆成功,跳转到博客列表页面,如果ok为false则用户名或密码错误,如果响应状态码不为200,则提示响应状态码及响应body,以便程序员作出更改
<script src="js/util.js"></script>
<script>
let submit = document.querySelector("#submit");
//绑定提交按钮点击事件
submit.onclick = function(){
let username = document.querySelector("#username").value;
let password = document.querySelector("#password").value;
//发送ajax请求,需要设置method,url,contentType,body
ajax({
method: "post",
url: "login",
contentType: "application/json",
body: JSON.stringify({
//冒号前是前后端约定的键,冒号后是变量值
username: username,
password: password
}),
callback: function(status,responseText){
if(status == 200){
let json = JSON.parse(responseText);
if(json.ok){
alert("登陆成功");
window.location.href = "blog_list.html";
}else {
alert("账号或密码错误");
}
}else {
alert("响应状态码:"+status+"/nbody:"+responseText);
}
}
});
}
</script>
后端Servlet设计
- 前端发送的body为json字符串
- 所以先使用InputStream输入流获取请求数据,将请求数据转化为user对象
- 使用该对象在数据库做校验,如果校验成功,设置session,设置要返回给前端的JsonResult对象json
- 设置完后,将json对象序列化json字符串后返回给前端
- 前端的回调函数就是依据后端返回的json字符串做相应的逻辑处理
@WebServlet("/login")//登陆
public class LoginServlet extends HttpServlet {
//登陆功能,json提交{username:abc,password:123}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//解析请求:通过输入流获取请求数据
req.setCharacterEncoding("utf-8"); //设置请求对象的编码格式
InputStream is = req.getInputStream();
//将输入流中的json字符串转化为java对象
//使用ObjectMapper将java对象和json字符串相互转换,Servlet都要用,封装到WebUtil中
User get = WebUtil.read(is,User.class);
//在数据库校验账号密码:通过账号密码在数据库查用户,若能查到则账号密码正确
User user = UserDao.isLogin(get.getUsername(),get.getPassword());
//不管登陆是否成功,返回的http响应正文(body)都是json字符串
//需要设计一个类,这个类的成员变量属性,用于前端ajax解析响应
//先创建一个响应正文需要的Java对象,然后在转换为json字符串,再设置到响应正文
JsonResult json = new JsonResult();
if(user != null){
//登陆成功,设置session
HttpSession session = req.getSession(true);
session.setAttribute("user",user);
//设置json对象中,操作是否成功为true
json.setOk(true);
}else {
//登陆失败,设置操作是否成功字段为false
json.setOk(false);
}
//设置响应正文的格式
resp.setContentType("application/json; charset=utf-8");
resp.getWriter().write(WebUtil.write(json));
}
}
5.4.2 博客列表页面功能设计
前端设计
客户端展示页面时,就需要展示文章列表数据,加载完页面就发生ajax请求,来获取文章列表内容,待收到返回的响应执行回调时,解析响应的文章列表数据
- 发送的ajax请求,method为get,url为blog_list,对应的后端Servlet路径也要与之对应
- 因为是get请求,所以没有body
- 设置回调函数,与前面登陆的回调函数逻辑相似,将后端返回的json字符串转化为json对象时,如果ok为true,则解析返回的数据
- 将返回的nickname和文章数设置到前端,将返回的文章集合以循环的方式设置到前端
<script src="js/util.js"></script>
<script>
//客户端展示页面时,就需要展示文章列表数据
//加载完页面,就发送ajax请求获取文章列表的数据
//返回响应执行回调时,解析响应的文章列表数据
ajax({
method: "get",
url: "blog_list",
callback: function(status,responseText){
if(status == 200){
let json = JSON.parse(responseText);
if(json.ok){
let data = json.data;
let nickname = data.nickname;
let h3 = document.querySelector(".card>h3");
h3.innerHTML = nickname;
let articles = data.articles;
let div = document.querySelector(".container-right");
//str不赋值就是undefined,再去拼接字符串就会出错
let str = "";
for(let a of articles){
//``里面可以包括单引号和双引号
str += `<div class="row">`;
str += `<div class="title">`;
str += a.title;
str += `</div>`;
str += `<div class="date">`;
str += a.dateString;
str += `</div>`;
str += `<div class="desc">`;
str += `<p>`;
str += a.content;
str += `</p>`;
str += `</div>`;
str += `<div class="to-detail">`;
str += `<a href="blog_content.html?id=` + a.id;
str += `">显示全文>></a>`;
str += `</div>`;
str += `</div>`;
}
div.innerHTML = str;
let num = data.count;
let count = document.querySelector("#count");
count.innerHTML = num;
}else {
alert("ok==false");
}
}else {
alert("响应状态码:"+status+"/nbody:"+responseText)
}
}
});
</script>
</html>
后端Servlet设计
- 先校验用户是否登陆,未登录不允许访问,直接跳转到用户登陆页面,登陆后才可执行后边逻辑
- 登陆成功后用用户的id查询该用户的所有文章并且查询该用户的所有文章数目
- 此时已经登陆成功,设置JsonResult对象json的ok为true
- 创建一个Map结构的data,保存要返回给前端的数据文章列表和用户昵称和文章数目
- 将data设置到json对象中,将json对象序列化为json字符串返回给前端
@WebServlet("/blog_list")//博客列表
public class BlogListServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//未登录,访问跳转到登陆页面
User user = WebUtil.checkLogin(req);
if(user == null){
resp.sendRedirect("login.html");
return; //未登录,直接跳转,不会执行后边逻辑
}
//通过登陆用户id查找所有文章
List<Article> articles = ArticleDao.selectById(user.getId());
//通过登陆用户id查找文章数目
int count = ArticleDao.getCount(user.getId());
//先构造响应正文需要的java对象,再转化为json字符串,再设置到响应正文
JsonResult json = new JsonResult();
json.setOk(true);
//前端需要的数据有nickname,articles,可以用map保存,然后设置到json.data中
Map<String,Object> data = new HashMap<>();
data.put("nickname",user.getNickname());
data.put("articles",articles);
data.put("count",count);
json.setData(data);
resp.setContentType("application/json; charset=utf-8");
resp.getWriter().write(WebUtil.write(json));
}
}
5.4.3 博客详情页面功能设计
前端设计
博客详情是从博客列表的显示全文按钮跳转过来的,所以跳转的连接携带id,id标识文章id,表示显示的是哪篇文章的全部内容
- 先使用window.location.search.substring获取到文章id
- 再发送ajax请求,请求方法为get,请求url为blog_content?id=id,设置回调函数
- 待后端返回响应后执行回调函数,将响应正文转化为json对象,解析json对象
- 设置用户昵称,文章数目,文章标题,发表日期,文章内容
<script src="js/util.js"></script>
<script>
//window.location.search获取的是queryString?后的部分,blog_content?id=1
//也就是获取的是?id=1
let id = window.location.search.substring(4);
//页面一加载就需要展示博客详情页面,所以就发送ajax请求来获取内容
ajax({
method: "get",
url: "blog_content?id="+id,
callback: function(status,responseText){
if(status == 200){
let json = JSON.parse(responseText);
if(json.ok){
let data = json.data;
let nickname = data.nickname;
let h3 = document.querySelector(".card>h3");
h3.innerHTML = nickname;
let num = data.count;
let count = document.querySelector("#count");
count.innerHTML = num;
let article = data.article;
let div = document.querySelector(".detail");
let str = "";
str += `<div class="title">`;
str += article.title;
str += `</div>`;
str += `<div class="date">`;
str += article.dateString;
str += `</div>`;
str += `<div id="article-content" class="desc">`;
//str += article.content;
str += `</div>`;
div.innerHTML = str;
//不能直接展示markdown源码,数据库保存的是markdown源码
editormd.markdownToHTML("article-content",{markdown: article.content});
}else {
alert("ok == false");
}
}else {
alert("响应状态码:"+status+"/nbody:"+responseText);
}
}
});
</script>
后端Servlet设计
- 用户未登录不允许访问,直接跳转到用户登陆页面
- 请求数据携带在queryString中,所以使用req.getParameter解析请求获取到文章id
- 根据文章id查询整个文章将查询的数据设置到一个文章对象中
- 将JsonResult对象json的ok设置为true
- 使用一个Map结构data保存获取的文章数目,文章,用户昵称
- 将data设置到json对象中,将json对象序列化为json字符串后返回给前端
@WebServlet("/blog_content")//博客详情
public class BlogContentServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//未登录,访问跳转到登陆页面
User user = WebUtil.checkLogin(req);
if(user == null){
resp.sendRedirect("login.html");
return; //未登录,直接跳转,不会执行后边逻辑
}
//路径为:blog_content?id=文章id
//解析请求
String sid = req.getParameter("id"); //获取到文章id
//通过文章id查询整篇文章
Article a = ArticleDao.queryById(Integer.parseInt(sid));
int count = ArticleDao.getCount(user.getId());
JsonResult json = new JsonResult();
json.setOk(true);
Map<String,Object> data = new HashMap<>();
data.put("nickname",user.getNickname());
data.put("article",a);
data.put("count",count);
json.setData(data);
resp.setContentType("application/json; charset=utf-8");
resp.getWriter().write(WebUtil.write(json));
}
}
5.4.4 博客编辑页面功能设计
前端设计
- 给发布文章绑定点击事件,点击发布,发送ajax请求用于给文章表中添加数据
- 获取到输入的文章标题和文章内容,将其设置为json对象
- 发送ajax请求的方法为post,url为blog_add,后端Servlet路径要与之对应,设置contentType为application/json,将设置的json对象转化为json字符串设置到body中
- 待收到后端返回的响应后,执行回调,提示发布文章成功并且跳转到博客列表页面
<script src="js/util.js"></script>
<script src="js/jquery.min.js"></script>
<script src="editor.md/lib/marked.min.js"></script>
<script src="editor.md/lib/prettify.min.js"></script>
<script src="editor.md/editormd.min.js"></script>
<script>
$(function(){
var editor = editormd("edit-content",{
width: "100%",
height: "calc(100% - 50px)",
markdown: "# 在这里写下第一篇博客",
path: "editor.md/lib/",
saveHTMLToTextarea: true
});
})
//发布文章点击事件
function addContent(){
let title = document.querySelector("#title").value;
let content = document.querySelector("#content").value;
ajax({
method: "post",
url: "blog_add",
contentType: "application/json",
body: JSON.stringify({
title: title,
content: content
}),
callback: function(status,responseText){
if(status == 200){
let json = JSON.parse(responseText);
if(json.ok){
alert("发布文章成功");
window.location.href = "blog_list.html";
}else {
alert("ok == false");
}
}else {
alert("响应状态码:"+status+"/nbody:"+responseText);
}
}
});
}
</script>
后端Servlet设计
- 用户未登录不允许访问,直接跳转到用户登录页面
- 使用InputStream解析请求,通过输入流获取数据
- 将输入流中的json字符串转化为文章对象
- 设置用户id,发布日期到该文章对象中
- 将JsonResult对象json的ok设置为true,将json对象序列化为json字符串后返回给前端
@WebServlet("/blog_add")//添加文章
public class BlogAddServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
User user = WebUtil.checkLogin(req);
if(user == null){
//未登录不允许访问
resp.sendRedirect("login.html");
return;
}
//解析请求
req.setCharacterEncoding("utf-8");
InputStream is = req.getInputStream();
Article beInsert = WebUtil.read(is,Article.class);
//数据库插入一条数据,相当于插入一个对象
beInsert.setUserId(user.getId());
beInsert.setDate(new java.util.Date());
int n = ArticleDao.insertOne(beInsert);
JsonResult json = new JsonResult();
json.setOk(true);
resp.setContentType("application/json; charset=utf-8");
resp.getWriter().write(WebUtil.write(json));
}
}
5.4.5 用户注销功能设计
- 获取到session
- 如果session不为空,将session中保存的user删除
- 删除后跳转到用户登陆页面
@WebServlet("/logout")
public class LogoutServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//注销就是通过session对象删除保存的用户信息
HttpSession session = req.getSession(false);
if(session != null){
session.removeAttribute("user");
}
resp.sendRedirect("login.html");
}
}
6. 数据库逻辑处理
前端后端做业务处理的数据库逻辑操作如下:
6.1 用户表的逻辑处理
通过登陆输入的用户名和密码查询到user并将user返回,以此来做用户密码校验功能
public class UserDao {
public static User isLogin(String username, String password){
Connection c = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
c = DBUtil.getConnection();
String sql = "select * from user where username=? and password=?";
ps = c.prepareStatement(sql);
ps.setString(1,username);
ps.setString(2,password);
rs = ps.executeQuery();
User user = null;
while(rs.next()){
user = new User();
int id = rs.getInt("id");
String nickname = rs.getString("nickname");
user.setId(id);
user.setNickname(nickname);
user.setUsername(username);
user.setPassword(password);
}
return user;
} catch (SQLException e) {
throw new RuntimeException("校验账号密码出错",e);
} finally {
DBUtil.close(c,ps,rs);
}
}
@Test
public void testLogin(){
System.out.println(isLogin("abc","123"));
}
}
6.2 文章表的逻辑处理
通过用户id查询所有文章
//通过用户id查询所有文章
public static List<Article> selectById(Integer id){
List<Article> articles = new ArrayList<>();
Connection c = null;
PreparedStatement ps = null;
ResultSet rs = null;
try{
c = DBUtil.getConnection();
String sql = "select * from article where user_id=?";
ps = c.prepareStatement(sql);
ps.setInt(1,id);
rs = ps.executeQuery();
while(rs.next()){
Article a = new Article();
a.setId(rs.getInt("id"));
a.setTitle(rs.getString("title"));
java.sql.Date date = rs.getDate("date");
long time = date.getTime();
a.setDate(new java.util.Date(time));
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
String dateString = df.format(a.getDate());
a.setDateString(dateString);
String content = rs.getString("content");
a.setContent(content.length()>50 ? content.substring(0,50) : content);
a.setUserId(id);
articles.add(a);
}
return articles;
} catch (SQLException e) {
throw new RuntimeException("查询文章出错",e);
} finally {
DBUtil.close(c,ps,rs);
}
}
根据文章id查询整篇文章
//根据文章id查文章
public static Article queryById(int id) {
Article a = null;
Connection c = null;
PreparedStatement ps = null;
ResultSet rs = null;
try{
c = DBUtil.getConnection();
String sql = "select * from article where id=?";
ps = c.prepareStatement(sql);
ps.setInt(1,id);
rs = ps.executeQuery();
while(rs.next()){
a = new Article();
a.setId(id);
a.setTitle(rs.getString("title"));
java.sql.Date date = rs.getDate("date");
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
String dateString = df.format(new java.util.Date(date.getTime()));
a.setDateString(dateString);
a.setContent(rs.getString("content"));
a.setUserId(rs.getInt("user_id"));
}
return a;
} catch (SQLException throwables) {
throw new RuntimeException("查询文章详情jdbc出错",throwables);
} finally{
DBUtil.close(c,ps,rs);
}
}
插入一篇文章
//插入文章
public static int insertOne(Article a) {
Connection c = null;
PreparedStatement ps = null;
try{
c = DBUtil.getConnection();
String sql = "insert into article(title,`date`,content,user_id) values(?,?,?,?)";
ps = c.prepareStatement(sql);
ps.setString(1,a.getTitle());
//ps.setDate(2,new java.sql.Date(a.getDate().getTime()))
ps.setDate(2,new java.sql.Date(System.currentTimeMillis()));
ps.setString(3,a.getContent());
ps.setInt(4,a.getUserId());
return ps.executeUpdate();
} catch (SQLException throwables) {
throw new RuntimeException("发布文章jdbc出错",throwables);
} finally {
DBUtil.close(c,ps);
}
}
获取文章数目
public static int getCount(Integer id) {
Connection c = null;
PreparedStatement ps = null;
ResultSet rs = null;
try{
c = DBUtil.getConnection();
String sql = "select 0 from article where user_id=?";
ps = c.prepareStatement(sql);
ps.setInt(1,id);
rs = ps.executeQuery();
int count = 0;
while(rs.next()){
count++;
}
return count;
} catch (SQLException throwables) {
throw new RuntimeException("查询文章数目出错",throwables);
} finally{
DBUtil.close(c,ps,rs);
}
}
7. 博客系统设计源码
在做前后端逻辑处理的时候,前端代码有些稍微的改动,本文没有提及到,请点击查看源码,查看改动的细节以及所有后端的设计实现:个人博客系统设计源码
版权归原作者 X_H学Java 所有, 如有侵权,请联系我们删除。