Servlet综合练习:个人博客系统

2023-05-16

功能简介

1)注册新用户
在这里插入图片描述
在这里插入图片描述
2)登录已有用户
在这里插入图片描述
在这里插入图片描述
3)展示博客列表(包含文章标题以及作者信息),点击标题就会跳转到文章详情页
在这里插入图片描述
4)文章详情页中,显示文章标题,作者,以及文章内容
在这里插入图片描述
5)发布新的博客
在这里插入图片描述
在这里插入图片描述
6)删除自己的博客
点击文章列表后边的删除按钮就会删除文章,注意每个用户只能删除自己写的文章。
在这里插入图片描述

整个设计的目录结构

在这里插入图片描述

使用技术

maven:使用maven来管理依赖,打包项目
mysql:使用MySQL作为业务数据的存储
html:使用HTML来编写前端页面
tomcat:使用Tomcat作为Web项目部署的服务器
servlet:每个页面调用后台接口都需要使用Servlet来完成业务。
多线程:synchronized、volatile关键字,在多线程下访问Servlet共享变量,需要保证线程安全

项目准备

需要的资源

Maven、IDEA、MySQL、Chrome浏览器、Fiddler4抓包工具

创建项目

在这里插入图片描述
加入依赖:a)Servlet API b)MySQL connector
配置pom.xml 文件:
在这里插入图片描述

数据库设计

设计当前的代码中用到的数据库中有几张表,每个表包含哪些字段,每个表之间的关联关系。在这里我们需要两张表,用户和文章表。

  • 创建数据库
  • 设计用户表
    需要userId、name、password字段
  • 设计文章表
    需要articleId、title、content字段,且需要关联用户表,关系表现为1个用户多篇文章,所以在文章表建立外键userId关联用户表的主键userId

db.sql:

drop database if exists java16_blogdemo;
create database java16_blogdemo;

use java16_blogdemo;

drop table if exists user;
create table user (
    userId int primary key auto_increment,
    name varchar(50) unique,
    password varchar(50)
);

drop table if exists article;
create table article (
    articleId int primary key auto_increment,
    title varchar(255),
    content text,
    userId int,
    foreign key(userId) references user(userId)
);

在这里插入图片描述

实现数据库相关操作

创建一个DBUtil类来管理链接

package modle;

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;

/**
 * @ Created with IntelliJ IDEA.
 * @ClassName DBUtil
 * @Description
 * @Author by小房
 * @Date 2020/7/15 17:51
 */
// 管理数据库连接   建立连接    断开连接
public class DBUtil {
    private static volatile DataSource dataSource = null;
    private static final String URL = "jdbc:mysql://127.0.0.1:3306/java16_blogdemo?characterEncoding=utf-8&useSSL=true";
    private static final String USERNAME = "root";
    private static final String PASSWORD = "***";//这里写自己的密码

