基于Servlet实现博客系统--- 前后端分离

news2024/11/25 18:57:07

目录 

一.博客系统概述

1.软件的生命周期

2.学习目标

二.数据库的建立

2.插入数据

三.创建项目

1.建立maven项目

2.导入相关的依赖

3.编写工具类

1.编写数据库相关的工具类

2.编写字符串的工具类 

3.编写用户的工具类

4.创建实体类

1.创建user实体类

2.创建blog实体类

5.创建dao层(与数据库交互)

1.UserDao

1.实现登录功能

2.BlogDao

5.4测试DAO层

1.TestUserDao

2.TestBlogDao

5.5编写Common层

1.AppResult

2.AppConfig

6.创建servlet层

1.LoginServlet

2.UserServlet

3.BlogServlet

4.LogoutServlet 

7.测试登录功能

1.测试登录接口

1.配置tomcat

2.使用postman测试登录接口

1.用户名为空校验

2.用户名不存在校验

3.密码错误校验

4.正确登录校验

​编辑

2.测试用户接口

1.未登录状态

2.登录状态

3.测试博客接口

4.发布博客测试

8.导入前端页面

1.登录页面前端JS代码的实现

2.博客展示页面前端JS代码的实现

3.查看博客详细内容的js代码

4.编写发布博客的js代码


代码获取:基于Servlet实现博客系统--- 前后端分离: 基于Servlet实现博客系统--- 前后端分离

一.博客系统概述

1.软件的生命周期

  1. 可行性研究
  2. 需求分析—需求文档
  3. 概要设计
  4. 详细设计
  5. 开发
  6. 集成测试
  7. 验收测试
  8. 上线运行
  9. 维护
  10. 退役
     

2.学习目标

  1. 熟悉前端怎么发送数据
  2. 后端怎么接收数据
  3. 熟悉前后端交互过程中参数的解析方式(前后端要约定好)
  4. 后端接收到参数之后要做哪些校验
  5. 数据库如何操作
  6. 后端返回什么样的结果给前端
  7. 前端拿到服务器的响应之后做什么样的处理
     

二.数据库的建立

1.创建数据库和表

#设置数据库的编码集和排序忽略大小写   
create database blog_db character set utf8mb4 collate utf8mb4_general_ci;
#建立user表
create table user(
            id bigint primary key auto_increment comment '用户id,自增',
            username varchar(50) unique not null comment '用户名',
    password varchar(50) not null comment '密码'

            );
#建立blog表
create table blog(
            id bigint primary key auto_increment comment '博客id,自增',
            title varchar(1024) not null comment '标题',
    cotent text not null comment '内容',
    createtime datetime not null comment '发布时间',
    userid bigint comment '用户id',
    foreign key (userid) references user(id)
            );

 insert into blog values(null,'我的铅笔','“铅笔,铅笔,5角一支呀!”,“橡皮5折啦,1元一块!”,还没进班,我就听到了这样的吆喝声,小学作文。
                            进了教室,只见桌椅摆成了柜台的形状,桌子上摆着各种各样的商品,琳琅满目。只见同学们有的在选购自己喜爱的商品,有的在边走边推销,说着:“只要是 想买,我可以给你打七折”,还有的坐在位子上吆喝着:“走过路过,不要错过,”“不看不知道,一看忘不掉!”看见这些情景,我也从书包中拿出我要卖的东 西。我卖的是一个神奇的魔术橡皮盒,它是天蓝色的,正面写着baby bear
                                    魔术橡皮盒。为什么叫魔术橡皮盒呢?原来它可以变魔术,你把抽屉拉开时里面什么也没有,而当你把左侧一个开关推开,再打开抽屉时,里面便会出现一块精 致的小橡皮。这时周 走过来说:“赵越伟,我用这个小火车,小老鼠玩具和这个夹心饼换你的魔术橡皮盒可以吗?”我看了看他的小火车,很好玩,而且我们又是好朋友,于是便和他换 了。程博威这时也在吆喝:“可爱的小狗玩具呀!快来买呀!快来买呀!”我走过去跟他说:“我用这个小火车和你换行吗?”他说:“不行,这个别人已经有人定 购了。”这样的交易活动持续了很久,大家都很开心。
                                    虽然我没有真正当过商人,可我已经感受到:“当商人真的不容易呀!只有想方设法吸引顾客,才能把自己的商品推销出去。”
                                    ',now(),1);

INSERT INTO blog VALUES(NULL,'测试1','测试内容',NOW(),2)

2.插入数据

#插入数据
        insert into user values(null,'张三','123456'),(null,'李四','123456');

 

三.创建项目

1.建立maven项目

2.导入相关的依赖

    <dependencies>
<!--        servlet依赖-->
        <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.47</version>
        </dependency>

<!--        json依赖-->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.15.2</version>
        </dependency>

    </dependencies>

3.编写工具类

1.编写数据库相关的工具类

采用单例模式创建数据库的工具类

package com.javastudy.utils;


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;

/**
 * @author Chooker
 * @create 2023-07-04 20:00
 */
public class DButils {
    private static DataSource dataSource;

    private static final String URL = "jdbc:mysql://localhost:13306/blog_db?characterEncoding=utf8&useSSL=false";

    private static final String USER = "root";

    private static final String PASSWORD = "woaini520";

    //单例模式
    private DButils() {

    }

    static {
        MysqlDataSource mysqlDataSource = new MysqlDataSource();
        mysqlDataSource.setURL(URL);
        mysqlDataSource.setUser(USER);
        mysqlDataSource.setPassword(PASSWORD);
        dataSource = mysqlDataSource;
    }

    public static Connection getConnection() throws SQLException {
        return dataSource.getConnection();
    }

    public static void close(ResultSet set, PreparedStatement statement, Connection connection) {
        if (set != null) {
            try {
                set.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);
            }
        }
    }

}

