博客网站/部署服务器---继上篇前端页面接入后端

news2024/9/20 2:47:36

目录

准备工作

创建用户类博客类与连接数据库

创建博客类

创建用户类

创建连接数据库工具类

实现对数据库数据博客的操作

实现对数据库用户的操作

创建数据库语句

登录页面

前端

后端

博客列表

前端

注销登录

写入数据

判断用户是否登录

替换页面用户昵称

后端

处理注销登录 LogoutServlet/doGet

处理获取所有博客 BlogServlet/doGet

处理判断用户是否登录 loginServlet/doGet

处理替换页面用户昵称 UserinfoServlet/doGet

博客详情页

前端

注销登录

查询博客

判断用户是否登录

将博客详情页昵称替换为当前博客作者昵称/是否显示删除博客

后端

处理注销登录 LogoutServlet/doGet

处理查询博客 BlogServlet/doGet

处理判断用户是否登录 LoginServlet/doGet

处理将博客详情页昵称替换为当前博客作者昵称/是否显示删除博客 UserinfoServlet/doGet

博客编辑页

前端

后端 BlogServlet/doPost

部署

准备工作

下载jdk

下载tomcat

加权限

安装mysql

使用maven打包

访问


准备工作

在main下创建webapp文件夹下再创建WEB-INF文件夹下再创建web.xml文件

web.xml

<!DOCTYPE web-app PUBLIC
        "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
        "http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
    <display-name>Archetype Created Web Application</display-name>
</web-app>

需要用到

  1. javaservlet3.1
  2. jackson 版本随意
  3. mysql 根据你的mysql版本

这些均在Maven Repository: Search/Browse/Explore (mvnrepository.com)网址内下载

之后复制代码粘贴到pom.xml下的 <dependecies>标签内,并且设置打包格式为war这是tomcat要求的(之后部署需要使用),再设置包名

<dependencies>
        <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
        <!--jQuery库-->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
        <!--jackSon库-->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.13.5</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.mysql/mysql-connector-j -->
        <!--Mysql库-->
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <version>8.0.33</version>
        </dependency>


    </dependencies>

<!--    打包格式-->
    <packaging>war</packaging>

    <build>
<!--        包名-->
        <finalName>blog_system</finalName>
    </build>

创建用户类博客类与连接数据库

创建博客类

博客包含

  1. 博客ID
  2. 博客标题
  3. 博客内容
  4. 创建它的作者ID
  5. 发布博客的时间

之后ALT+Insert生成Get和Set方法(时间的get方法有所改变,需要格式化为日期格式)

package model;

import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.SimpleTimeZone;

//表示博客
public class Blog {
    private int blogId;
    private String title;
    private String content;
    private int userId;
    private Timestamp postTime;

    public int getBlogId() {
        return blogId;
    }

    public void setBlogId(int blogId) {
        this.blogId = blogId;
    }

    public String getTitle() {
        return title;
    }

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

    public String getContent() {
        return content;
    }

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

    public int getUserId() {
        return userId;
    }

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

    public String getPostTime() {
        //把时间戳构造成日期结构
        SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return simpleDateFormat.format(this.postTime);
    }

    public void setPostTime(Timestamp postTime) {
        this.postTime = postTime;
    }
}

创建用户类

  1. 用户包含
  2. 用户ID
  3. 用户名称
  4. 用户密码
  5. 判定该博客是否是登录用户的博客(后续删除博客功能需要用到、此变量不会写入数据库)

生成Get、Set方法

package model;

//表示用户
public class User {
    private int userId;

    private String username;

    private String password;

    private int isYourBlog=0;

    public int getIsYourBlog() {
        return isYourBlog;
    }

    public void setIsYourBlog(int isYourBlog) {
        this.isYourBlog = isYourBlog;
    }

    public int getUserId() {
        return userId;
    }

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

    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;
    }
}

创建连接数据库工具类

获取数据库连接 管理数据库的创建配置和管理

package model;

import com.mysql.cj.jdbc.MysqlDataSource;

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


public class DBUtil {
    //定义私有静态的DataSource对象,用于存储数据库连接信息。
    //volatile确保了对这个变量的读写操作都是原子性的,即使再多线程环境下
    //对这个变量访问也是线程安全的
    private volatile static DataSource dataSource=null;

    //获取数据库连接 管理数据库的创建、配置和管理
    private static javax.sql.DataSource getDataSource() {
        //如果为空时 加锁
        if(dataSource==null){
            synchronized (DBUtil.class){
                if (dataSource == null) {
                    dataSource = new MysqlDataSource();
                    ((MysqlDataSource)dataSource).setURL("jdbc:mysql://127.0.0.1:3306/blog_system?characterEncoding=utf8&useSSL=false");
                    ((MysqlDataSource)dataSource).setUser("root");
                    ((MysqlDataSource)dataSource).setPassword("monan1946");
                }
            }
        }
        return dataSource;
    }

    //这个方法是从DataSource获取一个具体的数据库连接
    //它通常在需要执行数据库操作时调用,比如执行SQL查询或更新
    public static Connection getConnection() throws SQLException {
        return getDataSource().getConnection();
    }