    public 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() {
         try {
             return getDataSource().getConnection();
         } catch (SQLException e) {
             e.printStackTrace();
         }
         return null;
     }
    // 通过这个方法来断开连接
    public static void close(Connection connection, PreparedStatement statement, ResultSet resultSet) {

            try {
                if (resultSet != null) {
                resultSet.close();
                }

                if (statement != null) {
                    statement.close();
                }

                if (connection != null) {
                    connection.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
    }

}

创建实体类User Article

User:

package modle;

/**
 * @ Created with IntelliJ IDEA.
 * @ClassName User
 * @Description
 * @Author by小房
 * @Date 2020/7/15 17:50
 */
public class User {
    private int userId;
    private String name;
    private String password;

    public int getUserId() {
        return userId;
    }

    public String getName() {
        return name;
    }

    public String getPassword() {
        return password;
    }

    public void setUserId(int userId) {
        this.userId = userId;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "User{" +
                "userId=" + userId +
                ", name='" + name + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

article:

package modle;

/**
 * @ Created with IntelliJ IDEA.
 * @ClassName Article
 * @Description
 * @Author by小房
 * @Date 2020/7/15 17:51
 */
public class Article {
    private int articleId;
    private String title;
    private String content;
    private int userId;

    public int getArticleId() {
        return articleId;
    }

    public String getTitle() {
        return title;
    }

    public String getContent() {
        return content;
    }

    public int getUserId() {
        return userId;
    }

    public void setArticleId(int articleId) {
        this.articleId = articleId;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public void setUserId(int userId) {
        this.userId = userId;
    }

    @Override
    public String toString() {
        return "Article{" +
                "articleId=" + articleId +
                ", title='" + title + '\'' +
                ", content='" + content + '\'' +
                ", userId=" + userId +
                '}';
    }
}

实现数据库的基本增删改查

Dao表示数据访问层
通过UserDao 这个类来实现对用户数据库表的操作

package modle;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * @ Created with IntelliJ IDEA.
 * @ClassName UserDao
 * @Description
 * @Author by小房
 * @Date 2020/7/16 22:03
 */
public class UserDao {
    // 1、新增用户
      public void add(User user) {
        // 1、获取数据库连接
        Connection connection = DBUtil.getConnection();
        // 2、拼装 sql
        String sql = "insert into  user values (null, ?, ?)";
        PreparedStatement statement = null;
        try {
            statement = connection.prepareStatement(sql);
            statement.setString(1, user.getName());
            statement.setString(2, user.getPassword());
            // 3、执行 sql
            int ret = statement.executeUpdate();
            if (ret != 1) {
                System.out.println("插入新用户失败");
                return;
            }
            System.out.println("插入新用户成功");
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            // 4、释放数据库连接
            DBUtil.close(connection, statement, null);
        }
    }

    // 2、按照名字查找用户

    public User selectByName(String name) {
        // 1、建立数据库连接
        Connection connection = DBUtil.getConnection();
        // 2、拼装sql
        String sql = "select * from user where name = ?";
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        try {
            statement = connection.prepareStatement(sql);
            statement.setString(1, name);
            // 3、执行 sql
            resultSet = statement.executeQuery();
            // 4、遍历结构集
            if (resultSet.next()) {
                User user = new User();
                user.setUserId(resultSet.getInt("userId"));
                user.setName(resultSet.getString("name"));
                user.setPassword(resultSet.getString("password"));
                return user;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBUtil.close(connection, statement, resultSet);
        }
        return null;
    }

    // 根据用户 id 找到用户信息
    public User selectById(int userId) {
        // 1、建立数据库连接
        Connection connection = DBUtil.getConnection();
        // 2、拼装sql
        String sql = "select * from user where userId = ?";
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        try {
            statement = connection.prepareStatement(sql);
            statement.setInt(1, userId);
            // 3、执行 sql
            resultSet = statement.executeQuery();
            // 4、遍历结构集
            if (resultSet.next()) {
                User user = new User();
                user.setUserId(resultSet.getInt("userId"));
                user.setName(resultSet.getString("name"));
                user.setPassword(resultSet.getString("password"));
                return user;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBUtil.close(connection, statement, resultSet);
        }
        return null;
    }
    /*public static void main(String[] args) {
        UserDao userDao = new UserDao();
        // 1、先测试 add 方法
        //User user = new User();
        //user.setName("***");
       // user.setPassword("********");
       // userDao.add(user);
        // 2、测试 selectByName
        //User user = userDao.selectByName("fwh");
        //System.out.println(user);
    }*/
}

通过ArticleDao 这个类来实现对文章的数据库操作

package modle;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * @ Created with IntelliJ IDEA.
 * @ClassName ArticleDao
 * @Description
 * @Author by小房
 * @Date 2020/7/16 20:43
 */
public class ArticleDao {
    // 1、新增文章
    public void add (Article article) {
        // 1、获取数据库连接
        Connection connection = DBUtil.getConnection();
        // 2、构造  sql
        String sql = "insert into article values (null, ?, ?, ?)";
        PreparedStatement statement = null;
        try {
            statement = connection.prepareStatement(sql);
            statement.setString(1, article.getTitle());
            statement.setString(2, article.getContent());
            statement.setInt(3, article.getUserId());
            // 3、执行sql
            int ret = statement.executeUpdate();
            if (ret != 1) {
                System.out.println("执行插入文章操作失败");
                return;
            }
            System.out.println("执行插入文章操作成功");
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            // 4、释放连接
            DBUtil.close(connection, statement, null);
        }
    }


    // 2、查看文章列表

    public List<Article> selectAll() {
        List<Article> articles = new ArrayList<Article>();
        // 1、建立连接
        Connection connection = DBUtil.getConnection();
        // 2、拼装 sql
        String sql = "select articleId, title, userId from article";
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        try {
            statement = connection.prepareStatement(sql);
            // 3、执行 sql
            resultSet = statement.executeQuery();
            // 4、遍历结果集
            while (resultSet.next()) {
                // 针对每一个结果记录,都构造一个对应的 Article 对象
                Article article = new Article();
                article.setArticleId(resultSet.getInt("articleId"));
                article.setTitle(resultSet.getString("title"));
                article.setUserId(resultSet.getInt("userId"));
                articles.add(article);
            }
            return articles;
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBUtil.close(connection, statement, resultSet);
        }
        return null;
    }

    // 3、查看指定文章详情
    public Article selectById (int articleId) {
        // 1、建立数据库连接
        Connection connection = DBUtil.getConnection();
        // 2、构造 SQL
        String sql = "select * from article where articleId = ?";
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        try {
            statement = connection.prepareStatement(sql);
            statement.setInt(1, articleId);
            // 3、执行 sql
            resultSet = statement.executeQuery();
            // 4、便利结果集
            if (resultSet.next()) {
                Article article = new Article();
                article.setArticleId(resultSet.getInt("articleId"));
                article.setTitle(resultSet.getString("title"));
                article.setContent(resultSet.getString("content"));
                article.setUserId(resultSet.getInt("userId"));
                return article;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBUtil.close(connection, statement, resultSet);
        }
        return null;
    }

    //  4、删除指定文章
    public void delete  (int articleId) {
        // 1、获取连接
        Connection connection = DBUtil.getConnection();
        // 2、拼装 sql
        String sql = "delete from article where articleId = ?";
        PreparedStatement statement = null;
        try {
            statement = connection.prepareStatement(sql);
            statement.setInt(1, articleId);
            int ret = statement.executeUpdate();
            if (ret != 1) {
                System.out.println("删除文章失败");
                return;
            }
            System.out.println("删除文章成功");
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBUtil.close(connection, statement, null);
        }
    }

    /*public static void main(String[] args) {
        ArticleDao articleDao = new ArticleDao();
        // 1、测试新增文章
        Article article = new Article();
        article.setTitle("this is title 2");
        article.setContent("this is content 1 this is content 1 this is content 1this is content 1this is content 1this is content 1this is content 1this is content 1this is content 1this is content 1this is content 1this is content 1this is content 1this is content 1this is content 1this is content 1this is content 1");
        article.setUserId(1);
        articleDao.add(article);
    }*/
}

单元测试

我们可以针对上边的数据库操作进行简单的测试,有助于提前发现问题,在这里我们需要一些库/框架可以便于测试。
pom.xml 中导入我们的依赖:
在这里插入图片描述

一个常见问题

我们可能会出现数据库连接不上,就会抛出异常
常见原因:
1)url 写错了
2)用户名,密码错误
3)数据库服务器没有正常启动
4)连接了其他主机的数据库

注意:如果拼装 sql ,直接使用String 来按照字符串拼接的方式来拼装,这样会出现一些问题,比如:不方便也不安全。要尽可能防止SQL注入
SQL注入理解:
在这里插入图片描述

进行前后端接口设计

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

分别实现接口API

LoginServlet:

package api;

import modle.User;
import modle.UserDao;
import view.HtmlGenerator;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

/**
 * @ Created with IntelliJ IDEA.
 * @ClassName LoginServlet
 * @Description
 * @Author by小房
 * @Date 2020/7/21 15:12
 */
public class LoginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html; charset=utf-8");
        //1、获取到用户名和密码, 并进行见到校验
        String name = req.getParameter("name");
        String password = req.getParameter("password");
        if (name == null || "".equals(name) || password == null || "".equals(password)) {
            String html = HtmlGenerator.getMessagePage("用户名和密码为空", "login.html");
            resp.getWriter().write(html);
            return;
        }
        // 2、数据库中查找,看用户是否存在
        // 3、对比密码是否正确
        UserDao userDao = new UserDao();
        User user = userDao.selectByName(name);
        if (user == null || !password.equals(user.getPassword())) {
            String html = HtmlGenerator.getMessagePage("用户名或者密码输入错误", "login.html");
            resp.getWriter().write(html);
            return;
        }
        // 4、匹配成功则认为登录成功,创建一个 Session
        HttpSession httpSession = req.getSession(true);
        httpSession.setAttribute("user", user);
        String html = HtmlGenerator.getMessagePage("登录成功!", "article");
        resp.getWriter().write(html);
    }
}

RegisterServlet:

package api;

import modle.User;
import modle.UserDao;
import view.HtmlGenerator;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @ Created with IntelliJ IDEA.
 * @ClassName RegisterServlet
 * @Description
 * @Author by小房
 * @Date 2020/7/20 16:46
 */
public class RegisterServlet extends HttpServlet {
    //浏览器通过 POST 方法提交注册信息给服务器

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html; charset=utf-8");
        // 1、获取到前端提交的数据(用户名, 密码),校验是否合法
        String name = req.getParameter("name");
        String password = req.getParameter("password");
        if (name == null || "".equals(password)) {
            // 用户提交的数据有误,返回一个错误页面
            String html = HtmlGenerator.getMessagePage("用户名或者密码输入错误", "register.html");
            resp.getWriter().write(html);
            return;
        }
        //2、拿着用户名在数据库中进行查找, 看看用户名是否已经存在,如果存在,认为注册失败(用户名不能重复)
        UserDao userDao = new UserDao();
        User existUser = userDao.selectByName(name);
        if (existUser != null) {
            String html = HtmlGenerator.getMessagePage("用户名重复,请换个名字!", "register.html");
            resp.getWriter().write(html);
            return;
        }

        //3、根据前端提交的数据, 构造 User 对象并插入到数据库当中
        User user = new User();
        user.setName(name);
        user.setPassword(password);
        userDao.add(user);

        // 4、返回一个结果页面, 提示当前注册成功
        String html = HtmlGenerator.getMessagePage("注册成功!点击跳转登录页面", "login.html");
        resp.getWriter().write(html);
    }
}

ArticleServlet:

package api;

import modle.Article;
import modle.ArticleDao;
import modle.User;
import modle.UserDao;
import view.HtmlGenerator;

import javax.servlet.ServletException;
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.util.List;

/**
 * @ Created with IntelliJ IDEA.
 * @ClassName ArticleServlet
 * @Description
 * @Author by小房
 * @Date 2020/7/21 15:34
 */
public class ArticleServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html; charset=utf-8");
        // 1、验证用户是否已经登录,如果尚未登录,就提示用户进行登录操作
        HttpSession httpSession = req.getSession(false);
        if (httpSession == null) {
            // 当前状态就是未登录状态
            String html = HtmlGenerator.getMessagePage("请先进行登录!", "login.html");
            resp.getWriter().write(html);
            return;
        }
        User user = (User) httpSession.getAttribute("user");
        // 2、判断请求是否存在 articleId 参数
        String articleIdStr = req.getParameter("articleId");
        if (articleIdStr == null) {
            // a)没有这个参数就去执行获取文章列表操作
            getAllArticle(user, resp);
        } else {
            // b) 有这个参数就去执行获取文章具体内容
            getOneArticle(Integer.parseInt(articleIdStr), user, resp);
        }
    }

    private void getOneArticle(int articleId, User user, HttpServletResponse resp) throws IOException {
        // 1、查找数据库
        ArticleDao articleDao = new ArticleDao();
        Article article = articleDao.selectById(articleId);
        if (article == null) {
            // 文章未找到
            String html = HtmlGenerator.getMessagePage("文章不存在", "article");
            resp.getWriter().write(html);
            return;
        }
        // 2、根据作者 id 找到作者信息,进一步得到作者姓名
        UserDao userDao = new UserDao();
        User author = userDao.selectById(article.getUserId());   //在这里刚才错误  在这里是根据用户id 获得作者信息
        // 3、构造页面
        String html = HtmlGenerator.getArticleDetailPage(article, user, author);
        resp.getWriter().write(html);
    }

    private void getAllArticle(User user, HttpServletResponse resp) throws IOException {
        // 1、查找数据库
        ArticleDao articleDao = new ArticleDao();
        List<Article> articles = articleDao.selectAll();
        // 2、构造页面
        String html = HtmlGenerator.getArticleListPage(articles, user);
        resp.getWriter().write(html);
    }

    // 实现新增文章的逻辑

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html; charset=utf-8");
        // 1、判断用户登录状态,如果用户上未登录,就要提醒用户登录
        HttpSession httpSession = req.getSession(false);
        if (httpSession == null) {
            String html = HtmlGenerator.getMessagePage("您尚未登录", "login.html");
            resp.getWriter().write(html);
            return;
        }
        User user = (User) httpSession.getAttribute("user");
        // 2、从请求中读取浏览器提交的数据(title , content) ,并进行简单的校验
        String title = req.getParameter("title");
        String content = req.getParameter("content");
        if (title == null || "".equals(title)
                || content == null ||"".equals(content)) {
            String html = HtmlGenerator.getMessagePage("提交的标题或者内容为空", "article");
            resp.getWriter().write(html);
            return;
        }
        // 3、把数据放在数据库中
        ArticleDao articleDao = new ArticleDao();
        Article article = new Article();
        article.setUserId(user.getUserId());
        article.setContent(content);
        article.setTitle(title);
        articleDao.add(article);
        // 4、返回一个插入成功的页面
        String html = HtmlGenerator.getMessagePage("发布成功!", "article");
        resp.getWriter().write(html);
        return;
    }
}