2.编写字符串的工具类 

package com.javastudy.utils;

/**
 * @author Chooker
 * @create 2023-07-04 20:35
 */
public class Stringutils {
    /**
     * 校验字符串是否为空
     * @param value
     * @return
     */
    public static boolean isEmpty(String value) {
        if (value == null || "".equals(value)) {
            return true;
        }
        return false;
    }
}

3.编写用户的工具类

package com.javastudy.utils;

import com.javastudy.common.AppConfig;
import com.javastudy.entities.User;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

/**
 * @author Chooker
 * @create 2023-07-06 21:29
 */
public class UserUtils {

    public static User checkUserLoginStatus(HttpServletRequest req) {
        //判断req对象是否为空
        if (req == null) {
            return null;
        }
        HttpSession session = req.getSession(false);
        if (session == null) {
            return null;
        }
        User user = (User) session.getAttribute(AppConfig.USER_SESSION_KEY);

        return user;

    }
}

4.创建实体类

1.创建user实体类

生成相对应的get和set方法和toString()方法(当然也可以使用lombok注解)

package com.javastudy.entities;

import com.fasterxml.jackson.annotation.JsonIgnore;

/**
 * @author Chooker
 * @create 2023-07-04 20:15
 */
public class User {
    private Long id;

    private String username;

    @JsonIgnore  //不参与json序列化
    private String password;

    private boolean isAuthor;

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", isAuthor=" + isAuthor +
                '}';
    }

    public Long getId() {
        return id;
    }

    public void setId(Long 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 boolean isAuthor() {
        return isAuthor;
    }

    public void setAuthor(boolean author) {
        isAuthor = author;
    }

    public User() {
    }

    public User(Long id, String username, String password) {
        this.id = id;
        this.username = username;
        this.password = password;
    }
}

注意:最好在password上面加上JsonIgnore注解,这样在进行json序列化的时候,不会序列化password序列.加之前和之后的区别:可以看到密码没有进行json序列化

 

2.创建blog实体类

package com.javastudy.entities;

import java.sql.Timestamp;

/**
 * @author Chooker
 * @create 2023-07-04 20:17
 */
public class Blog {
    private Long id;

    private String title;

    private String content;

    private Timestamp createTime;

    private Long userId;

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

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    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 Timestamp getCreateTime() {
        return createTime;
    }

    public void setCreateTime(Timestamp createTime) {
        this.createTime = createTime;
    }

    public Long getUserId() {
        return userId;
    }

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

    public Blog(Long id, String title, String content, Timestamp createTime, Long userId) {
        this.id = id;
        this.title = title;
        this.content = content;
        this.createTime = createTime;
        this.userId = userId;
    }

    public Blog() {
    }
}

5.创建dao层(与数据库交互)

1.UserDao

1.实现登录功能

package com.javastudy.dao;

import com.javastudy.entities.User;
import com.javastudy.utils.DBUtils;
import com.javastudy.utils.StringUtils;

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

/**
 * @author Chooker
 * @create 2023-07-04 20:33
 */