    //关闭数据库连接
    public static void close(Connection connection, PreparedStatement statement, ResultSet resultSet){
        if (resultSet!=null){
            try {
                resultSet.close();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }
        if(statement!=null){
            try {
                statement.close();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }
        if(connection!=null){
            try {
                connection.close();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }
    }


}

实现对数据库数据博客的操作

与数据库连接后,查询数据库,插入数据,删除数据操作

package model;

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

//import static jdk.nashorn.internal.objects.NativeString.substring;

//Dao Data Access Object 用来访问数据的对象
//针对博客的增删改查
public class BlogDao {
    //插入博客
    public void insert(Blog blog){
        Connection connection=null;
        PreparedStatement statement=null;
        try {
            //与数据库建立连接
            connection = DBUtil.getConnection();

            //构造SQL语句
            String sql = "insert into blog values(null,?,?,?,now())";
            //写入sql语句
            statement = connection.prepareStatement(sql);
            //写入问号对应的数据
            statement.setString(1, blog.getTitle());
            statement.setString(2, blog.getContent());
            statement.setInt(3, blog.getUserId());
            //执行sql
            int ret = statement.executeUpdate();
            if (ret == 1) {
                System.out.println("插入成功");
            } else {
                System.out.println("插入失败");
            }
        }catch (SQLException e) {
            e.printStackTrace();
        }finally {
            //关闭连接
            DBUtil.close(connection,statement,null);
        }
    }

    //查询所有博客
    public List<Blog> selectAll(){
        Connection connection=null;
        PreparedStatement statement=null;
        ResultSet resultSet=null;
        List<Blog> blogs=new ArrayList<>();
        try {
            //与数据库建立连接
            connection=DBUtil.getConnection();

            //构造sql
            //让新的先读取 页面新的在最上面
            String sql="select * from blog order by postTime desc";
            //写入sql
            statement=connection.prepareStatement(sql);
            //执行SQL
            resultSet=statement.executeQuery();
            //遍历结果集合
            while (resultSet.next()){
                Blog blog=new Blog();
                blog.setBlogId(resultSet.getInt("blogId"));
                blog.setTitle(resultSet.getString("title"));
                String content=resultSet.getString("content");
//                //如果长度大于100时,只截取100个字符作为摘要
                if(content.length()>100){
                    content=content.substring(0,100);
                }
                //如果不大于100 不截取
                blog.setContent(content);
                blog.setUserId(resultSet.getInt("userId"));
                blog.setPostTime(resultSet.getTimestamp("postTime"));
                blogs.add(blog);
            }

        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            //关闭连接
            DBUtil.close(connection,statement,resultSet);
        }
        return blogs;
    }

    //查询一篇博客
    public Blog selectOne(int blogId) {
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        try {
            // 1. 和数据库建立连接
            connection = DBUtil.getConnection();
            // 2. 构造 SQL
            String sql = "select * from blog where blogId = ?";
            statement = connection.prepareStatement(sql);
            statement.setInt(1, blogId);
            // 3. 执行 SQL
            resultSet = statement.executeQuery();
            // 4. 遍历结果集. 由于是按照 blogId 来查询. blogId 是自增主键, 不能重复.
            //    此处的查询结果不可能是多条记录. 只能是 1 条或者 0 条.
            if (resultSet.next()) {
                Blog blog = new Blog();
                blog.setBlogId(resultSet.getInt("blogId"));
                blog.setTitle(resultSet.getString("title"));
                blog.setContent(resultSet.getString("content"));
                blog.setPostTime(resultSet.getTimestamp("postTime"));
                blog.setUserId(resultSet.getInt("userId"));
                return blog;
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } finally {
            // 5. 关闭资源
            DBUtil.close(connection, statement, resultSet);
        }

        return null;
    }

    //删除博客
    public void delete(int blogId){
        Connection connection=null;
        PreparedStatement statement=null;
        ResultSet resultSet=null;
        try {
            //建立连接
            connection =DBUtil.getConnection();

            //构造SQL语句
            String sql="delete from blog where blogId=?";
            //写入sql
            statement=connection.prepareStatement(sql);
            //替换?
            statement.setInt(1,blogId);
            //执行sql
            int ret=statement.executeUpdate();
            if(ret==1){
                System.out.println("删除成功");
            }
            else{
                System.out.println("删除失败");
            }
        } catch (SQLException e) {

            e.printStackTrace();
        }finally {
            DBUtil.close(connection,statement,null);
        }
    }
}

实现对数据库用户的操作

对数据库内的数据进行操作

package model;

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

//Dao Data Access Object 用来访问数据的对象
//针对用户的增删改查
public class UserDao {
    //查询用户
    public User selectByName(String username){
        Connection connection=null;
        PreparedStatement statement=null;
        ResultSet resultSet=null;
        try {
            //建立连接
            connection=DBUtil.getConnection();
            //构造sql语句
            String sql="select * from user where username=?";
            //写入sql
            statement=connection.prepareStatement(sql);
            //填入问号
            statement.setString(1,username);
            //执行sql
            resultSet=statement.executeQuery();
            if(resultSet.next()){
                User user=new User();
                user.setUserId(resultSet.getInt("userId"));
                user.setUsername(resultSet.getString("username"));
                user.setPassword(resultSet.getString("password"));
                return user;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            DBUtil.close(connection,statement,resultSet);
        }
        return null;
    }

    public User selectById(int userId){
        Connection connection=null;
        PreparedStatement statement=null;
        ResultSet resultSet=null;
        try {
            //建立连接
            connection=DBUtil.getConnection();
            //构造sql语句
            String sql="select * from user where userId=?";
            //写入sql
            statement=connection.prepareStatement(sql);
            //填入问号
            statement.setInt(1,userId);
            //执行sql
            resultSet=statement.executeQuery();
            if(resultSet.next()){
                User user=new User();
                user.setUserId(resultSet.getInt("userId"));
                user.setUsername(resultSet.getString("username"));
                user.setPassword(resultSet.getString("password"));
                return user;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            DBUtil.close(connection,statement,resultSet);
        }
        return null;
    }
}

创建数据库语句

需要把创建数据库的语句放入db.sql中,方便后续更换数据库使用

create database blog_system;

use blog_system;

create table blog(
    blogId int primary key auto_increment, --主键 自增 博客ID
    title varchar(1024), --博客标题
    content mediumtext, --博客正文  mediutext类型很长
    userId int, --作者id
    postTime datetime --发布事件
);

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

create table user(
    userId int primary key auto_increment, --用户id
    username varchar(128) unique , --用户名
    password varchar(128) --密码
);
create table user(
    userId int primary key auto_increment,
    username varchar(128) unique ,
    password varchar(128)
);

登录页面

前端

login/loginServlet

前端将用户写入的数据已post方法提交给后端

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <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>
        <!-- 导航栏 -->
        <div class="nav">
            <!-- logo图片 -->
            <img src="image/logo.jpg" alt="" width="50px">
    
            <span class="title">我的博客系统</span>
            <span class="spacer"></span>
    
            <!-- 导航栏 -->
            <a href="blog_list.html">主页</a>
            <a href="blog_edit.html">写博客</a>
        </div>

        <!-- 登录板块 -->
        <div class="login-container">
            <div class="login-dialog">
                <p>登录</p>
            <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">
                    <input type="submit" value="提交"id="submit">
                </div>
            </form>
            </div>
        </div>
</body>
</html>

后端

  1. 后端调用doPost方法
  2. 使用resp.getParameter方法获取数据
  3. 去数据库内查询数据。
  4. 查询不到则响应登录失败
  5. 若查询到时,创建session HttpSession session= req.getSession()
  6. 也就是浏览器内的cookie session.setAttribute把此用户存储进去,方便后续使用之后登录成功跳转至博客列表
package controller;

import model.User;
import model.UserDao;

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("/login")
public class loginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //告诉servlet(服务器)按照utf格式解析请求中的body
        //如果不使用这个 中文格式的会乱码
        req.setCharacterEncoding("utf8");

        //告诉浏览器 按照utf8格式解析响应
//        resp.setCharacterEncoding("utf8");

        resp.setContentType("text/html;charset=utf8");
        String username=req.getParameter("username");
        String password=req.getParameter("password");

//        System.out.println(username);
//        System.out.println(password);

//        if(username.equals("user")&&password.equals("123")){
//            resp.getWriter().write("登录成功");
//        }
//        else
//        {
//            resp.getWriter().write("用户名或密码错误");
//        }

        UserDao userDao=new UserDao();
        User user=userDao.selectByName(username);
        if(user==null){
            resp.getWriter().write("用户名或密码错误");
            return;
        }
        if(!user.getPassword().equals(password)){
            resp.getWriter().write("用户名或密码错误");
            return;
        }
        //到这里就是登录成功了

        //构造会话 cookie
        HttpSession session= req.getSession();

        //把信息存到cookie内,方便后续使用
        session.setAttribute("user",user);

        //登录成功后 跳转页面
        resp.sendRedirect("blog_list.html");
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //验证登录状态
        //如果用户未登录,强制重定向到登录页面
        //如果用户已登录,不做动作

        //取查询session
        HttpSession session=req.getSession(false);
        if(session==null){
            //如果连session都没有 返回403状态码
            //403状态码就是代表用户未登录的状态码
            resp.setStatus(403);
            return;
        }
        //取cookie查找是否有user这个用户
        //这个user不是用户名 而是user内的用户名
        User user= (User) session.getAttribute("user");
        if(user==null){
            //没有这个用户,说明未登录
            resp.setStatus(403);
            return;
        }
        //到这说明用户已经登录成功
        resp.setStatus(200);
    }
}

博客列表

前端

前端使用ajax方法,所以需要引入jquery

jquery需要从jQuery CDN  链接内点击minified 复制

https://code.jquery.com/jquery-3.7.1.min.js

之后引入即可使用

前端整体代码

<!DOCTYPE html>
 <html lang="en">
<head>
    <meta charset="UTF-8">
    <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.css">
</head>
<body>
    <!-- 导航栏 -->
    <div class="nav">
        <!-- logo图片 -->
        <img src="image/logo.jpg" alt="" width="50px">

        <span class="title">我的博客系统</span>
        <span class="spacer"></span>

        <!-- 导航栏 -->
        <a href="blog_list.html">主页</a>
        <a href="blog_edit.html">写博客</a>
        <a href="logout">注销</a>
<!--        a会直接向对应路径发起get请求-->
    </div>

    <!-- 页面主体 -->
    <div class="container">

        <!-- 左侧个人信息 -->
        <div class="container-left">
            <div class="card">
                <img src="image/蕾姆.jpg" alt="">
                <h2>墨轩111</h2>
                <a href="#">github链接</a>
                <div class="counter">
                    <span>文章</span>
                    <span>分类</span>
                </div>
                <div class="counter">
                    <span>2</span>
                    <span>3</span>
                </div>
            </div>


        <!-- 右侧个人信息 -->
        </div>
        <div class="container-right">
            <!-- <div class="blog">这是我的第一篇文章</div>
            <div class="date">2024-3-27 20:20</div>
            <div class="desc">文章内容Lorem ipsum dolor sit amet consectetur, adipisicing elit. At laboriosam quis quos, numquam tenetur cum ipsa architecto nihil, a asperiores error fugit. Praesentium eaque animi esse nemo ut nobis atque.</div>
            <a href="blog_detail.html">查看全文 &gt;&gt; </a> -->
            <!-- &gt;是html的> 正常的>无法之间写入 -->
        </div>
    </div>

    <!-- 引入jquery -->
    <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
    <script src="js/app.js"></script>
    <script>
        function getBlogs(){
            //构造ajax
            $.ajax({
                type:'get',
                url:'blog',
                success: function(body){
                    let container=document.querySelector('.container-right');
                    //后端返回的是json数据
                    //如果Content-Type是application/json,jquery ajax会把body转成js对象
                    for(let blog of body){
                        //构造最外层的div
                        let blogDiv=document.createElement('div');
                        blogDiv.className='blog';

                        //创建博客标题
                        let titleDiv=document.createElement('div');
                        titleDiv.className='title';
                        //把后端传来的json,被jackson解析成blog对象,对象内的标题属性赋值
                        titleDiv.innerHTML=blog.title;
                        //把titleDiv添加在blogDiv内
                        blogDiv.appendChild(titleDiv);

                        //创建日期
                        let dateDiv=document.createElement('div');
                        dateDiv.className='date';
                        //把后端传来的json,被jackson解析成blog对象 对象内的时间属性赋值
                        dateDiv.innerHTML=blog.postTime;
                        //把dateDiv添加到blogDiv内
                        blogDiv.appendChild(dateDiv);

                        //创建内容
                        let descDiv=document.createElement('div');
                        descDiv.className='desc';
                        //把把后端传来的json,被jackson解析成blog对象 对象内的内容属性赋值
                        descDiv.innerHTML=blog.content;
                        //把descDiv添加到blogDiv内
                        blogDiv.appendChild(descDiv);

                        //创建按钮
                        let a=document.createElement('a');
                        a.innerHTML='查看全文 >>';
                        //传递这篇博客的ID是多少 后端才能取查询这篇博客的详细页
                        a.href='blog_detail.html?blogId='+blog.blogId;
                        blogDiv.appendChild(a);

                        //把blogDiv添加到container内
                        container.appendChild(blogDiv);
                    }
                }
            });
        }
        getBlogs();

        //使用ajax构造get方法。判断当前是否用户
        // 如果没登陆,强制跳转到登录页面
        checkLogin();

        //将博客列表的昵称替换为当前登录用户的昵称
        function GetUser(){
            $.ajax({
                type: 'get',
                url:'userInfo',
                //后端查询失败时,发送状态码为403 403不会触发回调函数
                success:function (body){
                    //将登录的用户名替换上去
                    let user=document.querySelector('.card h2');
                    user.innerHTML=body.username;
                }
            });
        }
        GetUser();
    </script>
</body>
</html>

注销登录

注意:注销登录和注销账号是不同的,注销登录即退出登录,而注销账户是删除账号

<a href="logout">注销</a>
<!--        a会直接向对应路径发起get请求-->

写入数据

  1. 前端构造ajax构造get方法,发送给后端。
  2. 调用回调函数。
  3. 遍历后端传来的数据(想要用遍历,那么后端传来的数据一定是像List这种可遍历的,如何只传来的对象,那就无法遍历)
  4. 创建div 分别把博客的标题,时间,内容创建,把后端数据都写入。并且创建查询博客详情页的按键。当按下这个按键时,会把博客ID传递给博客详情页,详情页就能拿着这个ID去后端查询此博客
  5. 把整体div放入原先的div内
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
    <script src="js/app.js"></script>
    <script>
        function getBlogs(){
            //构造ajax
            $.ajax({
                type:'get',
                url:'blog',
                success: function(body){
                    let container=document.querySelector('.container-right');
                    //后端返回的是json数据
                    //如果Content-Type是application/json,jquery ajax会把body转成js对象
                    for(let blog of body){
                        //构造最外层的div
                        let blogDiv=document.createElement('div');
                        blogDiv.className='blog';

                        //创建博客标题
                        let titleDiv=document.createElement('div');
                        titleDiv.className='title';
                        //把后端传来的json,被jackson解析成blog对象,对象内的标题属性赋值
                        titleDiv.innerHTML=blog.title;
                        //把titleDiv添加在blogDiv内
                        blogDiv.appendChild(titleDiv);

                        //创建日期
                        let dateDiv=document.createElement('div');
                        dateDiv.className='date';
                        //把后端传来的json,被jackson解析成blog对象 对象内的时间属性赋值
                        dateDiv.innerHTML=blog.postTime;
                        //把dateDiv添加到blogDiv内
                        blogDiv.appendChild(dateDiv);

                        //创建内容
                        let descDiv=document.createElement('div');
                        descDiv.className='desc';
                        //把把后端传来的json,被jackson解析成blog对象 对象内的内容属性赋值
                        descDiv.innerHTML=blog.content;
                        //把descDiv添加到blogDiv内
                        blogDiv.appendChild(descDiv);

                        //创建按钮
                        let a=document.createElement('a');
                        a.innerHTML='查看全文 >>';
                        //传递这篇博客的ID是多少 后端才能取查询这篇博客的详细页
                        a.href='blog_detail.html?blogId='+blog.blogId;
                        blogDiv.appendChild(a);

                        //把blogDiv添加到container内
                        container.appendChild(blogDiv);
                    }
                }
            });
        }
        getBlogs();

判断用户是否登录

因为这个功能是多个页面都会使用,所以写入js文件内,在前面引入js即可调用这个方法

//使用ajax构造get方法。判断当前是否用户
        // 如果没登陆,强制跳转到登录页面
        checkLogin();

这个在js内的app.js文件

function checkLogin(){
    $.ajax({
        type: 'get',
        url:'login',
        success:function (){
            // 当客户端响应200状态码时,说明用户已登录,不做处理
        },
        error:function (){
            //发客户端响应403时 就会触发error

            //强制跳转登录页面
            location.assign('login.html');
        }
    })
}

替换页面用户昵称

向后端发起get方法,把页面昵称替换为当前登录用户的昵称

function GetUser(){
            $.ajax({
                type: 'get',
                url:'userInfo',
                //后端查询失败时,发送状态码为403 403不会触发回调函数
                success:function (body){
                    //将登录的用户名替换上去
                    let user=document.querySelector('.card h2');
                    user.innerHTML=body.username;
                }
            });
        }
        GetUser();

后端

处理注销登录 LogoutServlet/doGet

  1. req.getSession查询是否创建了session
  2. 使用session.removeAttribute删除session的当前的用户
  3. resp.sendRedirect强制跳转到登录页面
@WebServlet("/logout")
public class LogoutServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //注销功能
        //删除session中的对象 就相当于取消状态

        //查找是否有session
        HttpSession session=req.getSession(false);
        if(session==null) {
            resp.setStatus(403);
            return;
        }

        //删除session中的user
        session.removeAttribute("user");
        //重定向到登录页面
        resp.sendRedirect("login.html");
    }
}

处理获取所有博客 BlogServlet/doGet

  1. 想要构造JSON格式,就得创建ObjectMapper
  2. 因为前端使用的是ajax,后端需要响应json格式。所以需要用resp.setContentType设置响应格式 (application/json;charset=utf8)
  3. 创建操作博客内容的数据库类
  4. 查看req.getParameter获取前端是否传来了博客ID,如果传来了,说明前端想要查询单个博客(这里是博客详情页,后续讲)
  5. 如果没传博客ID,说明前端想要查询所有博客,博客列表是查询所有博客
  6. 调用blogDo查询博客类,查询所有博客,并且把这些数据放入List,保证所有博客可以遍历。
  7. 使用objectMapper.writeValueAsString将数据构造成json格式
  8. 响应数据
@Override
    //发送博客列表或博客详情页的内容
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //想要构造JSON格式,就得用到此类
        private ObjectMapper objectMapper=new ObjectMapper();
        resp.setContentType("application/json;charset=utf8");
        //要拿到写数据库操作的类
        BlogDao blogDao=new BlogDao();
        //获取url中的博客ID
        String blogId=req.getParameter("blogId");
        System.out.println(blogId);
        //为空时 说明时获取博客列表,而不是获取博客详情
        if(blogId==null){
            //查询所有 返回的是list 每个类型是一个博客类型
            List<Blog> blogs=blogDao.selectAll();
            //转成json格式

            String jsonString=objectMapper.writeValueAsString(blogs);
            //响应
            resp.getWriter().write(jsonString);
        }else{
            //如果获取到博客ID时,说明时获取博客详情页
            //使用数据库查找这个博客ID
            Blog blog=blogDao.selectOne(Integer.parseInt(blogId));
            //记住,传json格式,如果你要用for循环 那么你的对象一定要是可迭代的对象
            //如果你单构造个类过去,你用for是肯定循环不了的,你必须使用List这种可以迭代的对象,才能使用这个迭代循环
            List<Blog> blogs=new ArrayList<>();
            blogs.add(blog);

            //你也可以单传个对象 到前端那不用循环直接使用也可以
//            List<Blog> blogs=new ArrayList<>();
//            String jsonString=objectMapper.writeValueAsString(blog);


            //转为json格式
            String jsonString=objectMapper.writeValueAsString(blogs);
            //响应
            resp.getWriter().write(jsonString);
        }
    }

处理判断用户是否登录 loginServlet/doGet

