基于Android的JavaEE课设

news2024/11/30 2:43:16

目录

1 技术栈

2 android前端

2.1 概述

2.1.1 目录结构

2.1.2 代码分层

2.2 技术点

2.2.1 数据绑定

2.2.2 前后端数据交互

2.2.3 九宫格图片

2.2.4 未处理消息提醒

2.2.5 动画效果

2.2.6 实时聊天

2.2.7 文件上传

2.2.8 底部弹窗

2.2.9 其他

3 后端

3.1 概述

3.1.1 目录结构

3.2 技术点

3.2.1 viewmodel

3.2.2 文件上传

3.2.3 websocket

4 服务器相关

4.1 搭建环境遇到的问题

4.1.1 本地访问不了远程mysql数据库

5 前后端交互设计文档

6 后台管理系统

6.1 搭建步骤

6.1.1 初始化本地仓库

6.1.2 从Gitee上拉取项目

6.1.3 配置、运行renren-fast项目

6.1.4 配置、运行renren-fast-vue项目

6.1.5 配置,运行 renren-generator

6.2 过程中遇到的问题

6.3 最终呈现效果


1 技术栈

前端:

  • android

后端:

  • springboot
  • springsecurity
  • mybatis-plus
  • redis
  • websocket

项目部署阿里云服务器

2 android前端

2.1 概述

主要介绍引用的第三方框架、技术点

2.1.1 目录结构

2.1.2 代码分层

不论是目录结构,还是代码,都应注意分层

2.2 技术点

2.2.1 数据绑定

viewBinding

android {
    buildFeatures {
        viewBinding true
    }
}

2.2.2 前后端数据交互

xutils

引入依赖

implementation 'org.xutils:xutils:3.8.5'
// gson
implementation 'com.google.code.gson:gson:2.8.2'

2.2.3 九宫格图片

AssNineGridView

2.2.4 未处理消息提醒

badgeview

2.2.5 动画效果

lottie

2.2.6 实时聊天

服务器 + websocket

2.2.7 文件上传

单文件、多文件

2.2.8 底部弹窗

2.2.9 其他

走马灯

    <TextView
        android:id="@+id/zm_tv"
        android:layout_width="260dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="32dp"
        android:ellipsize="marquee"
        android:focusable="true"
        android:focusableInTouchMode="true"
        android:marqueeRepeatLimit="-1"
        android:padding="10dp"
        android:singleLine="true"
        android:text="@string/trotting_horse_lamp"
        android:textColor="@color/baby_blue"
        android:textSize="20dp"
        app:layout_constraintHorizontal_bias="0.497"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent">
        <requestFocus />
    </TextView>

输入提示属性

android:hint="请输入用户名"

文本改变监听器

    searchEditText.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
        @Override
        public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
        @Override
        public void afterTextChanged(Editable editable) {
               // 文本改变后执行的动作
        }
    });

webView

spinner

3 后端

3.1 概述

3.1.1 目录结构

3.2 技术点

3.2.1 viewmodel

使用场景:比如用户有多个字段,但是当我们注册,登录时,并不需要这么多字段

好处:节省数据交互时空间的消耗,有提升效率的作用。

 

 实际上,我们需要的字段是比较少的,比如:

 在UserController层:

不过在最后,我们存入数据库的肯定还是原来的User,而不是UserRegisterVM, 所以,我们要对这两者之间作个转换:

User user = modelMapper.map(model, User.class);

以下是对modelMapper的封装,可以当做API调用。

public class BaseApiController {
 /**
     * The constant DEFAULT_PAGE_SIZE.
     */
    protected final static String DEFAULT_PAGE_SIZE = "10";
    /**
     * The constant modelMapper.
     */
    protected final static ModelMapper modelMapper = ModelMapperSingle.Instance();
}

需要使用modelMapper的时候,要继承BaseApiController 这里对应的是一个单例modelMapper