public class UserDao {
    /**
     * 根据用户名查询用户信息
     *
     * @param username
     * @return
     */
    public User selectByUsername(String username) {
        //非空校验
        if (StringUtils.isEmpty(username)) {
            return null;
        }
        //进行数据库的查询操作
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;

        try {
            //1.获取数据库的连接
            connection = DBUtils.getConnection();
            //2.定义sql语句
            String sql = "select * from user where username=?";
            //3.对sql语句进行预处理
            preparedStatement = connection.prepareStatement(sql);
            //4.设置占位符的值
            preparedStatement.setString(1, username);
            //5.执行sql并获取结果
            resultSet = preparedStatement.executeQuery();
            //6.构建查询出来的user对象
            if (resultSet.next()) {
                User user = new User();
                user.setId(resultSet.getLong(1));
                user.setUsername(resultSet.getString(2));
                user.setPassword(resultSet.getString(3));
                return user;
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            DBUtils.close(resultSet, preparedStatement, connection);
        }
        return null;

    }

    /**
     * 根据用户id查询用户信息
     *
     * @param id
     * @return
     */
    public User selectById(Long id) {
        if (id == null || id < 0) {
            return null;
        }
        //进行数据库的查询操作
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        try {
            connection = DBUtils.getConnection();
            String sql = "select id,username,password from user where id=?";
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setLong(1, id);

            resultSet = preparedStatement.executeQuery();

            if (resultSet.next()) {
                User user = new User();
                user.setId(resultSet.getLong(1));
                user.setUsername(resultSet.getString(2));
                user.setPassword(resultSet.getString(3));
                return user;
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            DBUtils.close(resultSet, preparedStatement, connection);
        }
        return null;

    }
}

2.BlogDao

package com.javastudy.dao;

import com.javastudy.entities.Blog;
import com.javastudy.utils.DBUtils;
import com.javastudy.utils.StringUtils;

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

/**
 * @author Chooker
 * @create 2023-07-04 20:33
 */
public class BlogDao {
    /**
     * 查询所有的博客信息
     *
     * @return
     */
    public List<Blog> selectAll() {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        try {
            connection = DBUtils.getConnection();
            String sql = "select id,title,content,createTime,userId from blog order by createTime desc";
            preparedStatement = connection.prepareStatement(sql);

            List<Blog> list = null;

            resultSet = preparedStatement.executeQuery();
            while (resultSet.next()) {
                if (list == null) {
                    list = new ArrayList<>();
                }
                Blog blog = new Blog();
                blog.setId(resultSet.getLong(1));
                blog.setTitle(resultSet.getString(2));
                blog.setContent(resultSet.getString(3));
                blog.setCreateTime(resultSet.getTimestamp(4));
                blog.setUserId(resultSet.getLong(5));
                list.add(blog);
            }
            return list;

        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            DBUtils.close(resultSet, preparedStatement, connection);
        }
    }

    /**
     * 根据博客id查询博客信息
     *
     * @param id
     * @return
     */
    public Blog selectById(Long id) {
        if (id == null || id < 0) {
            return null;
        }
        //进行数据库的查询操作
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        try {
            connection = DBUtils.getConnection();
            String sql = "select id,title,content,createTime,userId from blog where id=?";
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setLong(1, id);

            resultSet = preparedStatement.executeQuery();

            if (resultSet.next()) {
                Blog blog = new Blog();
                blog.setId(resultSet.getLong(1));
                blog.setTitle(resultSet.getString(2));
                blog.setContent(resultSet.getString(3));
                blog.setCreateTime(resultSet.getTimestamp(4));
                blog.setUserId(resultSet.getLong(5));
                return blog;
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            DBUtils.close(resultSet, preparedStatement, connection);
        }
        return null;


    }

    /**
     * 发布一篇博客
     *
     * @param blog
     * @return 发布了多少条博客
     */
    public int insert(Blog blog) {
        if (blog == null || StringUtils.isEmpty(blog.getTitle()) || StringUtils.isEmpty(blog.getContent())
                || blog.getUserId() == null) {
            return 0;
        }
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        try {
            connection = DBUtils.getConnection();

            String sql = "insert into blog values(null,?,?,?,?)";

            //预处理sql

            preparedStatement = connection.prepareStatement(sql);

            preparedStatement.setString(1, blog.getTitle());
            preparedStatement.setString(2, blog.getContent());
            preparedStatement.setTimestamp(3, blog.getCreateTime());
            preparedStatement.setLong(4, blog.getUserId());

            return preparedStatement.executeUpdate();

        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            DBUtils.close(null, preparedStatement, connection);
        }

    }

}

5.4测试DAO层

1.TestUserDao

import com.javastudy.dao.UserDao;
import com.javastudy.entities.User;
import org.junit.Test;

/**
 * @author Chooker
 * @create 2023-07-06 21:12
 */
public class TestUser {
    @Test
    public void test01(){
        UserDao userDao=new UserDao();
        User user = userDao.selectByUsername("张三");
        System.out.println(user);
    }
}

2.TestBlogDao

import com.javastudy.dao.BlogDao;
import com.javastudy.entities.Blog;
import org.junit.Test;

import java.util.List;

/**
 * @author Chooker
 * @create 2023-07-06 21:05
 */
public class TestBlog {

    @Test
    public void test01(){
        BlogDao blogDao = new BlogDao();
        List<Blog> blogs = blogDao.selectAll();
        System.out.println(blogs);
    }
}

5.5编写Common层

1.AppResult

package com.javastudy.common;

/**
 * @author Chooker
 * @create 2023-07-05 11:24
 */
public class AppResult<T> {
    //状态码
    private Integer code;
    //描述信息
    private String message;
    //相关数据
    private T data;

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    public AppResult(Integer code, String message, T data) {
        this.code = code;
        this.message = message;
        this.data = data;
    }

    public static <T> AppResult success(T data) {
        return new AppResult(0, "操作成功", data);
    }

    public static <T> AppResult success(String message) {
        return new AppResult(0, message, null);
    }

    public static <T> AppResult success() {
        return new AppResult(0, "操作成功", null);
    }

    public static <T> AppResult fail(String message) {
        return new AppResult(-1, message, null);
    }

    public static <T> AppResult fail() {
        return new AppResult(-1, "操作失败", null);
    }


}

2.AppConfig

package com.javastudy.common;

/**
 * @author Chooker
 * @create 2023-07-05 17:37
 */
public class AppConfig {
    public static final String USER_SESSION_KEY="USERSESSIONKEY";
}

6.创建servlet层

1.LoginServlet

package com.javastudy.servlet;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.javastudy.common.AppConfig;
import com.javastudy.common.AppResult;
import com.javastudy.dao.UserDao;
import com.javastudy.entities.User;
import com.javastudy.utils.Stringutils;

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;

/**
 * @author Chooker
 * @create 2023-07-04 21:00
 */
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    ObjectMapper objectMapper = new ObjectMapper();

    UserDao userDao = new UserDao();

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //设置编码集
        req.setCharacterEncoding("utf-8");
        resp.setContentType("application/json;charset=utf-8");
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        if (Stringutils.isEmpty(username) || Stringutils.isEmpty(password)) {
            AppResult appResult = AppResult.fail("用户名或者密码为空");
            resp.getWriter().write(objectMapper.writeValueAsString(appResult));
            return;
        }
        User user = userDao.selectByUsername(username);
        if (user == null) {
            AppResult appResult = AppResult.fail("用户名不存在");

            resp.getWriter().write(objectMapper.writeValueAsString(appResult));
            return;
        }
        //验证密码是否错误
        if (!user.getPassword().equals(password)) {
            AppResult appResult = AppResult.fail("密码错误");

            resp.getWriter().write(objectMapper.writeValueAsString(appResult));
            return;
        }
        //登录成功  保存用户信息到session中
        HttpSession session = req.getSession(true);
        AppResult appResult = AppResult.success("登录成功");

        //使用全局定义的sessionKey
        session.setAttribute(AppConfig.USER_SESSION_KEY, user);

        resp.getWriter().write(objectMapper.writeValueAsString(appResult));


    }
}

2.UserServlet

package com.javastudy.servlet;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.javastudy.common.AppConfig;
import com.javastudy.common.AppResult;
import com.javastudy.dao.BlogDao;
import com.javastudy.dao.UserDao;
import com.javastudy.entities.Blog;
import com.javastudy.entities.User;
import com.javastudy.utils.StringUtils;
import com.javastudy.utils.UserUtils;

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;

/**
 * @author Chooker
 * @create 2023-07-06 15:05
 */
@WebServlet("/user")
public class UserServlet extends HttpServlet {
    private ObjectMapper objectMapper = new ObjectMapper();