DeleteArticleServlet:

package api;

import modle.Article;
import modle.ArticleDao;
import modle.User;
import view.HtmlGenerator;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

/**
 * @ Created with IntelliJ IDEA.
 * @ClassName DeleteArticleServlet
 * @Description
 * @Author by小房
 * @Date 2020/7/21 18:08
 */
public class DeleteArticleServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html; charset=utf-8");
        // 1、验证用户的登录状态,如果未登录,肯定不能删除
        HttpSession httpSession = req.getSession(false);
        if (httpSession == null) {
            String html = HtmlGenerator.getMessagePage("您尚未登陆!", "login.html");
            resp.getWriter().write(html);
            return;
        }
        User user = (User) httpSession.getAttribute("user");

        // 2、根据请求内容, 获取要删除的文章id
        String articleIdStr = req.getParameter("articleId");
        if (articleIdStr == null || "".equals(articleIdStr)) {
            String html = HtmlGenerator.getMessagePage("要删除的文章不存在", "article");
            resp.getWriter().write(html);
            return;
        }

        // 3、根据文章id 查到文章的作者,只有当文章作者是当前用户才可以进行删除操作
        ArticleDao articleDao = new ArticleDao();
        Article article = articleDao.selectById(Integer.parseInt(articleIdStr));
        if (article.getUserId() != user.getUserId()) {
            String html = HtmlGenerator.getMessagePage("您只能删除自己的文章!", "article");
            resp.getWriter().write(html);
            return;
        }
        // 4、真正执行删除操作
        articleDao.delete(Integer.parseInt(articleIdStr));
        // 5、返回一个删除成功的页面
        String html = HtmlGenerator.getMessagePage("删除成功!",
                "article");
        resp.getWriter().write(html);
    }
}