public class ModelMapperSingle {
    /**
     * The constant modelMapper.
     */
    protected final static ModelMapper modelMapper = new ModelMapper();
    private final static ModelMapperSingle modelMapperSingle = new ModelMapperSingle();

    static {
        modelMapper.getConfiguration().setFullTypeMatchingRequired(true);
        modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
    }

    /**
     * Instance model mapper.
     *
     * @return the model mapper
     */
    public static ModelMapper Instance() {
        return modelMapperSingle.modelMapper;
    }
}

3.2.2 文件上传

/*
* @description: 将文件保存在本地
* @author: xingxg
* @date: 2022/11/8 17:32
* @param: file , 与前端的名字相对应
* @return: 返回文件保存的路径
**/

@PostMapping("/upload")
public CommonResult<List<String>> fileLoad(MultipartFile[] file, HttpServletRequest request) throws IOException {
    String saveLocation = "e:/images/";
    //String saveLocation = "/images/";
    String fileSaveName = "";
    List<String> imageUri = new ArrayList<>();
    for (MultipartFile multipartFile : file) {
        fileSaveName = UUID.randomUUID().toString() + multipartFile.getOriginalFilename();
        multipartFile.transferTo(new File(saveLocation, fileSaveName));
        String result = request.getScheme() + "://" +
            request.getServerName() + ":" +
            request.getServerPort() + "/" +
            fileSaveName;
        imageUri.add(result);
    }
    return CommonResult.ok(imageUri);
}

3.2.3 websocket

此前的状态是,两个人进行聊天,A发一句,B需要重新进入聊天界面才能看到A新发的消息,这是不合理的,针对该问题进行改进。

预期效果,不用重新进入页面,只要由新消息传进来,就可以展示新的数据。

解决方法1:

前端周期性地去请求后端数据,达到实时聊天的效果。

这种方式非常消耗资源,明显是不合理的。

解决方法2:

A向B发消息, A将消息推送到服务器上,由服务器主动推动消息给B

 android

引入依赖

implementation "org.java-websocket:Java-WebSocket:1.3.7"

android核心代码