    private UserDao userDao = new UserDao();
    private BlogDao blogDao = new BlogDao();


    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        resp.setContentType("application/json;charset=utf-8");

        HttpSession session = req.getSession(false);
        //判断session
        if (UserUtils.checkUserLoginStatus(req) == null) {
            //设置状态码 403  表示用户没有权限
            resp.setStatus(403);
            //错误描述
            AppResult appResult = AppResult.fail("用户没有登录,请登录后再试");
            //代表用户没有登录
            resp.getWriter().write(objectMapper.writeValueAsString(appResult));
            return;

        }
        String blogId = req.getParameter("blogId");
        String jsonStr = null;
        if (StringUtils.isEmpty(blogId)) {
            User user = (User) session.getAttribute(AppConfig.USER_SESSION_KEY);
            jsonStr = objectMapper.writeValueAsString(AppResult.success(user));

        } else {
            Blog blog = blogDao.selectById(Long.valueOf(blogId));
            if (blog == null) {
                resp.getWriter().write(objectMapper.writeValueAsString(AppResult.fail("没有找到对应的博客")));
                return;
            }

            User user = userDao.selectById(blog.getUserId());

            jsonStr = objectMapper.writeValueAsString(AppResult.success(user));

        }
        //返回json
        resp.getWriter().write(jsonStr);

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doPost(req, resp);
    }
}

3.BlogServlet

package com.javastudy.servlet;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.javastudy.common.AppResult;
import com.javastudy.dao.BlogDao;
import com.javastudy.entities.Blog;
import com.javastudy.entities.User;
import com.javastudy.utils.StringUtils;
import com.javastudy.utils.UserUtils;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * @author Chooker
 * @create 2023-07-06 21:16
 */
@WebServlet("/blog")
public class BlogServlet extends HttpServlet {

    BlogDao blogDao = new BlogDao();

    ObjectMapper objectMapper = new ObjectMapper();


    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        resp.setContentType("application/json;charset=utf-8");

        //校验用户登录状态
        HttpSession session = req.getSession(false);
        //判断session
        if (UserUtils.checkUserLoginStatus(req) == null) {
            //设置状态码 403  表示用户没有权限
            resp.setStatus(403);
            //错误描述
            AppResult appResult = AppResult.fail("用户没有登录,请登录后再试");
            //代表用户没有登录
            resp.getWriter().write(objectMapper.writeValueAsString(appResult));
            return;

        }
        String blogId = req.getParameter("blogId");
        String jsonStr = null;
        if (StringUtils.isEmpty(blogId)) {
            List<Blog> blogs = blogDao.selectAll();
            //非空的校验
            if (blogs == null) {
                blogs = new ArrayList<>();
            }
            jsonStr = objectMapper.writeValueAsString(AppResult.success(blogs));

        } else {

            Blog blog = blogDao.selectById(Long.valueOf(blogId));
            if (blog == null) {
                resp.getWriter().write(objectMapper.writeValueAsString(AppResult.fail("没有找到对应的博客")));
                return;
            }

            jsonStr = objectMapper.writeValueAsString(AppResult.success(blog));
        }


        resp.getWriter().write(jsonStr);

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        resp.setContentType("application/json;charset=utf-8");

        //校验用户登录状态
        HttpSession session = req.getSession(false);
        User user = UserUtils.checkUserLoginStatus(req);
        //判断session
        if (user == null) {
            //设置状态码 403  表示用户没有权限
            resp.setStatus(403);
            //错误描述
            AppResult appResult = AppResult.fail("用户没有登录,请登录后再试");
            //代表用户没有登录
            resp.getWriter().write(objectMapper.writeValueAsString(appResult));
            return;

        }

        String title = req.getParameter("title");
        String content = req.getParameter("content");

        if (StringUtils.isEmpty(title) || StringUtils.isEmpty(content)) {
            AppResult appResult = AppResult.fail("文章的标题或者内容为空");
            //代表用户没有登录
            resp.getWriter().write(objectMapper.writeValueAsString(appResult));
            return;
        }
        Blog blog = new Blog();
        blog.setTitle(title);
        blog.setContent(content);
        blog.setCreateTime(Timestamp.valueOf(LocalDateTime.now()));
        blog.setUserId(user.getId());

        int insert = blogDao.insert(blog);
        if (insert <= 0) {
            AppResult appResult = AppResult.fail("文章发布失败,请重新发布");
            //代表用户没有登录
            resp.getWriter().write(objectMapper.writeValueAsString(appResult));
            return;
        }

        resp.getWriter().write(objectMapper.writeValueAsString(AppResult.success("发布成功")));

    }

    @Override
    protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        resp.setContentType("application/json;charset=utf-8");

        //校验用户登录状态
        HttpSession session = req.getSession(false);
        User user = UserUtils.checkUserLoginStatus(req);
        //判断session
        if (user == null) {
            //设置状态码 403  表示用户没有权限
            resp.setStatus(403);
            //错误描述
            AppResult appResult = AppResult.fail("用户没有登录,请登录后再试");
            //代表用户没有登录
            resp.getWriter().write(objectMapper.writeValueAsString(appResult));
            return;

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

        Blog blog = blogDao.selectById(Long.valueOf(blogId));
        if (blog == null) {
            resp.getWriter().write(objectMapper.writeValueAsString(AppResult.fail("不存在这个博客")));
            return;
        }

        if (blog.getUserId() != user.getId()) {
            resp.getWriter().write(objectMapper.writeValueAsString(AppResult.fail("无权删除别人的博客")));
            return;
        }

        if (StringUtils.isEmpty(blogId)) {
            resp.getWriter().write(objectMapper.writeValueAsString(AppResult.fail("参数校验失败")));
            return;
        }

        //调用DAO进行删除操作

        int row = blogDao.deleteById(Long.valueOf(blogId));
        if (row != 1) {
            resp.getWriter().write(objectMapper.writeValueAsString(AppResult.fail("删除失败")));
            return;
        }

        resp.getWriter().write(objectMapper.writeValueAsString(AppResult.success("删除成功")));


    }
}

