Java音讯体系简朴设想与完成_玖富娱乐主管发布


玖富娱乐是一家为代理招商,直属主管信息发布为主的资讯网站,同时也兼顾玖富娱乐代理注册登录地址。

媒介:由于导师在我的毕设项目里加了音讯体系(本来想水水就过的..),没办法...来轻微研讨研讨吧..简朴简朴...

需求剖析

我的毕设是一个博客体系,相似于简书如许的,以是音讯体系也相似,在用户的音讯里包罗了有:喜好和赞、批评、存眷、私信如许的一类器械,如许的一个体系应当包罗以下的功用:

    1. 当用户批评/存眷/点赞时能够或许关照到被批评/存眷/点赞的用户,并天生像以下花样的提示信息(许可作废存眷/点赞但不收到关照):

    我没有 存眷了 你
    三颗 喜好了你的文章 《Java音讯体系简朴设想与完成》
    心脏 批评了你的文章 《Java音讯体系简朴设想与完成》

    1. 用户之间能够或许发送/接收私信,不需要像QQ那样竖立长衔接完成及时通讯,但革新列表能看到新音讯,并且界面相似QQ谈天界面一左一右,许可删除私信
    1. 管理员能发送通知布告,实在就像是用管理员的账号给每一个用户发送私信;
    1. 能够检察存眷的用户最新宣布的文章,获得相似推送的结果;
    1. 一切音讯固然也要标注好音讯已读or未读,登录就可以获得音讯提示标识好有若干未读音讯,像是QQ音讯右上角的小红点那样相似;

OK,大抵就是以上的功用,那末题目来了:这要如何设想啊?

进一步剖析

实在能够依据上面的需求剖析,把上面的音讯大抵能够分为通知布告(Announcement)、提示(Remind)、私信(Message)三类,我们能够大抵笼统出一个 关照(Notify) 模子:

发送者 接收者 信息范例 行动范例 关照内容 是不是已读 音讯建立时刻
粉丝1号 我没有三颗心脏 提示 存眷 粉丝1号 存眷了 你 xx:xx:xx
粉丝1号 我没有三颗心脏 提示 喜好和赞 粉丝1号 喜好了你的文章 《Java音讯体系简朴设想与完成》 xx:xx:xx
粉丝1号 我没有三颗心脏 提示 批评 粉丝1号 批评了你的文章 《Java音讯体系简朴设想与完成》 xx:xx:xx
粉丝2号 我没有三颗心脏 私信 你收到了来自 粉丝2号 的 1 条私信 xx:xx:xx

上面加了一些数据以便明白,不外话说粉丝1号果然是真爱粉,又存眷又喜好又批评,嘻嘻嘻嘻...

emm.如许的模子能够或许胜任我们的事情吗?我也不知道..不外依据这个模子能够或许想出也许的如许的建立关照的逻辑:

好像看上去也没有甚么大题目..不外既然音讯内容都能够依据行动范例自动天生的了,加上私信和通知布告的内容由于长度题目也肯定不生存在这张内外的好,以是我们在设想数据库时痛快把关照内容这条去掉不要,当信息范例是通知布告或许私信时能够依据这条关照的 id 在响应的表中找到响应的数据就可以够或许了,emm..我以为能够

顺下去想一想实在脑中有了一个也许,如许的模子还轻易设想和想到,实在重要的题目照样下面的那些

题目一:单表数据大了如何办?

若是当用户量上去到肯定量的时刻,那末这张 关照表 势必会变得伟大,由于不论是我们的通知布告、提示照样私信都邑在这个关照表上建立一条数据,到时刻就会面对查询慢的题目,题目标谜底是:我也不知道..

以是我们的规定是:不斟酌像简书如许超大用户量,能够或许敷衍毕设就好啦..简朴设想,嘻嘻嘻..不外也不要太不置信MySQL的机能,照样有肯定包容才能的!

题目二:用户要如何准确获得本身的未读音讯呢?

暴力一点要领是,横竖关照内外有用户一切的音讯,直接读取完,然后经由历程是不是已读字段就可以够或许找到准确的一切未读音讯了,这..这么简朴吗?