public void addUserToService() {
    URI serverURI = URI.create("ws://192.168.130.1:9000/chat/" + Global.username);

    webSocketClient = new WebSocketClient(serverURI) {
        @Override
        public void onOpen(ServerHandshake handshakedata) {
            Log.i("WebSocketClient", "onOpen");
        }
        @Override
        public void onMessage(String message) {
            loadMessage(); // 有新消息传给本用户的话,重新请求后端,加载数据。
        }
        @Override
        public void onClose(int code, String reason, boolean remote) {
            Log.i("WebSocketClient", "onClose");
        }
        @Override
        public void onError(Exception ex) {
            Log.i("WebSocketClient", "onError");
        }
    };
    try {
        webSocketClient.connectBlocking();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

后端核心代码

package com.huiliyi.backend.utils;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@ServerEndpoint(value = "/chat/{username}")
@Component
@Data
public class ChatEndpoint {

    //用来存储每个用户客户端对象的ChatEndpoint对象
    public static Map<String,ChatEndpoint> onlineUsers = new ConcurrentHashMap<>();

    //声明session对象,通过对象可以发送消息给指定的用户
    private Session session;

    private String username;
    //连接建立
    @OnOpen
    public void onOpen(@PathParam("username") String username,
                       Session session, EndpointConfig config){
        this.session = session;
        this.username = username;
        //存储登陆的对象
        onlineUsers.put(username,this);
        log.info("onOpen:{}", username);
    }
    //收到消息
    @OnMessage
    public void onMessage(String toName,Session session){
        //将数据转换成对象
        try {
            //发送数据
            log.info("onMessage:{}",toName);
            onlineUsers.get(toName).session.getBasicRemote().sendText("来消息了");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //关闭
    @OnClose
    public void onClose(Session session) {
        //从容器中删除指定的用户
        log.info("onClose:{}", username);
        onlineUsers.remove(username);
    }
}
public static Map<String,ChatEndpoint> onlineUsers = new ConcurrentHashMap<>();

系统中用户名昵称是全局唯一的,所以可以将用户名作为主键,使得每个用户对应一个ChatEndpoint

4 服务器相关

采用宝塔面板进行傻瓜式操作。

注意在阿里云的云服务器实例开放所需要的所有端口

4.1 搭建环境遇到的问题

4.1.1 本地访问不了远程mysql数据库

在linux本地可以登录mysql, 但是本地机连不上远程的?

  原因是远程主机没有开放3306端口

开放3306端口号后,还是出现问题:

这是因为远程的 主机限制了只能localhost连接数据库

所以,在远程主机上修改这个限制,就可以解决这个问题了

1、在安装Mysql数据库的主机上登录root用户:

mysql -u root -p

2、执行命令:

use mysql;
select host from user where user='root';

可以得到结果:

表名此时mysql数据库只允许localhost连接,所以此前才会拒绝本地的主机连接远程服务器。

3、将Host设置为通配符%

update user set host = '%' where user ='root';

4、Host修改完成后记得执行flush privileges使配置立即生效

flush privileges;

5 前后端交互设计文档

使用Apipost

在课程设计的过程中,项目采用前后端分离技术。

有的人负责编写后端,有的人负责编写前端。这可以使得整个项目的结构更加清晰明了,但是前端如何去与后端交互是一个问题。

因为前后端是不同的人写的,所以需要提前规范好API文档

而ApiPost不仅可以对API接口进行调试,还可以自动生成相对应的文档,是一个非常实用的开发的工具。

 生成的文档,就比较清晰,比自己写一个API接口文档要规范的多

6 后台管理系统

renren.io

人人开源是Gitee上的一个开源项目,可以快速搭建后台管理系统

6.1 搭建步骤

6.1.1 初始化本地仓库

1、 创建一个总目录,用来承载多个项目

2、初始化为git仓库

进入test_project

 

6.1.2 从Gitee上拉取项目

 

同理,再拉取2个项目

最终的目录层次为:

6.1.3 配置、运行renren-fast项目

 

 

 

运行项目, 访问Swagger文档路径,如果可以正常访问,则表明一切正常。

 

6.1.4 配置、运行renren-fast-vue项目

打开renren-fast-vue项目, 这里本人使用的是WebStorm编译器

依赖安装完成, 打开终端,运行项目

这里的命令行是:

 npm run dev

 

登录成功后:

此时,这个项目还算是一个空壳,没有管理到真正自身的项目

这是就需要另一个项目, renren-generator 实现代码生成!

代码生成需要提供关于数据库的表


6.1.5 配置,运行 renren-generator

 

修改generator.properties

注释出现乱码问题,修改字符集编码

 

在renren_fast数据库中插入你真正项目中所使用的表, 可以在已有的数据库中选择转储sql文件,然后在renren_fast中执行这个sql文件即可。

然后,就可以在代码生成器中查到你刚刚插入的数据库表。

运行项目,访问localhost

 

代码就自动生成了。

解压文件,可以看到有如下内容:

这些sql文件,直接拖到navicat里执行就可以了。

作用是用来生成管理的子菜单

 

将后端代码复制到renren-fast项目下的 module

最后,就可以实现对模块的管理。

6.2 过程中遇到的问题

人人开源后端中,自带了一个User,而我们自身模块有一个名字一模一样的User

冲突1:

  • Spring容器中UserService组件不唯一

解决:

冲突2:

  • UserDao也是自动注入的。虽然说对应的mapper文件可以映射过去,但是名字重复了,还是会有点问题.

解决方法:

冲突3:

  • ShiroConfig 已经存在对UserEntity的映射。意思就是说,类名不能重复。

解决方法:修改类名

6.3 最终呈现效果

可以看到,用户的ID后几位都为0,这是由于前段接收Long类型时,出现精度丢失,以下为解决方式:

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

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

相关文章

BUUCTF Misc 假如给我三天光明 数据包中的线索 后门查杀 webshell后门

假如给我三天光明 下载文件&#xff0c;一个压缩包&#xff08;需要密码&#xff09;和图片 百度得知下面一行是盲文&#xff0c;根据盲文对照表 和上述图片对照&#xff0c;得到字符串&#xff1a;kmdonowg 。使用它解压压缩包 使用Audacity打开 转换成摩斯密码&#xff0c;…

C语言程序设计 复习总结[持续更新ing]

目录 一 初识C语言 1 main 主函数 2 注释 3 C 程序执行的过程&#xff1a; 4 C 程序的结构 5 进制的转换 1.内存容量 2.二进制与十进制的转换 1>将二进制数转换成十进制 2>将十进制转换成二进制数 3.二进制与八进制的转换 1>将八进制数转换成二进制: 2>将二进…

Java项目:JSP酒店客房管理系统

作者主页&#xff1a;源码空间站2022 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文末获取源码 项目介绍 酒店管理系统共分为三个角色&#xff0c;客房经理、前台管理员、客户&#xff0c;各个角色的权限各不相同&#xff1b; 客房经理功能包括&#…

leetcode《图解数据结构》刷题日志【第五周】(2022/11/21-2022/11/28)

leetcode《图解数据结构》刷题日志【第五周】1. 剑指 Offer 60. n 个骰子的点数1.1 题目1.2 解题思路1.3 数据类型功能函数总结1.4 java代码1.5 踩坑小记1.6 进阶做法2. 剑指 Offer 63. 股票的最大利润2.1 题目2.2 解题思路2.3 数据类型功能函数总结2.4 java代码3. 剑指 Offer …

SpringBoot SpringBoot 原理篇 1 自动配置 1.16 自动配置原理【2】

SpringBoot 【黑马程序员SpringBoot2全套视频教程&#xff0c;springboot零基础到项目实战&#xff08;spring boot2完整版&#xff09;】 SpringBoot 原理篇 文章目录SpringBootSpringBoot 原理篇1 自动配置1.16 自动配置原理【2】1.16.1 看源码了1.16.2 Import({AutoConfig…

archlinux 安装matlab

最近在学matlab使用的是windows版本的&#xff0c;比起windows我更喜欢在linux中写代码。于是乎就想在Linux中安装一下。 主要过程参考此篇文章&#xff1a; 《【首发】 ubuntu20.04安装matlab2021b/matlab2020b》 https://blog.csdn.net/hanjuefu5827/article/details/1151677…

【Hack The Box】Linux练习-- Forge

HTB 学习笔记 【Hack The Box】Linux练习-- Forge &#x1f525;系列专栏&#xff1a;Hack The Box &#x1f389;欢迎关注&#x1f50e;点赞&#x1f44d;收藏⭐️留言&#x1f4dd; &#x1f4c6;首发时间&#xff1a;&#x1f334;2022年11月27日&#x1f334; &#x1f36…

队列(C语言实现)

文章目录&#xff1a;1.队列的概念2.队列的结构3.接口实现3.1初始化队列3.2判断队列是否为空3.3入队3.4出队3.5查看队头元素3.6查看队尾元素3.7统计队列数据个数3.8销毁队列1.队列的概念 队列&#xff1a;只允许在一端进行插入数据操作&#xff0c;在另一端进行删除数据操作的特…

jQuery插件【validate】国际化校验插件

jQuery插件系列 相信大家在网站上都遇到过这种注册的情况吧&#xff0c;有的时候我们什么也不输入点登录或者注册或者鼠标失去焦点的时候&#xff0c;就会自动提示xxx为空&#xff0c;密码不正确&#xff0c;请输入xxx等一系列的提示信息。 那么这是怎么实现的呢&#xff0c;其…

【LeetCode】No.101. Symmetric Tree -- Java Version

题目链接&#xff1a;https://leetcode.com/problems/symmetric-tree/ 1. 题目介绍&#xff08;Symmetric Tree&#xff09; Given the root of a binary tree, check whether it is a mirror of itself (i.e., symmetric around its center). 【Translate】&#xff1a; 给定…

QT实战项目1——无边框窗口拖拽和阴影

课时2 开发环境,无边框窗口拖拽和阴影_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV14t411b7EL?p2&vd_source0471cde1c644648fafd07b54e303c905 目录 一、设置无边框 和 鼠标可以拖动窗口 1.1 设置无边框 1.2 鼠标拖动 1.3 展示阴影 一、设置无边框 和 鼠标可…

设计模式-组合模式

组合模式一、学校院系展示需求二、传统方案解决学校院系展示三、组合模式基本介绍四、组合模式原理类图五、组合模式解决的问题六、使用组合模式解决院校展示问题6.1、类图6.2、代码一、学校院系展示需求 编写程序展示一个学校院系结构&#xff1a;需求是这样&#xff0c;要在…

SQL练习题

新建数据表 首先建立测试数据库的表&#xff0c;新建数据库的sql语句如下&#xff0c;大家可以粘贴成一个sql文件&#xff0c;然后新建所有的表并插入所有的数据&#xff1a; 新建数据库sql文件&#xff1a; DROP TABLE IF EXISTS EMP; DROP TABLE IF EXISTS DEPT; DROP TAB…

Unity UI锚点和位置关系

一、Anchors锚点 Anchors的设置会直接改变RectTransform中它的位置信息&#xff1b;Anchors设置中的X 改变会影响&#xff08;PosX和Width&#xff09;或&#xff08;left和right&#xff09; 1、Anchors改变位置信息 下图中X锚点的Min和Max值相同时&#xff0c;上面的一栏中…

Java调用命令行并返回打印的内容

博主在最近的工作中&#xff0c;收到了这样一个需求。 调用别人以前完成开发的 jar 包或 python 程序&#xff0c;并将原程序在命令行中输出的内容封装为 JSON 对象后通过 RESTFul 接口返回。 面对以上的需求&#xff0c;博主给出了以下解决方案。话不多说&#xff0c;上代码。…

Mathematica for Linux v13.1.0 科学计算软件多语言版

Wolfram Mathematica for Linux 中文正式版是一款强大的数学计算科学计算软件&#xff0c;MathWorks MATLAB 和 Wolfram Mathematica 、Maplesoft Maple 并称为三大数学软件&#xff0c;Wolfram Mathematica 中文正式版主要用于符号计算软件&#xff0c;也称为计算机代数系统&a…

MySQL如何恢复不小心误删的数据记录(binlog)

前言 题主于今天&#xff08;2022年11月27日&#xff09; 在线上环境误操作删除了记录&#xff0c;且没有备份数据&#xff0c;通宵排查事故原因&#xff0c;终于没有酿成生产事故。谨以此文记录。 参考资料 https://blog.csdn.net/qq_23543983/article/details/127298578 …

单源最短路径问题(Java)

单源最短路径问题&#xff08;Java&#xff09; 文章目录单源最短路径问题&#xff08;Java&#xff09;1、问题描述2、算法思路3、代码实现4、算法正确性和计算复杂性4.1 贪心选择性质4.2 最优子结构性质4.3 计算复杂性5、参考资料1、问题描述 给定带权有向图G(V,E),其中每条…

分布式电源接入对配电网的影响matlab程序(IEEE9节点系统算例)

分布式电源接入对配电网的影响matlab程序&#xff08;IEEE9节点系统算例&#xff09; 摘 要&#xff1a;分布式电源的接入使得配电系统从放射状无源网络变为分布有中小型电源的有源网络。带来了使单向流动的电流方向具有了不确定性等等问题&#xff0c;使得配电系统的控制和管…

Android反编译apk

文章目录安装Android Studio1. 解压apk文件方法一&#xff1a;使用apktool反编译&#xff08;得到的是.smali文件和可直接读的资源文件&#xff0c;如果要得到.dex文件&#xff0c;还要看方法二&#xff09;方法二&#xff1a;使用解压工具解压&#xff08;得到的是.dex文件和二…