4.LogoutServlet 

package com.javastudy.servlet;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.javastudy.common.AppResult;
import com.javastudy.utils.UserUtils;

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;

/**
 * @author Chooker
 * @create 2023-07-10 12:34
 */
@WebServlet("/logout")
public class LogoutServlet extends HttpServlet {
    ObjectMapper objectMapper = new ObjectMapper();

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        resp.setContentType("application/json;charset=utf-8");

        HttpSession session = req.getSession(false);

        //判断session
        if (UserUtils.checkUserLoginStatus(req) == null) {
            //设置状态码 403  表示用户没有权限
            resp.setStatus(403);
            //错误描述
            AppResult appResult = AppResult.fail("用户没有登录,请登录后再试");
            //代表用户没有登录
            resp.getWriter().write(objectMapper.writeValueAsString(appResult));
            return;

        }
        if (session != null) {
            session.invalidate();
        }
        resp.getWriter().write(objectMapper.writeValueAsString(AppResult.success("注销成功")));
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doPost(req, resp);
    }
}

7.测试登录功能

1.测试登录接口

1.配置tomcat

2.使用postman测试登录接口

1.用户名为空校验

符合代码的预期

2.用户名不存在校验

符合预期

3.密码错误校验

 符合预期

4.正确登录校验

符合预期

2.测试用户接口

1.未登录状态

2.登录状态

3.测试博客接口

4.发布博客测试

 

发布博客成功.

8.导入前端页面

关于前段的html,css等信息可以到这个链接进行下载:

链接:https://pan.baidu.com/s/1BlLCsAzpN0szCsSEJYyF8Q?pwd=kvfu
提取码:kvfu

1.登录页面前端JS代码的实现

首先我们需要引入js的依赖

<script src="./js/jquery-3.6.3.min.js"></script>

<script>
    //页面加载完成之后执行
    jQuery(function () {


        //为登录按钮绑定时间
        jQuery("#btn_login_submit").click(function () {

            //获取用户名
            var username = jQuery("#username");
            if (!username.val()) {
                alert("用户名不能为空");
                username.focus();
                return;
            }

            //获取密码
            var password = jQuery("#password");
            if (!password.val()) {
                alert("密码不能为空");
                password.focus();
                return;
            }

            //构造发送的数据
            var postData = {
                username: username.val(),
                password: password.val()
            };

            jQuery.ajax({
                type: 'get',
                url: 'login',
                contentType: 'application/x-www-form-urlencoded',
                data: postData,
                //表示正常发送 http200
                success: function (respData) {
                    if (respData.code == 200) {
                        //登陆成功,跳转到blog_list.html
                        location.assign('blog_list.html');

                    } else {
                        //登陆失败
                        alert(respData.message);
                    }
                },
                //http不是200
                error: function () {
                    console.log("访问出现问题");
                }

            });

        })


    })

</script>

注意点:记得将表单的属性全部去掉,可以仅仅当这是一个标签,不需要表单的提交,这样会整个页面刷新,我们使用的是AJAX的局部提交技术,可以将form标签改为div标签也可以

 其次就是我们需要将按钮的属性从submit改为button,如果不修改的话,当我们点击按钮的时候自动提交给本页面,刷新本页面,之前填的信息都没有了,一次仅仅是一个button即可,之后通过绑定click事件进行相关的操作.

2.博客展示页面前端JS代码的实现

<script src="./js/jquery-3.6.3.min.js"></script>
<script src="./js/common.js"></script>

<script>
    //页面加载完成之后执行
    jQuery(function () {
        //直接发送ajax请求,获取姓名
        jQuery.ajax({
            type: 'get',
            url: 'user',
            success: function (respData) {
                if (respData.code == 0) {
                    //成功
                    var user = respData.data;
                    jQuery("#h_list_username").html(user.username);

                } else {
                    //失败
                }

            },
            error: function () {
                console.log("访问出现问题");

            },
            statusCode: {
                //可以为不同的HTTP状态码定义不同的方法
                403: function () {
                    //打印日志并跳转到登录页面
                    console.log("用户无权访问");
                    location.assign('blog_login.html');

                }

            }
        });
        jQuery.ajax({
            type: 'get',
            url: 'blog',
            //回调函数
            success: function (respData) {
                if (respData.code == 0) {
                    //构建文章列表
                    bulidArticleList(respData.data);

                } else {

                }

            },
            error: function () {
                //打印日志
                console.log("访问出现错误");
            },
            statusCode: {
                403: function () {
                    //登陆失败
                    location.assign('blog_login.html');

                }
            }

        });
        jQuery("#a_list_logout").click(function () {
            //发送请求
            jQuery.ajax({
                type: 'get',
                url: 'logout',
                //回调函数
                success: function (respData) {
                    if (respData.code == 0) {
                        location.assign("blog_login.html");


                    } else {
                        alert(respData.message);

                    }

                },
                error: function () {
                    //打印日志
                    console.log("访问出现错误");
                },
                statusCode: {
                    403: function () {
                        //登陆失败
                        location.assign('blog_login.html');

                    }
                }
            });
        });



    })
    function bulidArticleList(data) {
        //如果data为空
        if (!data || data.length == 0) {
            var htmlString = "<h3>没有文章,懒狗快发布一篇</h3>";
            jQuery(".container-right").html(htmlString);
            return;

        }
        // for(var i=0;i<data.length;++i){
        //     var blog=data[i];
        // }
        data.forEach(element => {
            var htmlStr = ' <div class="blog-content"> '
                + ' <div class="blog-title"> '
                + element.title
                + ' </div> '
                + ' <div class="blog-datetime"> '
                + formatDate(element.createTime)
                + ' </div> '
                + ' <div class="content"> '
                + element.content
                + ' </div> '
                + ' <div class="aEl"> '
                + ' <a href="./blog_details.html?blogId=' + element.id + '">查看全文 &gt;&gt; </a> '
                + ' </div> '
                + ' <hr> '
                + ' </div> ';
            //追加到
            jQuery(".container-right").append(htmlStr);
        });

    }