注意:如果我们出现一些问题一定不要慌,要去定位问题解决问题。
比如:提交没反应
我们先用Fiddle 抓包看看,如果请求构造的有问题,那么就是网页的问题;如果请求构造ok,相应的结果错误,那么就是服务器的问题;如果请求构造ok,响应结果ok,可能还是网页的问题。

GitHub链接

java_blogDemo 完整代码

在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Servlet综合练习:个人博客系统 的相关文章

  • Archlinux 安装、美化、软件入门(一)

    本文章可能更新不及时 xff0c 前往我的博客阅读 xff0c 阅读体验更佳 xff1a https jin dan oier space 前言 本文只适用于 UEFI 引导 本文适用于从 Windows 迁移到 Archlinux 本文作
  • Archlinux 安装、美化、软件入门(二)

    本文章可能更新不及时 xff0c 前往我的博客阅读 xff0c 阅读体验更佳 xff1a https jin dan oier space 0x01 备份数据 使用 微PE 和 DiskGenius 工具进行数据备份和分区克隆 由于在 PE
  • Archlinux 安装、美化、软件入门(三)

    本文章可能更新不及时 xff0c 前往我的博客阅读 xff0c 阅读体验更佳 xff1a https jin dan oier space 0x03 安装系统 从U盘启动 待完善 连接Wi Fi xff08 有线用户直接跳过 xff09 输
  • 如何在笔记本电脑触摸板上进行中键单击

    Most laptop touchpads make it possible to perform a middle click but not all do In some situations you may need to enabl
  • Archlinux 安装、美化、软件入门(五)

    本文章可能更新不及时 xff0c 前往我的博客阅读 xff0c 阅读体验更佳 xff1a https jin dan oier space 0x07 系统美化 GRUB 美化 挑选喜欢的主题并下载 在 Gnome look 网站可以找到 G
  • 系统提示E: Unable to correct problems, you have held broken packages.错误解决

    系统提示E Unable to correct problems you have held broken packages 上网求答 xff0c 发现网上很多人选择用 aptitude xff0c 但是这个一般比较危险 xff0c 并不推
  • Linux kernel升级(详)

    环境 xff1a 系统版本 xff1a CentOS Linux release 7 4 1708 Core 内核版本 xff1a 3 10 0 693 el7 x86 64 内核由3 10升级5 4 升级说明 xff1a Linux Ke
  • stm32之蓝牙模块HC-05使用

    参考资料 xff1a 常用模块 HC 05蓝牙串口通信模块使用详解 xff08 实例 xff1a 手机蓝牙控制STM32单片机 xff09 HC 05蓝牙模块使用教程 HC 05蓝牙模块使用记录 补充与理解 xff1a 套餐有两个板子 一个
  • 2021-09-28->HttpClientUtil 工具包

    span class token keyword package span span class token namespace com span class token punctuation span ruoyi span class
  • 微信通知方法

    span class token comment 微信通知 span span class token function wxMessage span span class token punctuation span userId spa
  • 2021-09-29->微信支付

    接下来看微信支付jsapi接口是怎么调用的 步骤一 xff1a 获取微信支付四大参数 首先要想支持微信支付 必须拥有两个账号 微信公众平台 xff1a 账户 公众APPID xff0c APPSECEPT xff0c 微信商户平台商户ID
  • 20以为加减法

    span class token keyword for span span class token punctuation span span class token keyword int span i span class token
  • coturn服务配置

    COTURN服务配置 准备工作 一台带有公网ip的服务器 xff08 coturn服务部署在具有公网ip的服务器上 xff09 下载coturn wget https span class token operator span span
  • BigDecimal 精确算法 工具类

    BigDecimal a 61 new BigDecimal 101 BigDecimal b 61 new BigDecimal 111 使用compareTo方法比较 注意 xff1a a b均不能为null xff0c 否则会报空指针
  • wsappx_什么是“ wsappx”,为什么在我的PC上运行它?

    wsappx The wsappx process is part of Windows 8 and 10 and you may see it running in the background or even using a signi
  • python获取文件路径、文件夹内所有文件

    python获取文件路径 文件夹内所有文件名字 项目内相对路径 在test12 py内 想获取其所在文件夹的所有的表格文件 windows 第一种方案 34 34 34 获取路径 34 34 34 def list dir file dir
  • MySQL-常用内置函数(字符串、数值、日期、流程)

    字符串函数 xff1a 函数作用CONCAT str1 str2 拼接字符串 xff0c 返回拼接后的字符串LENGTH str 返回字符串字节长度 xff0c 注意是字节 xff0c 中文占3个LEFT str len 返回从最左边截取到
  • MySQL-基础语法DDL、DML、DQL、DCL

    DDL xff1a DDL Data Definition Language 数据库定义语言用来定义数据库对象 xff1a 数据库 xff0c 表 xff0c 列等 关键字 xff1a create drop alter 等 语法 DML语
  • VMware安装虚拟机Mac版

    VMware xff1a 1 不需要分区或重开机就能再同一台PC上使用多种操作系统 2 完全隔离并且保护不同操作系统的环境以及所有软件 资料 3 不同的操作系统之间还能互动操作 4 有复原功能 5 能够设置并且随时修改操作系统的操作环境 下
  • JSON转换工具

    JSON的处理 xff1a JSON JavaScript Object Notation xff1a 是一种轻量级的数据交换格式 它是基于 ECMAScript 规范的一个子集 xff0c 采用完全独立于编程语言的文本格式来存储和表示数据