实在有思考过运用时刻或许另建一张生存有最新已读到哪条音讯的表,但用户能够挑选有一些读有一些不读,这两个好像都很难到达目标...照样暴力吧

题目三:私信音讯该如何设想?

发送者 接收者 内容 发送时刻
粉丝1号 我没有三颗心脏 我是你的真爱粉啊!我要给你生山公! 2019年1月7日11:34:23
我没有三颗心脏 粉丝1号 已阅...下一个... 2019年1月7日11:34:53

就像 QQ音讯 一样嘛,包罗一个内容、时刻、发送者和接收者,然后前端直接依据时刻或许 id 排序天生一左一右的音讯对话框,不外对照迥殊的一点就是私信是一个双向交换的历程,在一个对话框中我能够既是接收者也是发送者,这也无所谓嘛,轻微剖析剖析场景:

  • 读取私信列表时:依照接收者和发送者一同查询的准绳,也就是查询接收者是本身和发送者是本身的数据,然后依据时刻和已读未读来竖立私信列表;
  • 读取私信时:这时候已经有了明白的接收者和发送者,那就查询一切 发送者是对方接收者是本身 Or 发送者是本身接收者是对方 的数据,然后在前端拼凑出一左一右的谈天框;
  • 发送私信时:先查询之前是不是有纪录,然后同上竖立谈天框,点击发送今后把发送方设为本身接收方设为私信对象,然后在关照表中新建一条未读数据关照私信对象有私信来了;

这完全能满足要求,只不外觉得查询多了些..

数据库设想

简朴弄了弄弄..看着挺难熬痛苦的,不外能简朴完胜利用,并且为了演示,这里是做了一张user_follow表,透露表现用户之间的联系干系干系,点赞和批评与这个相似,就未几弄了..下面给一下建表语句吧:

user表:

CREATE TABLE `user` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `username` varchar(50) NOT NULL COMMENT '用户姓名',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

user_follow表:

CREATE TABLE `user_follow` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `uid` bigint(20) NOT NULL COMMENT '用户ID',
  `follow_uid` bigint(20) NOT NULL COMMENT '存眷的用户id',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户存眷表,纪录了一切用户的存眷信息';

notify表:

CREATE TABLE `notify` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `sender_id` bigint(20) NOT NULL COMMENT '发送者用户ID',
  `reciver_id` bigint(20) NOT NULL COMMENT '接收者用户ID',
  `type` varchar(50) NOT NULL COMMENT '音讯范例:announcement通知布告/remind提示/message私信',
  `is_read` bit(1) NOT NULL DEFAULT b'0' COMMENT '是不是已读,0未读,1已读',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '建立时刻:按今后时刻自动建立',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户关照表,包罗了一切用户的音讯';

message表:

CREATE TABLE `message` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `notify_id` bigint(20) NOT NULL COMMENT '对应关照音讯的id',
  `sender_id` bigint(20) NOT NULL COMMENT '发送者用户ID',
  `reciver_id` bigint(20) NOT NULL COMMENT '接收者用户ID',
  `content` varchar(1000) NOT NULL COMMENT '音讯内容,最长长度不许可凌驾1000',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '建立时刻:按今后时刻自动建立',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='私信信息表,包罗了一切用户的私信信息';

依据《Java开辟手册》5.3 第六条 没有运用任何级联和外键,bingo!

Spring Boot MyBatis 实例

第一步:基本状况搭建

SpringBoot项目如何搭就不说了吧,给一给几个症结的设置装备摆设文件:

pom包依靠:

-玖富娱乐是一家为代理招商,直属主管信息发布为主的资讯网站,同时也兼顾玖富娱乐代理注册登录地址。-
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>1.3.2</version>
</dependency>
<!-- SpringBoot - MyBatis 逆向工程 -->
<dependency>
    <groupId>org.mybatis.generator</groupId>
    <artifactId>mybatis-generator-core</artifactId>
    <version>1.3.6</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>5.1.18</scope>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