</script>

3.查看博客详细内容的js代码

<script src="./js/common.js"></script>
<script src="./js/jquery-3.6.3.min.js"></script>

<!-- 再引入编辑器插件 -->
<script src="./editor.md/editormd.min.js"></script>
<script src="./editor.md/lib/marked.min.js"></script>
<script src="./editor.md/lib/prettify.min.js"></script>

<script>
    jQuery(function () {
        //发送ajax请求,获取当前博客的详细信息

        jQuery.ajax({
            type: 'get',
            url: 'blog' + location.search,
            success: function (respData) {
                if (respData.code == 0) {
                    var blog = respData.data;
                    //为页面中的相应标签进行赋值
                    jQuery("#div_details_title").html(blog.title);
                    jQuery("#div_details_datatime").html(formatDate(blog.createTime));
                    // jQuery('#div_detals_content').html(blog.content);
                    // 内容
                    editormd.markdownToHTML('div_details_content', { markdown: blog.content });

                } else {
                    alert(respData.message);
                }

            },
            error: function () {
                console.log("访问出现错误");
            },
            statusCode: {
                403: function () {
                    location.assign('blog_login.html');

                }
            }
        });

        //获取作者详情
        jQuery.ajax({
            type: 'get',
            url: 'user' + location.search,
            success: function (respData) {
                if (respData.code == 0) {
                    var user = respData.data;
                    //设置作者名
                    jQuery("#h3_detail_author").html(user.username);

                    if (user.author) {
                        //生成删除按钮
                        var htmlStr = '<a href="javascript:void(0);">删除</a>';
                        //把HTML转换为jQuery对象并追加到当前页面
                        var deleteObj = jQuery(htmlStr);
                        //获取到按钮要追加元素的父标签
                        jQuery('.opts').append(deleteObj);
                        deleteObj.click(deleteBlog);
                    }


                } else {
                    alert(respData.message);
                }

            },
            error: function () {
                console.log("访问出现错误");
            },
            statusCode: {
                403: function () {
                    location.assign('blog_login.html');

                }
            }

        });

        //删除文章事件
        function deleteBlog() {
            if (!confirm("是否删除")) {
                return;
            }
            jQuery.ajax({
                type: 'delete',
                url: 'blog' + location.search,
                success: function (respData) {
                    if (respData.code == 0) {
                        location.assign('blog_list.html');
                    } else {
                        alert(respData.message);
                    }

                },
                error: function () {
                    console.log("访问出现错误");
                },
                statusCode: {
                    403: function () {
                        location.assign('blog_login.html');

                    }
                }

            });

        }


    })
</script>

4.编写发布博客的js代码

<!-- 先引入jQuery -->
<script src="./js/jquery-3.6.3.min.js"></script>
<!-- 再引入编辑器插件 -->
<script src="./editor.md/editormd.min.js"></script>
<!-- 初始化编辑器 -->
<script type="text/javascript">
    $(function () {
        var editor = editormd("blog_edit", {
            width: "100%",
            height: "100%",
            // theme : "dark",
            // previewTheme : "dark",
            // editorTheme : "pastel-on-dark",
            codeFold: true,
            //syncScrolling : false,
            saveHTMLToTextarea: true,    // 保存 HTML 到 Textarea
            searchReplace: true,
            //watch : false,                    // 关闭实时预览
            htmlDecode: "style,script,iframe|on*",            // 开启 HTML 标签解析,为了安全性,默认不开启    
            // toolbar  : false,             //关闭工具栏
            // previewCodeHighlight : false, // 关闭预览 HTML 的代码块高亮,默认开启
            emoji: true,
            taskList: true,
            tocm: true,         // Using [TOCM]
            tex: true,                     // 开启科学公式TeX语言支持,默认关闭
            flowChart: true,               // 开启流程图支持,默认关闭
            sequenceDiagram: true,         // 开启时序/序列图支持,默认关闭,
            placeholder: '开始创作...',     // 占位符
            path: "./editor.md/lib/"
        });

        jQuery("#submit").click(function () {
            //获取用户数据
            var titleEl = jQuery("#title");
            if (!titleEl.val() || titleEl.val().length == 0) {
                alert("请输入标题");

                return;
            }
            var contentEl = jQuery("#text_edit_content");
            if (!contentEl.val() || contentEl.val().length == 0) {
                alert("请输入文章内容");
                return;
            }
            //构造发送的数据
            var postData = {
                title: titleEl.val(),
                content: contentEl.val()
            }
            //提交请求
            jQuery.ajax({
                type: 'post',
                url: 'blog',
                contentType: 'application/x-www-form-urlencoded',
                data: postData,
                success: function (respData) {
                    if(respData.code==0){
                        alert('发布成功');
                        location.assign('blog_list.html');

                    }else{
                        alert(respData.message);
                        
                    }

                },
                error: function () {
                    console.log('访问出现错误');

                },
                statusCode: {
                    403: function () {
                        location.assign('blog_list.html');
                    }
                }

            })

        })


    });