  1. req.getSession查询是否创建了session(这里可以直接判断用户是否登录了,因为只要登录,那么就一定创建了session
  2. 为空时,resp.setStatus响应状态码403
  3. 如果不为空时,session.getAttribute查询session是否有该用户
  4. 如果为空,则有创建session,但没有此用户,setStatus响应状态码403
  5. 如果也不为空,说明该用户以及登录,setStatus响应状态码200
  6. 响应状态码403是为了不让前端调用回调函数,当返回200时,才调用
@Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //验证登录状态
        //如果用户未登录,强制重定向到登录页面
        //如果用户已登录,不做动作

        //取查询session
        HttpSession session=req.getSession(false);
        if(session==null){
            //如果连session都没有 返回403状态码
            //403状态码就是代表用户未登录的状态码
            resp.setStatus(403);
            return;
        }
        //取cookie查找是否有user这个用户
        //这个user不是用户名 而是user内的用户名
        User user= (User) session.getAttribute("user");
        if(user==null){
            //没有这个用户,说明未登录
            resp.setStatus(403);
            return;
        }
        //到这说明用户已经登录成功
        resp.setStatus(200);
    }

处理替换页面用户昵称 UserinfoServlet/doGet

  1. 想要构造JSON格式,就得创建此类objectMapper
  2. req.getParameter获取blogId(如果为空,则是博客列表发来的,想要获取此博客的用户名,如果不为空,是博客详情页发来的,判断此博客是否是当前登录用户的博客)
  3. req.getSession判断是否有session
  4. session.getAttribute 查询session是否有该用户,获取此用户
  5. 当blogId为空时,博客列表发来的
  6. 首先用户的密码设为空串 (不是修改数据库内的数据)
  7. resp.setContentType设置响应格式
  8. objectMapper.writeValueAsString数据构造为JSON格式
  9. 响应数据
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //想要构造json 就要创建这个类
        ObjectMapper objectMapper=new ObjectMapper();