这里有一个巨坑,耗费了我好半天的时刻,不知道为何我明显引入的 5.1.18 版本的 mysql-connector-java,可 Maven 就是非要给我对照新版本的 8.0.13,这致使了在我运用 MyBatis 逆向工程天生 domain 和 mapper 的历程当中涌现了以下的题目:

  • 1、提示我数据库衔接的驱动称号需要改成com.mysql.cj.jdbc.Driver而不是之前的com.mysql.jdbc.Driver,否则就报错:

Loading class com.mysql.jdbc.Driver'. This is deprecated. The new driver class iscom.mysql.cj.jdbc.Driver'. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.

  • 2、还需要设置 mysql 的时区,也就是需要将connectionURL属性写成"jdbc:mysql://localhost:3306/test?serverTimezone=UTC"。若是不指定serverTimezone=UTC(还必须大写),将报错:

java.sql.SQLException: The server time zone value '?й???????' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc time zone value if you want to utilize time zone support.
  at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:695)
   at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:663)

  • 3、逆向工程会去找 MySQL 其他库的雷同表名的表,然后天生一堆杂乱无章的器械,还由于找不到主键 id 天生了只含 inser() 要领而不含删除、更新要领的 Mapper 文件;

解决要领就只有本身手动去调低 mysql-connector-java 的版本到 5.xx,还找到一个跟我状况相似:https://blog.csdn.net/angel_xiaa/article/details/52474022

application.properties:

## 数据库衔接设置装备摆设
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/message_system?characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=123456
## MyBatis相干设置装备摆设
mybatis.type-aliases-package=com.wmyskxz.demo.messagesystem.domain
mybatis.mapper-locations=classpath:mapper/*.xml

在启动类上加上注解:

@EnableTransactionManagement  // 启注解事务管理,等同于xml设置装备摆设体式格局的 <tx:annotation-driven />
@MapperScan("com.wmyskxz.demo.messagesystem.dao")
@SpringBootApplication
public class MessageSystemApplication {
        ....
}

第二步:MyBatis 逆向工程

新建【util】包,在下面新建两个类:

MybatisGenerator类:

public class MybatisGenerator {

    public static void main(String[] args) throws Exception {
        String today = "2019-1-7";

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date now = sdf.parse(today);
        Date d = new Date();

        if (d.getTime() > now.getTime()   1000 * 60 * 60 * 24) {
            System.err.println("——————未成胜利运转——————");
            System.err.println("——————未成胜利运转——————");
            System.err.println("本顺序具有损坏作用,应当只运转一次,若是必需要再运转,需要修正today变量为本日,如:"   sdf.format(new Date()));
            return;
        }

        if (false)
            return;
        List<String> warnings = new ArrayList<String>();
        boolean overwrite = true;
        InputStream is = MybatisGenerator.class.getClassLoader().getResource("generatorConfig.xml").openStream();
        ConfigurationParser cp = new ConfigurationParser(warnings);
        Configuration config = cp.parseConfiguration(is);
        is.close();
        DefaultShellCallback callback = new DefaultShellCallback(overwrite);
        MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
        myBatisGenerator.generate(null);

        System.out.println("天生代码胜利,只能实行一次,今后实行会掩盖掉mapper,pojo,xml 等文件上做的修正");

    }
}

OverIsMergeablePlugin类:

/**
 * 解決 MyBatis 逆向工程反复天生掩盖题目标对象类
 */
public class OverIsMergeablePlugin extends PluginAdapter {
    @Override
    public boolean validate(List<String> warnings) {
        return true;
    }

    @Override
    public boolean sqlMapGenerated(GeneratedXmlFile sqlMap, IntrospectedTable introspectedTable) {
        try {
            Field field = sqlMap.getClass().getDeclaredField("isMergeable");
            field.setAccessible(true);
            field.setBoolean(sqlMap, false);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return true;
    }
}

在【resrouces】资本文件下新建逆向工程设置装备摆设文件【generatorConfig.xml】:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
        PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
    <context id="DB2Tables" targetRuntime="MyBatis3">

        <!--制止天生反复代码的插件-->
        <plugin type="com.wmyskxz.demo.messagesystem.util.OverIsMergeablePlugin"/>