</script>

三.部署并发布 

1.购买服务器

购买服务器,可以从阿里云,腾讯云中购买服务器 

 

 选择centos

 设置密码,购买即可

进入控制台,点击进入云服务器 

 

点击即可进入服务器实例

 

2.配置服务器

通过xshell连接服务器,主机即为刚才买服务器的公网ip,只有有密码的验证,即为设置的自定义密码

 登陆之后的页面

1.安装JDK

 yum -y install java-1.8.0-openjdk.x86_64

 注意:可通过Shift+insert复制到xshell中,有些笔记本电脑需要(Shift+Fn+insert)

通过以下命令验证是否安装成功,出现一下信息表示安装成功

java -version

 2.安装数据库


安装mariadb服务

yum install -y mariadb-server

安装mariadb命令行客户端

yum install -y mariadb

安装mariadb C library

yum install -y mariadb-libs

安装mariadb开发包

yum install -y mariadb-devel

启动服务

systemctl start mariadb

设置服务开启自启动

systemctl enable mariadb

 查看服务状态

systemctl status mariadb

 active表示启动成功

 安装成功之后可以正常连接服务器

语法与mysql一致 

可以通过以下代码来进行设置密码和修改密码,默认没有密码

set password for 'root' @'localhost'=password('newpassword');

修改数据库的端口号:

vi /etc/my.cnf.d/server.cnf

重启数据库服务

systemctl restart mariadb

查看端口号:

show variables like 'port';

 3.安装tomcat

下载 Tomcat 压缩包
通过官网进行下载: Apache Tomcat® - Apache Tomcat 8 Software Downloads

 

通过,下面的命令下载拖拽工具

yum -y  install lrzsz 

 直接将压缩包拖拽到命令行

 安装解压工具

yum -y install unzip

 解压压缩包

unzip apache-tomcat-8.5.47.zi

 此时表示解压成功

进入到tomcat的bin目录下,启动tomcat