随机推荐

  • MacOS Apple M1 安装ARM架构的JDK及动态切换版本

    JDK下载安装 xff1a 咱就是说 xff0c ARM版本的JDK就是一个字 xff0c 真特么快 xff0c 想变快吗 xff0c 赶紧下载叭 xff01 xff01 1 下载地址 xff1a https www azul com do
  • Go_详解TCP协议三次握手四次挥手

    三次握手 xff1a 三次握手表示建立通信阶段 xff0c 在TCP协议中 xff0c 在发送数据的准备阶段 xff0c 客户端与服务器之间的三次交互 xff0c 以保证连接的可靠 xff0c 由于这种面向连接的特性 xff0c TCP协议
  • Go_常量、iota(枚举)的使用

    常量 常量是在程序运行过程中 xff0c 其值不可以发生改变的数据 xff0c 常量无法被获取地址 常量中的数据类型能是布尔型 数字型 xff08 整型 浮点型和复数型 xff09 字符串 常量的定义是通过const关键字完成的 xff0c
  • Go_反射的使用

    反射可以在运行时动态地检查变量和类型 xff0c 并且可以调用变量和类型的方法 获取和修改变量的值和类型等 使用反射可以使程序更加灵活 xff0c 但也需要谨慎使用 基于反射的代码是极其脆弱的 xff0c 反射中的类型错误会在真正运行的时候
  • 登录注册页怎么做

    app常见页面 xff1a 引导页 xff1a 概念 xff1a 第一次安装App或者更新App后第一次打开App时所展示的可以滑动的页面 作用 xff1a 主要是用于展示产品本身的一些核心功能点或者特色 启动页 xff1a 概念 xff1
  • win10安装appx工具_如何在Windows 10上安装.Appx或.AppxBundle软件

    win10安装appx工具 Microsoft s new Universal Windows Platform applications use the Appx or AppxBundle file format They re nor
  • 本地mysql数据库开启远程访问

    本地mysql数据库开启远程访问 1 开启远程访问端口 3306端口 依次点击控制面板 系统和安全 windows防火墙 高级设置 入站规则 xff1b 设置端口为3306 一直点下一步 xff1b PS xff1a 入站 xff1a 别人
  • Go_String常用操作

    字符串操作 xff1a len xff1a 统计字符串的长度 span class token keyword func span span class token function main span span class token p
  • Arrarys常用的方法

    int newArrary 61 Arrays copyOf int original int newarrary length 拷贝数组 xff0c 可定义要拷贝的长度 Array copyOf 有进行复制的功能 xff0c 而且底层是调
  • Unity2019 打包Android报错 Android NDK not found

    打包报错 xff1a UnityException Android NDK not found Android NDK not found or invalid NDK配置报错 xff1a Edit gt Preferences gt Ex
  • 安装zabbix proxy

    Centos7搭建zabbix proxy5 0 概述安装创建数据库导入数据下载包安装 编译过程中的报错 概述 Zabbix 代理可以代表 Zabbix 服务器收集性能和可用性数据 这样 xff0c 代理可以自己承担一些收集数据的负载并卸载
  • Mac localhost无法访问

    Mac localhost无法访问 localhost 8080和127 0 0 1 8080可以访问nginx的文件 xff0c 但输入localhost和127 0 0 1都打不开了
  • 生产者与消费者问题(线程同步经典案例)

    生产者 xff08 producer xff09 和消费者 xff08 consumer xff09 问题是并发处理中最常见的一类问题 xff0c 是一个多线程同步问题的经典案例 可以这样描述这个问题 xff0c 有一个或者多个生产者产生某
  • Git忽略提交规则 & .gitignore配置总结

    Git忽略提交规则 xff06 gitignore配置总结 在使用Git的过程中 xff0c 我们喜欢有的文件比如日志 xff0c 临时文件 xff0c 编译的中间文件等不要提交到代码仓库 xff0c 这时就要设置相应的忽略规则 xff0c
  • Spring之配置文件

    Spring简介 Spring是什么 Spring 自带 IoC xff08 Inverse of Control 控制反转 xff09 和 AOP Aspect Oriented Programming 面向切面编程 可以很方便地对数据库
  • Ubuntu开启SSH服务远程登录

    Ubuntu开启SSH服务远程登录 Ubuntu下开启ssh服务并能通过MobaXterm或者 Xshell进行远程登录 本人使用的是window10系统安装的MobaXterm window10系统安装MobaXterm可以参考 http
  • MongoDB

    一 MongoDB简介 1 集成简介 spring data mongodb提供了MongoTemplate与MongoRepository两种方式访问mongodb xff0c MongoRepository操作简单 xff0c Mong
  • 更改桌面壁纸_使用DeskSlide轻松更改桌面墙纸

    更改桌面壁纸 Looking to add some variety to your desktop instead of looking at the same wallpaper day in and day out Have fun
  • 科学素养题(2022年2月-2022年10月)

    二月科学素养 在我国山东省和山西省中间的 山 34 是 C A泰山 B吕梁山 C太行山 D沂蒙山 在一些寻宝游戏中 每个线索都会指向下一个线索的位置 玩家可以顺着这些线索一个一个找到所有的元素 这样的寻宝游戏的设计与 数据结构有着异曲同工之
  • Servlet综合练习:个人博客系统

    功能简介 1 注册新用户 2 xff09 登录已有用户 3 xff09 展示博客列表 xff08 包含文章标题以及作者信息 xff09 xff0c 点击标题就会跳转到文章详情页 4 xff09 文章详情页中 xff0c 显示文章标题 xff