        String blogid=req.getParameter("blogId");

        //直接取查找是否有cookie
        HttpSession session=req.getSession(false);
        if(session==null){
            //后端查询失败时,发送状态码为403 403不会触发回调函数
            resp.setStatus(403);
            resp.setContentType("text/html;charset=utf8");
            resp.getWriter().write("没有该用户");
            return;
        }
        //获取当前登录用户
        User user= (User) session.getAttribute("user");
        if(user==null){
            resp.setStatus(403);
            resp.setContentType("text/html;charset=utf8");
            resp.getWriter().write("没有该用户");
            return;
        }

        if(blogid==null){
            //查询登录的用户
            //当url中的查询字符串中没有blogId时,说明是博客列表发来的请求
            //不用让密码在body中明文显示
            user.setPassword("");
            resp.setContentType("application/json;charset=utf8");
            //构造成json格式
            //返回登录的用户
            String jsonString=objectMapper.writeValueAsString(user);
            //写入
            resp.getWriter().write(jsonString);

博客详情页

前端

总体

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <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.css">
    <link rel="stylesheet" href="css/blog_detail.css">

    <!-- 引入 editor.md 的依赖 -->
    <link rel="stylesheet" href="editor.md/css/editormd.min.css" />
    <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.js"></script>
</head>
<body>
        <!-- 导航栏 -->
        <div class="nav">
            <!-- logo图片 -->
            <img src="image/logo.jpg" alt="" width="50px">
    
            <span class="title">我的博客系统</span>
            <span class="spacer"></span>
    
            <!-- 导航栏 -->
            <a href="blog_list.html">主页</a>
            <a href="blog_edit.html">写博客</a>
            <a href="logout">注销</a><!--        a会直接向对应路径发起get请求-->
            <div class="dete"></div>
<!--            删除博客-->
        </div>

        <!-- 页面主体 -->
    <div class="container">

        <!-- 左侧个人信息 -->
        <div class="container-left">
            <div class="card">
                <img src="image/蕾姆.jpg" alt="">
                <h2>墨轩111</h2>
                <a href="#">github链接</a>
                <div class="counter">
                    <span>文章</span>
                    <span>分类</span>
                </div>
                <div class="counter">
                    <span>2</span>
                    <span>3</span>
                </div>
            </div>
        </div>

        <!-- 右侧个人信息 -->
<!--        <div class="container-right">-->
<!--        </div>-->

        <div class="container-right">
            <!-- 这个 div 里来放博客的内容 -->
            <div class="blog-content">
            </div>
        </div>
    </div>


        <script src="https://code.jquery.com/jquery-3.6.1.min.js"></script>
        <script src="js/app.js"></script>
    <script>
        function getBlogs() {
            //构造ajax
            $.ajax({
                type: 'get',
                //博客列表传来的
                url: 'blog' + location.search,
                success: function (body) {
                    let container = document.querySelector('.container-right');
                    //后端返回的是json数据
                    //如果Content-Type是application/json,jquery ajax会把body转成js对象
                    for (let blog of body) {
                        //构造最外层的div
                        let blogDiv = document.createElement('div');
                        blogDiv.className = 'blog';

                        //创建博客标题
                        let titleDiv = document.createElement('div');
                        titleDiv.className = 'title';
                        //把后端传来的json,被jackson解析成blog对象,对象内的标题属性赋值
                        titleDiv.innerHTML = blog.title;
                        //把titleDiv添加在blogDiv内
                        blogDiv.appendChild(titleDiv);

                        //创建日期
                        let dateDiv = document.createElement('div');
                        dateDiv.className = 'date';
                        //把后端传来的json,被jackson解析成blog对象 对象内的时间属性赋值
                        dateDiv.innerHTML = blog.postTime;
                        //把dateDiv添加到blogDiv内
                        blogDiv.appendChild(dateDiv);

                        //创建内容
                        let descDiv = document.createElement('div');
                        descDiv.className = 'desc';
                        //把把后端传来的json,被jackson解析成blog对象 对象内的内容属性赋值
                        descDiv.innerHTML = blog.content;
                        //把descDiv添加到blogDiv内
                        blogDiv.appendChild(descDiv);

                        //把blogDiv添加到container内
                        container.appendChild(blogDiv);
                    }
                }
            });
        }

        getBlogs();

        checkLogin();

                function GetUser(){
                $.ajax({
                type: 'get',
                url:'userInfo'+location.search,//加个博客ID 让后端查找这篇博客
                success:function (body){
                    //将这篇作者的用户名替换上去
                let user=document.querySelector('.card h2');
                user.innerHTML=body.username;
                //当这篇博客是当前用户的 那么就显示删除按钮
                if(body.isYourBlog){
                    let delet=document.createElement('a');
                    delet.className="delete";
                    delet.innerHTML="删除博客"
                    delet.href='blogdelete'+location.search;

                    let de=document.querySelector('.dete');
                    de.appendChild(delet);
                }
            }
            });
            }
        GetUser();
    </script>
</body>
</html>

注销登录

与博客列表一致这里不再赘述

查询博客

  1. 构造ajax的get方法,url是博客列表传来的博客ID,传给后端,后端才能根据这个ID查询博客
  2. 后端传来了数据,只要是json格式(application/json;charset=utf8)那么ajax就会把body转成js的对象。
  3. 创建div,分别把博客的标题、时间、内容写入
<script src="https://code.jquery.com/jquery-3.6.1.min.js"></script>
        <script src="js/app.js"></script>
    <script>
        function getBlogs() {
            //构造ajax
            $.ajax({
                type: 'get',
                //博客列表传来的
                url: 'blog' + location.search,
                success: function (body) {
                    let container = document.querySelector('.container-right');
                    //后端返回的是json数据
                    //如果Content-Type是application/json,jquery ajax会把body转成js对象
                    for (let blog of body) {
                        //构造最外层的div
                        let blogDiv = document.createElement('div');
                        blogDiv.className = 'blog';

                        //创建博客标题
                        let titleDiv = document.createElement('div');
                        titleDiv.className = 'title';
                        //把后端传来的json,被jackson解析成blog对象,对象内的标题属性赋值
                        titleDiv.innerHTML = blog.title;
                        //把titleDiv添加在blogDiv内
                        blogDiv.appendChild(titleDiv);

                        //创建日期
                        let dateDiv = document.createElement('div');
                        dateDiv.className = 'date';
                        //把后端传来的json,被jackson解析成blog对象 对象内的时间属性赋值
                        dateDiv.innerHTML = blog.postTime;
                        //把dateDiv添加到blogDiv内
                        blogDiv.appendChild(dateDiv);

                        //创建内容
                        let descDiv = document.createElement('div');
                        descDiv.className = 'desc';
                        //把把后端传来的json,被jackson解析成blog对象 对象内的内容属性赋值
                        descDiv.innerHTML = blog.content;
                        //把descDiv添加到blogDiv内
                        blogDiv.appendChild(descDiv);

                        //把blogDiv添加到container内
                        container.appendChild(blogDiv);
                    }
                }
            });
        }

        getBlogs();

判断用户是否登录

这个与博客列表页一样,这里不再赘述

将博客详情页昵称替换为当前博客作者昵称/是否显示删除博客

  1. 构造ajax的get方法,url传入博客列表传来的博客ID
  2. 获取数据后,将后端的数据写入昵称
  3. 判断isYourBlog是否为1 (1是说明当前登录用户的ID与博客ID相同(此篇博客是当前用户写的),说明当前用户有支配此篇博客的权利,显示删除博客 0说明当前登录用户的ID与博客ID不同(此篇博客不是当前用户写的,没有支配全,不显示删除博客)
  4. 为1时,创建a标签,命名为删除博客,链接到删除博客的后端,并且传入博客ID
  5. 再放入原先的div
function GetUser(){
                $.ajax({
                type: 'get',
                url:'userInfo'+location.search,//加个博客ID 让后端查找这篇博客
                success:function (body){
                    //将这篇作者的用户名替换上去
                let user=document.querySelector('.card h2');
                user.innerHTML=body.username;
                //当这篇博客是当前用户的 那么就显示删除按钮
                if(body.isYourBlog){
                    let delet=document.createElement('a');
                    delet.className="delete";
                    delet.innerHTML="删除博客"
                    delet.href='blogdelete'+location.search;

                    let de=document.querySelector('.dete');
                    de.appendChild(delet);
                }
            }
            });
            }
        GetUser();

后端

处理注销登录 LogoutServlet/doGet

这里与博客列表一致,不再赘述

处理查询博客 BlogServlet/doGet

  1. resp.setContentTyoe设置响应格式 (application/json;charset=utf8)
  2. 创建操作博客类
  3. req.getParameter获取前端传来的博客ID
  4. 这里是查询单个博客,所以是不为空的
  5. 将博客ID转为int 并且从数据库内查询
  6. 将博客放入List(这里最好不用放入List,因为只是单个博客,不需要迭代,我只是演示)
  7. objectMapper.writeVlueAsString构造成JSON格式
  8. 响应数据
else{


            resp.setContentType("application/json;charset=utf8");
            //如果获取到博客ID时,说明时获取博客详情页
            //使用数据库查找这个博客ID
            String blogId=req.getParameter("blogId");
            Blog blog=blogDao.selectOne(Integer.parseInt(blogId));
            //记住,传json格式,如果你要用for循环 那么你的对象一定要是可迭代的对象
            //如果你单构造个类过去,你用for是肯定循环不了的,你必须使用List这种可以迭代的对象,才能使用这个迭代循环
            List<Blog> blogs=new ArrayList<>();
            blogs.add(blog);

            //你也可以单传个对象 到前端那不用循环直接使用也可以
//            List<Blog> blogs=new ArrayList<>();
//            String jsonString=objectMapper.writeValueAsString(blog);


            //转为json格式
            String jsonString=objectMapper.writeValueAsString(blogs);
            //响应
            resp.getWriter().write(jsonString);
        }

处理判断用户是否登录 LoginServlet/doGet

这里是与博客列表是一样的,就不再赘述

处理将博客详情页昵称替换为当前博客作者昵称/是否显示删除博客 UserinfoServlet/doGet

  1. 创建要构造JSON的类
  2. resp.getParameter获取blogId
  3. req.GetSession查询是否有session
  4. session.getAttribute获取session是否有该用户
  5. 数据库中查询此篇博客
  6. 数据中查询用户类是否有此篇博客的作者
  7. 当都有时,判断当前session的用户ID与此篇博客的ID是否相同(相同时,用户类的isyourblog设置1反之设置0)
  8. 响应时,把用户密码设置为0不要名为显示,不修改数据库的数据
  9. resp.setContentType设置响应格式
  10. objectMapper.writeValueAsString构造为JSON格式
  11. 响应
//想要构造json 就要创建这个类
        ObjectMapper objectMapper=new ObjectMapper();

        String blogid=req.getParameter("blogId");

        //直接取查找是否有cookie
        HttpSession session=req.getSession(false);
        if(session==null){
            //后端查询失败时,发送状态码为403 403不会触发回调函数
            resp.setStatus(403);
            resp.setContentType("text/html;charset=utf8");
            resp.getWriter().write("没有该用户");
            return;
        }
        //获取当前登录用户
        User user= (User) session.getAttribute("user");
        if(user==null){
            resp.setStatus(403);
            resp.setContentType("text/html;charset=utf8");
            resp.getWriter().write("没有该用户");
            return;
        }

else{
            //查询这篇博客的作者
            //如果有blogId时,说明是博客详情页发来的请求
            BlogDao blogDao=new BlogDao();
            Blog blog=blogDao.selectOne(Integer.parseInt(blogid));
            if(blog==null){
                resp.setStatus(403);
                resp.setContentType("text/html;charset=utf8");
                resp.getWriter().write("没有该用户");
                return;
            }
            UserDao userDao=new UserDao();
            //用博客类里的用户id 去用户类去查询  查询用户是否有这个博客作者
            User author=userDao.selectById(blog.getUserId());
            if(author==null){
                resp.setStatus(403);
                resp.setContentType("text/html;charset=utf8");
                resp.getWriter().write("没有该用户");
                return;
            }

            if(author.getUserId()== user.getUserId()){
                author.setIsYourBlog(1);
            }else {
                author.setIsYourBlog(0);
            }

            //不用让密码在body中明文显示
            user.setPassword("");
            resp.setContentType("application/json;charset=utf8");
            String jsonString=objectMapper.writeValueAsString(author);
            //返回这篇博客的作者
            resp.getWriter().write(jsonString);
        }

博客编辑页

前端

通过from表单提交标题,内容

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <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-container.css">

    <!-- 引入 editor.md 的依赖 -->
    <link rel="stylesheet" href="editor.md/css/editormd.min.css" />
    <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.js"></script>
</head>
<body>
    <!-- 导航栏 -->
    <div class="nav">
        <!-- logo图片 -->
        <img src="image/logo.jpg" alt="" width="50px">

        <span class="title">我的博客系统</span>
        <span class="spacer"></span>

        <!-- 导航栏 -->
        <a href="blog_list.html">主页</a>
        <a href="blog_edit.html">写博客</a>
        <a href="logout">注销</a><!--        a会直接向对应路径发起get请求-->
    </div>

    <div class="blog-edit-container">
        <form action="blog" method="post" style="height: 100%">
            <!-- 标题编辑区 -->
            <div class="title">
                <input type="text" id="title" placeholder="请输入文章标题" name="title">
                <input type="submit" id="submit" value="发布文章">
            </div>
            <!-- 博客编辑器标签 -->
            <div id="editor">
                <!-- 需要在这里加上一个隐藏的 textarea -->
                <!-- 属于 editor.md 这个库要求的. -->
                <textarea name="content" style="display: none;" ></textarea>
            </div>
        </form>
    </div>

    <script>
        // 初始化编辑器
        var editor = editormd("editor", {
            // 这里的尺寸必须在这里设置. 设置样式会被 editormd 自动覆盖掉.
            width: "100%",
            // 设定编辑器高度
            height: "calc(100% - 50px)",
            // 编辑器中的初始内容
            markdown: "# 在这里写下一篇博客",
            // 指定 editor.md 依赖的插件路径
            path: "editor.md/lib/",
            // 加上这个属性, 效果就是把编辑器里的内容给自动保存到 textarea 里.
            saveHTMLToTextArea: true,
        });
    </script>
</body>
</html>

后端 BlogServlet/doPost

  1. req.setCharacterEncoding设置后端读取的格式
  2. req.getSession判断session是否存在
  3. session.getAttribute判断用户是否在session内
  4. 使用req.getParameter获取标题、内容
  5. 如果标题内容为空或者为空串,则响应400状态码
  6. 创建一个博客类
  7. 将数据写入博客类中
  8. 博客的作者ID就是当前登录用户的ID
  9. 最后将这个类写入数据库(实际就是将类中的数据写入)
  10. 写入后,resp.sendRedirect跳转到博客列表
//提交博客
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf8");
        //判断会话是否存在和会话中的用户是否存在
        HttpSession session=req.getSession(false);
        if (session == null) {
            resp.setStatus(400);
            return;
        }
        User user= (User) session.getAttribute("user");
//        System.out.println(user.getUsername());
//        System.out.println(user.getUserId());
        if(user==null){
            resp.setStatus(400);
            return;
        }

        //2.获取博客的标题和正文
        String title=req.getParameter("title");
        String content=req.getParameter("content");
//        System.out.println(title);
//        System.out.println(content);
        if(title==null||content==null||title.equals("")||content.equals("")){
            resp.setStatus(400);
            resp.setContentType("text/html;charset=utf8");
            resp.getWriter().write("标题或正文不符合");
            return;
        }

        //把数据写入一个对象
        Blog blog=new Blog();
        blog.setTitle(title);
        blog.setContent(content);
        //博客作者的ID就是当前登录用户的ID  所以直接从session拿出当前用户 再拿出当前用户的id
        blog.setUserId(user.getUserId());
        //创建博客写入数据库的对象
        BlogDao blogDao=new BlogDao();
        //把这个博客对象写入数据库
        blogDao.insert(blog);

        //响应
        resp.sendRedirect("blog_list.html");
    }

部署

准备工作

均在Linux系统下

下载jdk

yum install java-1.8.0-openjdk-devel.x86_64

下载tomcat

把window下的tomcat8.0拖拽到linux上

解压 

unzip apache-tomcat-8.5.100.zip

加权限

cd到tomcat的bin目录下

给所有.sh加上权限

chmod +x *.sh

./即可启动

startup.sh是linux启动脚本

startup.bat是window启动脚本

但是大概率启动不了,因为tomcat8080端口,服务器是默认不开放的,所有要进入你的服务器控制台开放端口

安装mysql

之后把db.sql里的sql语句复制到数据库内,重新建库建表

使用maven打包

记得改包格式和包名

把打好的包从window拖拽到Linux的Tomcat的webappsxia

访问

你服务器的地址:端口:包名:你也访问的页面

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1612047.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C语言中的控制语句(循环语句while、for)

循环语句 什么是循环 重复执行代码 为什么需要循环循环的实现方式 whiledo...whilefor while语句 语法格式&#xff1a; while (条件) {循环体…… } 需求&#xff1a;跑步5圈 示例代码&#xff1a; #include <stdio.h>int main() {// 需求跑步5圈// 1. 条件变量的…

C语言 逻辑运算符

本文 我们来说 逻辑运算符 有时做出决策需要测试多个条件&#xff0c;C语言提供了用于将简单条件组合成复杂条件的逻辑运算符。 逻辑运算符 如下图 用逻辑运算符连接操作数组成的表达式称为逻辑表达式。 逻辑运算的结果只有0和1 逻辑运算的对象可以是任意数值型&#xff0c;但…

Axure RP 9中文激活版:专业原型设计工具mac/win

Axure RP 9是一款由美国Axure Software Solution公司开发的专业原型设计工具。它凭借强大的交互功能和丰富的设计素材&#xff0c;为产品经理、UI设计师、交互设计师等用户提供了高效、便捷的原型设计体验。 Axure RP 9支持快速创建线框图、流程图、原型和规格说明文档&#xf…

过零可控硅光耦与随机可控硅光耦

无过零检测 推荐型号 MOC3021无过零检测 对应的数据手册 原理框图 工作电流 过零检测 推荐型号 MOC3061 原理框图 工作电流 注意事项 随机导通型是随时打开的。都是过零时关闭 也即是说&#xff1a;过零型打开的都是一个馒头波。 参考链接 过零可控硅光耦怎么用-电路知识干…

大屏-flex布局

<div class"container"><div class"title">标题</div><div class"content"><div class"item"></div><div class"item" style"width: calc((100% - 30) / 3 * 2)"><…

Vue报错 Cannot read properties of undefined (reading ‘websiteDomains‘) 解决办法

浏览器控制台如下报错&#xff1a; Unchecked runtime.lastError: The message port closed before a response was received. Uncaught (in promise) TypeError: Cannot read properties of undefined (reading websiteDomains) at xl-content.js:1:100558 此问题困扰了…

Fannel和Calico

一 1、路由器下面每一个端口都是一个vlan,隔离了广播包 192.168.1.0和192.168.2.0他们属于不同的vlan,没有三层交换机或者路由器,他们通不了信 不在同一个vlan,也就是子网,包就会走向网关(也就是路由器那里,路由器有路由表。查看目的地192.168.2.0在b口,从b口出去vlan…

深度学习--CNN卷积神经网络(附图)

框架 让我们先看一下CNN的框架 卷积层中后是ReLu激活函数 &#xff0c;然后是深化池&#xff0c;之后是全连接&#xff0c;最后进行Softmax进行归一化。 所以&#xff0c;我们先逐一了解一下它们各个部分 全连接层 全连接层也称感知机&#xff0c;BP神经网络 全连接层&…

20240330-2-XGBoost面试题

XGBoost面试题 1. RF和GBDT的区别 相同点&#xff1a; 都是由多棵树组成&#xff0c;最终的结果都是由多棵树一起决定。 不同点&#xff1a; 集成学习&#xff1a; R F RF RF属于 B a g g i n g Bagging Bagging思想&#xff0c;而 G B D T GBDT GBDT是 B o o s t i n g Bo…

节点加密技术:保障数据传输安全的新利器

随着信息技术的快速发展&#xff0c;网络数据的安全传输问题日益凸显。节点加密技术作为一种新兴的加密手段&#xff0c;正逐渐成为保障数据传输安全的重要工具。本文将探讨节点加密技术的原理、应用及其优势&#xff0c;并分析其未来的发展趋势。 节点加密技术的原理 节点加密…

EI级 | Matlab实现VMD-TCN-LSTM-MATT变分模态分解卷积长短期记忆神经网络多头注意力多变量时间序列预测

EI级 | Matlab实现VMD-TCN-LSTM-MATT变分模态分解卷积长短期记忆神经网络多头注意力多变量时间序列预测 目录 EI级 | Matlab实现VMD-TCN-LSTM-MATT变分模态分解卷积长短期记忆神经网络多头注意力多变量时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.Matl…

(助力国赛)美赛O奖数学建模可视化!!!含代码2(箱型图、旭日图、直方图、三元图、平行坐标图、密度图、局部放大图)

众所周知&#xff0c;数学建模的过程中&#xff0c;将复杂的数据和模型结果通过可视化图形呈现出来&#xff0c;不仅能够帮助我们更深入地理解问题&#xff0c;还能够有效地向评委展示我们的研究成果。   今天&#xff0c;承接《可视化代码1》&#xff0c;作者将与大家分享《…

@reduxjs/toolkit进阶指南

虽然reduxjs/toolkit为Redux提供了开箱即用的最佳实践,但它也内置了一些强大的功能,可以极大简化Redux在复杂场景下的使用。本文将重点介绍以下进阶特性: 1.使用Immer简化不可变更新 Redux要求状态更新必须是不可变的,这意味着我们需要手动复制和更新数据,这种模式很容易出错…

Ubuntu 微调训练ChatGLM3大语言模型

Ubuntu 微调训练ChatGLM3大语言模型 LLaMA Factory 的 LoRA 微调提供了 3.7 倍的加速比&#xff0c;同时在广告文案生成任务上取得了更高的 Rouge 分数。结合 4 比特量化技术&#xff0c;LLaMA Factory 的 QLoRA 微调进一步降低了 GPU 显存消耗。 https://github.com/hiyouga…

天星金融(原小米金融)履行社会责任,提高社保政策知晓度

二十大报告指出“为民造福是立党为公、执政为民的本质要求“&#xff0c;人民幸福安康是推动高质量发展的最终目的。社会保障作为维护社会公平、增进人民福祉的基本制度&#xff0c;既是“安全网”也是“稳定器”&#xff0c;发挥着改善民生的重要作用。为进一步提升人民群众对…

接雨水 , 给定二维图,能容多少水

42. 接雨水 - 力扣&#xff08;LeetCode&#xff09; 看着就是非常常规的题目&#xff0c;所以非常有必要掌握。 最少也把O&#xff08;n^2&#xff09;的方法写出来吧。力扣官方题解的三种方法O&#xff08;n&#xff09;都挺好&#xff0c;不过可能有点难读&#xff0c;在此…

淘宝购物更智能:taobao.item_search API接口实现关键字精准匹配

随着电子商务的飞速发展&#xff0c;淘宝作为中国最大的网络购物平台之一&#xff0c;为亿万消费者提供了便捷、丰富的购物体验。然而&#xff0c;在海量商品中快速找到符合自己需求的商品&#xff0c;一直是消费者面临的挑战。为了提升购物体验&#xff0c;淘宝开放平台提供了…

渐进式交付实践:通过 Argo Rollouts 和 FSM Gateway 实现金丝雀发布

渐进式交付&#xff08;Progressive delivery&#xff09;是一种软件发布策略&#xff0c;旨在更安全、更可控地将新版本软件逐步推出给用户。它是持续交付的进一步提升&#xff0c;允许开发团队在发布新版本时拥有更细粒度的控制&#xff0c;例如可以根据用户反馈、性能指标和…

树莓派3B长时间不操作屏幕息屏无信号处理

树莓派外接显示器&#xff0c;需长时间展示某个网页&#xff0c;经过一段时间&#xff0c;显示器屏幕会黑掉显示无信号。 需修改 /etc/lightdm/lightdm.conf 配置文件中新增如下两行并重启。 xserver-commandX -s 0 dpms sleep-inactive-timeout0

系统架构设计精华知识

数据流风格&#xff1a;适合于分阶段做数据处理&#xff0c;交互性差&#xff0c;包括&#xff1a;批处理序列、管理过滤器。调用/返回风格&#xff1a;一般系统都要用到&#xff0c;包括&#xff1a;主程序/子程序&#xff0c;面向对象&#xff0c;层次结构&#xff08;分层越…