chmmod +x ./*.sh  (因为没有执行权限,所以先改权限)

./startup.sh   (启动)

 通过以下命令查询状态

netstat -anp | grep 8080

进入控制台配置安全规则

 

 防火墙设置

查看防火墙状态(如果没开启,建议开启,不开启可以直接访问,开启了需要进行已下的操作访问)

systemctl status firewalld

 启动防火墙和关闭防火墙

systemctl start firewalld

systemctl stop firewalld

查看开放的端口号

firewall-cmd --list-ports

开启8080端口

firewall-cmd --permanent --add-port=8080/tcp

重启防火墙

firewall-cmd --reload

设置开机启动

systemctl enable firewalld

 访问地址:公网ip:8080,看到以下的画面表示tomcat开启成功

3.部署发布

将项目打为war包,拖拽到tomcat的webapps目录下

创建数据库

两种方式:第一种我们可以一点点复制粘贴sql语句到数据库中,一步一步的执行

第二种,我们可以将sql语句写到一个文件中,然后拖拽到一个目录下,然后执行以下的语句

 source /root/java78/create.sql

此时即可 

注意:需要将项目war包里面的设置与linux服务器中的配置一样,比如数据库的信息之类的.

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

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

相关文章

window系统中如何判断是物理机还是虚拟机及VMPROTECT无法检测云主机

为什么要判断物理机&#xff0c;因为授权不能对虚拟机安装后的软件进行授权。虚拟机可以复制可以克隆&#xff0c;无法作为一个不可复制ID来使用。 总结了如何判断物理机&#xff1a; 1. 用systeminfo的系统型号。&#xff08;注&#xff0c;有资料是看处理器和bios。但是我这…

【Terraform学习】使用 Terraform创建 S3 存储桶事件(Terraform-AWS最佳实战学习)

本站以分享各种运维经验和运维所需要的技能为主 《python》&#xff1a;python零基础入门学习 《shell》&#xff1a;shell学习 《terraform》持续更新中&#xff1a;terraform_Aws学习零基础入门到最佳实战 《k8》暂未更新 《docker学习》暂未更新 《ceph学习》ceph日常问题解…

Flutter 逆向安全

前几天在 "学习" 一个项目&#xff0c; 发现是用 Flutter 开发的。之前研究过 flutter 的逆向&#xff0c;早期 Flutter 有工具可以通过快照进行反编译&#xff1a;《对照表如下》 新的版本开发者没有维护了。 目前没有很好的工具 可以对 Flutter 进行反编译&#xf…

FanoutExchange广播(扇形)交换机

目录 一、简介 二、代码展示 父pom文件 pom文件 配置文件 config 生产者 消费者 测试 结果 一、简介 扇型&#xff08;广播&#xff09;交换机&#xff0c;这个交换机没有路由键概念&#xff0c;就算你绑了路由键也是无视的。 这个交换机在接收到消息后&#xff0c;…

WordPress导航主题/酷啦鱼导航主题模板

酷啦鱼导航主题模板&#xff0c;是一款基于WordPress的导航主题&#xff0c;酷啦鱼导航主题是个人基于wordpresscodestar work框架设计的简洁导航主题。 下载地址&#xff1a;https://bbs.csdn.net/topics/616084697

当 Apache Doris 遇上大模型:探秘腾讯音乐如何基于大模型 + OLAP 构建智能数据服务平台

本文导读&#xff1a; 当前&#xff0c;大语言模型的应用正在全球范围内引发新一轮的技术革命与商业浪潮。腾讯音乐作为中国领先在线音乐娱乐平台&#xff0c;利用庞大用户群与多元场景的优势&#xff0c;持续探索大模型赛道的多元应用。本文将详细介绍腾讯音乐如何基于 Apach…

【大模型AIGC系列课程 3-2】国产开源大模型:ChatGLM

1. GLM https://arxiv.org/pdf/2103.10360.pdf GLM是General Language Model的缩写,是一种通用的语言模型预训练框架。它的主要目标是通过自回归的空白填充来进行预训练,以解决现有预训练框架在自然语言理解(NLU)、无条件生成和有条件生成等任务中表现不佳的问题。 具体来…

python conda实践 sanic框架gitee webhook实践

import subprocess import hmac import hashlib import base64 from sanic.response import text from sanic import Blueprint from git import Repo# 路由蓝图 hook_blue Blueprint(hook_blue)hook_blue.route(/hook/kaifa, methods["POST"]) async def kaifa(req…

【Java 中级】一文精通 Spring MVC - 数据格式化器(六)

&#x1f449;博主介绍&#xff1a; 博主从事应用安全和大数据领域&#xff0c;有8年研发经验&#xff0c;5年面试官经验&#xff0c;Java技术专家&#xff0c;WEB架构师&#xff0c;阿里云专家博主&#xff0c;华为云云享专家&#xff0c;51CTO 专家博主 ⛪️ 个人社区&#x…

计算机毕设 基于机器视觉的二维码识别检测 - opencv 二维码 识别检测 机器视觉

文章目录 0 简介1 二维码检测2 算法实现流程3 特征提取4 特征分类5 后处理6 代码实现5 最后 0 简介 今天学长向大家介绍一个机器视觉的毕设项目&#xff0c;二维码 / 条形码检测与识别 基于机器学习的二维码识别检测 - opencv 二维码 识别检测 机器视觉 1 二维码检测 物体检…

WordPress主题Zing V2.2.1/模块化WordPress响应式通用企业商城主题

WordPress主题Zing V2.2.1&#xff0c;模块化WordPress响应式通用企业商城主题。 功能介绍 百度熊掌号文章实时推送、原创保护 多设备支持自适应布局&#xff0c;支持电脑、Pad、手机以及各种浏览器 SEO优化首页、文章、页面、分类均支持自定义标题、关键字和描述 速度优化…

ios ipa包上传需要什么工具

目录 ios ipa包上传需要什么工具 前言 一、IPA包的原理 二、IPA包上传的步骤 1.注册开发者账号 2.apk软件制作工具创建应用程序 3.构建应用程序 4.生成证书和配置文件 5.打包IPA包 6.上传IPA包 三、总结 前言 iOS IPA包是iOS应用程序的安装包&#xff0c;可以通过iT…

高忆管理:美股盘中狂泻600点,美联储释放重磅信号!

隔夜美股商场&#xff0c;上演大跳水。 当地时间8月24日&#xff0c;美股三大指数团体大跳水&#xff0c;道指跌1.08%&#xff0c;纳指大跌1.87%&#xff0c;标普500指数跌1.35%。标普、纳指均创惠誉下调美国主权评级以来最差单日体现&#xff0c;道指盘中由最高34694点跌到了…

freertos之队列集

队列集就是队列的集合 队列集的长度所包含队列的长度之和 实验 创建两个队列和一个队列集&#xff0c;并把队列添加到队列集&#xff0c;创建3个任务&#xff0c;其中两个任务往队列存数据&#xff0c;另一个任务通过队列集来获取数据。 实验结果&#xff1a;

星云日记是什么?流量共享模式特点

星云日记是什么&#xff1f;流量共享&#xff0c;一键解决卖货难题 星云日记,即将来袭,竞拍抢购模式,一键转卖,24小时转卖成功 顾客共享&#xff0c;资源共享&#xff0c;利润共享无需找顾客&#xff0c;一键转卖24H结算&#xff0c;别光盯着大饼&#xff0c;先解决生活问题。…

微信签到抽奖活动策划指南,打造成功的营销活动

在如今竞争激烈的市场环境下&#xff0c;吸引用户参与活动成为了企业吸粉、增加品牌知名度的重要手段之一。签到抽奖活动作为一种简单而又有趣的方式&#xff0c;能够吸引更多用户的参与。那么&#xff0c;制作一个吸引人的签到抽奖活动需要几个步骤呢&#xff1f;下面我们一起…

聚观早报|闻泰科技上半年净利润12.58亿;馥逸医疗完成A轮融资

【聚观365】8月27日消息 闻泰科技2023上半年净利润12.58亿 馥逸医疗完成A轮融资 东方甄选转型直播电商成功 AI牙齿美白公司白里挑一完成千万元天使轮融资 特斯拉新款Model 3全面升级 闻泰科技上半年净利润12.58亿 闻泰科技发布2023年半年报。报告期内&#xff0c;闻泰科技…

img引入的svg图片,悬浮时怎么修改颜色?

实现效果&#xff1a;鼠标悬浮在这一行&#xff0c;让这行的文字和svg图片颜色发生变化。 因为是用img标签引入页面&#xff0c;使用fill属性是无效的。 css核心代码&#xff1a; &:active,&:hover {transform: scale(0.98);img{filter: drop-shadow(#409eff 50px 0);…

如何在一个有500台PC以上的局域网配置IP、子网掩码

上午好&#xff0c;我的网工朋友。 IP地址是一种在Internet上的给主机编址的方式&#xff0c;它是IP协议提供的一种统一的地址格式。 它为互联网上的每一个网络和每一台主机分配一个逻辑地址&#xff0c;以此来屏蔽物理地址的差异。 现在是互联网大行的时代&#xff0c;所以…

网络中的问题2

距离-向量算法的具体实现 每个routerY的路由表表项 involve<目的网络N&#xff0c;距离d&#xff0c;下一跳X> 对邻居X发来的报文,先把下一跳改为X,再把距离1,if original route table doesn’t involve N,add this item&#xff1b; else if original table’s relate…