        <!-- 是不是去除自动天生的代码中的解释 true:是 false:否-->
        <commentGenerator>
            <property name="suppressDate" value="true"/>
            <property name="suppressAllComments" value="true"/>
        </commentGenerator>

        <!--数据库链接地点账号密码-->
        <jdbcConnection driverClass="com.mysql.jdbc.Driver"
                        connectionURL="jdbc:mysql://localhost:3306/message_system?serverTimezone=UTC"
                        userId="root" password="123456">
        </jdbcConnection>
        <!-- 默许 false,把 JDBC DECIMAL 和 NUMERIC 范例剖析为 Integer
             为 true 时剖析为 java.math.BigDecimal -->
        <javaTypeResolver>
            <property name="forceBigDecimals" value="false"/>
        </javaTypeResolver>
        <!--天生pojo类寄存地位-->
        <javaModelGenerator targetPackage="com.wmyskxz.demo.messagesystem.domain" targetProject="src/main/java">
            <!-- enableSubPackages:是不是让 schema 作为包的后缀-->
            <property name="enableSubPackages" value="true"/>
            <!-- trimStrings:从数据库返回的值被清算前后的空格 -->
            <property name="trimStrings" value="true"/>
            <!-- 是不是对model增添 组织函数 -->
            <property name="constructorBased" value="true"/>
        </javaModelGenerator>
        <!--天生xml映照文件寄存地位-->
        <sqlMapGenerator targetPackage="mapper" targetProject="src/main/resources">
            <property name="enableSubPackages" value="true"/>
        </sqlMapGenerator>
        <!--天生mapper类寄存地位-->
        <javaClientGenerator type="XMLMAPPER" targetPackage="com.wmyskxz.demo.messagesystem.dao"
                             targetProject="src/main/java">
            <property name="enableSubPackages" value="true"/>
        </javaClientGenerator>

        <!--天生对应表及类名
            tableName:要天生的表名
            domainObjectName:天生后的实例名
            enableCountByExample:Count语句中到场where前提查询,默许为true开启
            enableUpdateByExample:Update语句中到场where前提查询,默许为true开启
            enableDeleteByExample:Delete语句中到场where前提查询,默许为true开启
            enableSelectByExample:Select多条语句中到场where前提查询,默许为true开启
            selectByExampleQueryId:Select单个对象语句中到场where前提查询,默许为true开启
        -->
        <table tableName="user" domainObjectName="User" enableCountByExample="false"
               enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="true"
               selectByExampleQueryId="false" enableDeleteByPrimaryKey="true" enableUpdateByPrimaryKey="true">
            <property name="my.isgen.usekeys" value="true"/>
            <property name="useActualColumnNames" value="false"/>
            <generatedKey column="id" sqlStatement="JDBC"/>
        </table>
        <table tableName="notify" domainObjectName="Notify" enableCountByExample="false"
               enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="true"
               selectByExampleQueryId="false" enableDeleteByPrimaryKey="true" enableUpdateByPrimaryKey="true">
            <property name="my.isgen.usekeys" value="true"/>
            <property name="useActualColumnNames" value="false"/>
            <generatedKey column="id" sqlStatement="JDBC"/>
        </table>
        <table tableName="user_follow" domainObjectName="UserFollow" enableCountByExample="false"
               enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="true"
               selectByExampleQueryId="false" enableDeleteByPrimaryKey="true" enableUpdateByPrimaryKey="true">
            <property name="my.isgen.usekeys" value="true"/>
            <property name="useActualColumnNames" value="false"/>
            <generatedKey column="id" sqlStatement="JDBC"/>
        </table>
        <table tableName="message" domainObjectName="Message" enableCountByExample="false"
               enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="true"
               selectByExampleQueryId="false" enableDeleteByPrimaryKey="true" enableUpdateByPrimaryKey="true">
            <property name="my.isgen.usekeys" value="true"/>
            <property name="useActualColumnNames" value="false"/>
            <generatedKey column="id" sqlStatement="JDBC"/>
        </table>
    </context>
</generatorConfiguration>

运转我们的【MybatisGenerator】类中的 main 要领就可以看到自动天生的实体、Xml文件和 Mapper 类

第三步:Service 层

不给接口了,直接给完成吧,要领都很简朴,并且没有做任何的平安限定,只是为了完成简朴的音讯体系,看结果

UserServiceImpl:

@Service
public class UserServiceImpl implements UserService {
    @Resource
    UserMapper userMapper;
    @Override
    public void addUserByUsername(String username) {
        userMapper.insert(new User(null, username));// 主键自增进.
    }
    @Override
    public User findUserById(Long id) {
        return userMapper.selectByPrimaryKey(id);
    }
}

UserFollowServiceImpl:

@Service
public class UserFollowServiceImpl implements UserFollowService {
    @Resource
    UserFollowMapper userFollowMapper;
    @Autowired
    NotifyService notifyService;
    @Override
    public void userAFollowUserBById(Long userAId, Long userBId) {
        // 先要建立一条提示音讯
        notifyService.addNotify(userAId, userBId, "follow");// 存眷信息
        UserFollow userFollow = new UserFollow();
        userFollow.setUid(userAId);
        userFollow.setFollowUid(userBId);
        userFollowMapper.insertSelective(userFollow);
    }
    @Override
    public void userAUnfollowUserBById(Long userAId, Long userBId) {
        // 起首查询到相干的纪录
        UserFollowExample example = new UserFollowExample();
        example.or().andUidEqualTo(userAId).andFollowUidEqualTo(userBId);
        UserFollow userFollow = userFollowMapper.selectByExample(example).get(0);
        // 删除存眷数据
        userFollowMapper.deleteByPrimaryKey(userFollow.getId());
    }
}

NotifyServiceImpl:

@Service
public class NotifyServiceImpl implements NotifyService {
    @Resource
    NotifyMapper notifyMapper;
    @Override
    public int addNotify(Long senderId, Long reciverId, String type) {
        Notify notify = new Notify(null, senderId, reciverId, type, false, null);
        return notifyMapper.insertSelective(notify);// id和creatTime自动天生.
    }
    @Override
    public void readNotifyById(Long id) {
        Notify notify = notifyMapper.selectByPrimaryKey(id);
        notify.setIsRead(true);
        notifyMapper.updateByPrimaryKey(notify);
    }
    @Override
    public List<Notify> findAllNotifyByReciverId(Long id) {
        List<Notify> notifies = new LinkedList<>();
        NotifyExample example = new NotifyExample();
        example.setOrderByClause("`id` DESC");// 按id倒叙,也就是第一个数据是最新的.
        example.or().andReciverIdEqualTo(id);
        notifies.addAll(notifyMapper.selectByExample(example));
        return notifies;
    }
    @Override
    public List<Notify> findAllUnReadNotifyByReciverId(Long id) {
        List<Notify> notifies = new LinkedList<>();
        NotifyExample example = new NotifyExample();
        example.setOrderByClause("`id` DESC");// 按id倒叙,也就是第一个数据是最新的.
        example.or().andReciverIdEqualTo(id).andIsReadEqualTo(false);
        notifies.addAll(notifyMapper.selectByExample(example));
        return notifies;
    }
}

MessageServiceImpl:

@Service
public class MessageServiceImpl implements MessageService {
    @Resource
    MessageMapper messageMapper;
    @Resource
    NotifyService notifyService;
    @Override
    public void addMessage(Long senderId, Long reciverId, String content) {
        // 先建立一条 notify 数据
        Long notifyId = (long) notifyService.addNotify(senderId, reciverId, "message");// message透露表现私信
        // 增添一条私信自信心
        Message message = new Message(null, notifyId, senderId, reciverId, content, null);
        messageMapper.insertSelective(message);// 插进去非空项,id/createTime数据库自动天生
    }
    @Override
    public void deleteMessageById(Long id) {
        messageMapper.deleteByPrimaryKey(id);
    }
    @Override
    public Message findMessageByNotifyId(Long id) {
        // 触发要领时应把音讯置为已读
        notifyService.readNotifyById(id);
        MessageExample example = new MessageExample();
        example.or().andNotifyIdEqualTo(id);
        return messageMapper.selectByExample(example).get(0);
    }
}

第四步:Controller 层

也很简朴,只是为了看结果

UserController:

@RestController
public class UserController {
    @Autowired
    UserService userService;
    @PostMapping("/addUser")
    public String addUser(@RequestParam String username) {
        userService.addUserByUsername(username);
        return "Success!";
    }
    @GetMapping("/findUser")
    public User findUser(@RequestParam Long id) {
        return userService.findUserById(id);
    }
}

UserFollowController :

@RestController
public class UserFollowController {
    @Autowired
    UserFollowService userFollowService;
    @PostMapping("/follow")
    public String follow(@RequestParam Long userAId,
                         @RequestParam Long userBId) {
        userFollowService.userAFollowUserBById(userAId, userBId);
        return "Success!";
    }
    @PostMapping("/unfollow")
    public String unfollow(@RequestParam Long userAId,
                           @RequestParam Long userBId) {
        userFollowService.userAUnfollowUserBById(userAId, userBId);
        return "Success!";
    }
}

NotifyController :

@RestController
public class NotifyController {
    @Autowired
    NotifyService notifyService;
    @PostMapping("/addNotify")
    public String addNotify(@RequestParam Long senderId,
                            @RequestParam Long reciverId,
                            @RequestParam String type) {
        notifyService.addNotify(senderId, reciverId, type);
        return "Success!";
    }
    @PostMapping("/readNotify")
    public String readNotify(@RequestParam Long id) {
        notifyService.readNotifyById(id);
        return "Success!";
    }
    @GetMapping("/listAllNotify")
    public List<Notify> listAllNotify(@RequestParam Long id) {
        return notifyService.findAllNotifyByReciverId(id);
    }
    @GetMapping("/listAllUnReadNotify")
    public List<Notify> listAllUnReadNotify(@RequestParam Long id) {
        return notifyService.findAllUnReadNotifyByReciverId(id);
    }
}

MessageController :

@RestController
public class MessageController {
    @Autowired
    MessageService messageService;
    @PostMapping("/addMessage")
    public String addMessage(@RequestParam Long senderId,
                             @RequestParam Long reciverId,
                             @RequestParam String content) {
        messageService.addMessage(senderId, reciverId, content);
        return "Success!";
    }
    @DeleteMapping("/deleteMessage")
    public String deleteMessage(@RequestParam Long id) {
        messageService.deleteMessageById(id);
        return "Success!";
    }
    @GetMapping("/findMessage")
    public Message findMessage(@RequestParam Long id) {
        return messageService.findMessageByNotifyId(id);
    }
}

第五步:测试

经由历程 REST 测试对象,能够看到准确的结果,这里就不给出一切的测试了。

总结

以上的项目简朴并且没有任何的平安考证,不外能够或许基本完成我们的需求,另有一些功用没有完成,比方管理员发通知布告(上面只演示了私信和存眷信息),依照上面的体系就直接暴力给每一个用户都加一条关照音讯,觉得有点自闭..我也不知道如何设想好..愿望有履历的大大能指条路啊!

实在关于这个简朴的体系我查了很多很多材料..把本身都看自闭了,厥后我痛快把一切网页都关掉,最先用 JPA 本身最先笼统实体,把各个实体写出来并把一切实体需要的数据啊相互之间的联系干系干系啊写清晰,然后再从自动天生的数据库中找思绪...hhh...要不是我 JPA 不是很熟我以为用 JPA 就可以写出来了,不消 JPA 的缘由在于一些数据的懒加载不知道如何处置惩罚,另有就是查询语句太庞杂,免不了要糟蹋一些资本...emmm..说到底照样不是迥殊懂 JPA,下面给一张庞杂的用 JPA 竖立的 User 实体吧(顺手截的..hhh...很乱..):

依照通例黏一个尾巴:

迎接转载,转载请说明出处!
简书ID:@我没有三颗心脏
github:wmyskxz
迎接存眷民众微旌旗灯号:wmyskxz
分享本身的进修 & 进修材料 & 生涯
想要交换的同伙也能够加qq群:3382693

-玖富娱乐是一家为代理招商,直属主管信息发布为主的资讯网站,同时也兼顾玖富娱乐代理注册登录地址。