• 懒人方案-半天搞定一个分布式后台管理系统


    前言

    老规矩,冒个泡,不知道为啥最近也是懒,一点点动力都没有了,可能是由于几个星星导致的精神萎靡吧,也可能是财富岛太迷人了。那么今天也是带来第二个part,也就是如何快速基于renren-fast 完成后台管理项目的构建。那么今天的内容呢,有一下两点,第一是如何打通分布式微服务与前端之间的交互,第二个就是如何完成后台页面的搭建。当然最主要的就是如何完成后台的页面搭建嘛,第一个谁不会呀,无非是跨越嘛。今天的内容很简单也不多,但是混个期末作业绰绰有余。

    环境

    首先是咱们的环境,这个环境包括了我一些组件的版本,然后就是我所使用的工具。

    SpringBoot:2.3.2.RELEASE
    SpringCloud:Hoxton.SR9
    SpringCloudAlibaba:2.2.6.RELEASE
    nacos:1.14

    使用的开源项目是:

    renren-fast
    renren-fast-vue
    renren-generation

    这个renren-generation前面的博文有说道:
    懒人方案–半天搞定一个SpringBoot单体项目

    不过这里由于我们这边是分布式的一个项目,所以我们需要把renren-fast注册到我们的nacos里面,最新的renren-fast的版本呢和我们上面给的环境版本是不一样的,所以需要降低版本。不过这个是后话了,待会再说,现在先把对应的环境搭建起来。

    后台管理系统搭建

    我们先把对应的前端代码搞到手,打开项目地址,上次给的是github的一个玩意,现在发现在gitee也有,毕竟也是国人发起的项目嘛。其实你也可以直接试一试人家的renren-security的,当然有时间再体验了,都一样的。

    前端搭建

    我们先把前端搭建好,我们去gitee里面把东西嫖到手。
    在这里插入图片描述

    下载解压,然后构建一下依赖,这样就把前端的项目构建好了,构建好之后大概是这样样子的。

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

    不过验证码这里是不会有的你得把后端构建好。因为这个验证码和我们先前做的不一样还是后端给的,以前为我都是尽可能把一些东西给前端做的,验证码也是前端的,当然防君子不防小人了哈。不过也没啥,设置黑名单嘛。

    后端搭建

    后端的话也是类似的,首先下载代码。

    idea打开,等待加载好就可以了。

    在这里插入图片描述

    然后打开你的数据库。
    执行一下对应的sql语句,比如我是mysql我就执行里面的sql。
    在这里插入图片描述

    我在我mysql里面创建了一个数据库。
    在这里插入图片描述

    然后执行了sql之后,你就会看到这些表
    在这里插入图片描述

    之后在配置文件里面配置一下数据库就好了
    在这里插入图片描述
    如果你的端口有冲突的话,换了端口那么需要在前端改一下地址。
    在这里插入图片描述

    这里主要默认地址是 127.0.0.1:8000/renren-fast 我这个是改了网关的哈。
    之后是这样的:
    在这里插入图片描述

    到此我们就搭建好了。但是还不够,由于我们是 分布式的玩意,我们是有nacos注册中心的,之后我们是需要和我们的微服务之间调动的。

    也就是这样:
    在这里插入图片描述

    renren-fast改动

    所以我们这边要做改动,首先第一点就是改依赖,现在官方给的配置是2.6.6的SpringBoot版本,然后也没有SpringCloud,所以我们要改动。

    它这里的配置我改成了这样:

    
    	<parent>
    		<groupId>org.springframework.bootgroupId>
    		<artifactId>spring-boot-starter-parentartifactId>
    		<version>2.3.2.RELEASEversion>
    		<relativePath   />
    	parent>
    
    	<properties>
    		<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
    		<project.reporting.outputEncoding>UTF-8project.reporting.outputEncoding>
    		<java.version>1.8java.version>
    		<mybatisplus.version>3.3.1mybatisplus.version>
    		<mysql.version>8.0.28mysql.version>
    		<mssql.version>4.0mssql.version>
    		<oracle.version>11.2.0.3oracle.version>
    		<druid.version>1.1.13druid.version>
    		<quartz.version>2.3.0quartz.version>
    		<commons.lang.version>2.6commons.lang.version>
    		<commons.fileupload.version>1.2.2commons.fileupload.version>
    		<commons.io.version>2.5commons.io.version>
    		<commons.codec.version>1.10commons.codec.version>
    		<commons.configuration.version>1.10commons.configuration.version>
    		<shiro.version>1.9.0shiro.version>
    		<jwt.version>0.7.0jwt.version>
    		<kaptcha.version>0.0.9kaptcha.version>
    		<qiniu.version>7.2.23qiniu.version>
    		<aliyun.oss.version>2.8.3aliyun.oss.version>
    		<qcloud.cos.version>4.4qcloud.cos.version>
    		<swagger.version>2.7.0swagger.version>
    		<joda.time.version>2.9.9joda.time.version>
    		<gson.version>2.8.5gson.version>
    		<fastjson.version>1.2.79fastjson.version>
    		<hutool.version>4.1.1hutool.version>
    		<lombok.version>1.18.4lombok.version>
    
    		
    		<service-path>/work/renrenservice-path>
    		<pack-name>${project.artifactId}-${project.version}.jarpack-name>
    		<remote-addr>192.168.1.10:22remote-addr>
    		<remote-username>rootremote-username>
    		<remote-passwd>123456remote-passwd>
    	properties>
    
    	<dependencies>
    
    		<dependency>
    			<groupId>com.huterox.whitehole.commongroupId>
    			<artifactId>whiteholo-commonartifactId>
    			<version>0.0.1-SNAPSHOTversion>
    		dependency>
    
    
    		<dependency>
    			<groupId>org.springframework.bootgroupId>
    			<artifactId>spring-boot-starter-testartifactId>
    			<scope>testscope>
    		dependency>
    		<dependency>
    			<groupId>org.springframework.bootgroupId>
    			<artifactId>spring-boot-starter-webartifactId>
    		dependency>
    		<dependency>
    			<groupId>org.springframework.bootgroupId>
    			<artifactId>spring-boot-starter-aopartifactId>
    		dependency>
    		<dependency>
    			<groupId>org.springframeworkgroupId>
    			<artifactId>spring-context-supportartifactId>
    		dependency>
    		<dependency>
    			<groupId>org.springframework.bootgroupId>
    			<artifactId>spring-boot-starter-data-redisartifactId>
    		dependency>
    		<dependency>
    			<groupId>org.springframework.bootgroupId>
    			<artifactId>spring-boot-starter-validationartifactId>
    		dependency>
    		<dependency>
    			<groupId>org.springframework.bootgroupId>
    			<artifactId>spring-boot-configuration-processorartifactId>
    			<optional>trueoptional>
    		dependency>
    		
    		
    		
    		
    		
    		<dependency>
    			<groupId>com.baomidougroupId>
    			<artifactId>mybatis-plus-boot-starterartifactId>
    			<version>${mybatisplus.version}version>
    			<exclusions>
    				<exclusion>
    					<groupId>com.baomidougroupId>
    					<artifactId>mybatis-plus-generatorartifactId>
    				exclusion>
    			exclusions>
    		dependency>
    		<dependency>
    			<groupId>mysqlgroupId>
    			<artifactId>mysql-connector-javaartifactId>
    			<version>${mysql.version}version>
    		dependency>
    		
    		<dependency>
    			<groupId>com.oraclegroupId>
    			<artifactId>ojdbc6artifactId>
    			<version>${oracle.version}version>
    		dependency>
    		
    		<dependency>
    			<groupId>com.microsoft.sqlservergroupId>
    			<artifactId>sqljdbc4artifactId>
    			<version>${mssql.version}version>
    		dependency>
    		
    		<dependency>
    			<groupId>org.postgresqlgroupId>
    			<artifactId>postgresqlartifactId>
    		dependency>
    		<dependency>
    			<groupId>com.alibabagroupId>
    			<artifactId>druid-spring-boot-starterartifactId>
    			<version>${druid.version}version>
    		dependency>
    		<dependency>
    			<groupId>org.quartz-schedulergroupId>
    			<artifactId>quartzartifactId>
    			<version>${quartz.version}version>
    			<exclusions>
    				<exclusion>
    					<groupId>com.mchangegroupId>
    					<artifactId>c3p0artifactId>
    				exclusion>
    			exclusions>
    		dependency>
    		<dependency>
    			<groupId>commons-langgroupId>
    			<artifactId>commons-langartifactId>
    			<version>${commons.lang.version}version>
    		dependency>
    		<dependency>
    			<groupId>commons-fileuploadgroupId>
    			<artifactId>commons-fileuploadartifactId>
    			<version>${commons.fileupload.version}version>
    		dependency>
    		<dependency>
    			<groupId>commons-iogroupId>
    			<artifactId>commons-ioartifactId>
    			<version>${commons.io.version}version>
    		dependency>
    		<dependency>
    			<groupId>commons-codecgroupId>
    			<artifactId>commons-codecartifactId>
    			<version>${commons.codec.version}version>
    		dependency>
    		<dependency>
    			<groupId>commons-configurationgroupId>
    			<artifactId>commons-configurationartifactId>
    			<version>${commons.configuration.version}version>
    		dependency>
    		<dependency>
    			<groupId>org.apache.shirogroupId>
    			<artifactId>shiro-coreartifactId>
    			<version>${shiro.version}version>
    		dependency>
    		<dependency>
    			<groupId>org.apache.shirogroupId>
    			<artifactId>shiro-springartifactId>
    			<version>${shiro.version}version>
    		dependency>
    		<dependency>
    			<groupId>io.jsonwebtokengroupId>
    			<artifactId>jjwtartifactId>
    			<version>${jwt.version}version>
    		dependency>
    		<dependency>
    			<groupId>com.github.axetgroupId>
    			<artifactId>kaptchaartifactId>
    			<version>${kaptcha.version}version>
    		dependency>
    		<dependency>
    			<groupId>io.springfoxgroupId>
    			<artifactId>springfox-swagger2artifactId>
    			<version>${swagger.version}version>
    		dependency>
    		<dependency>
    			<groupId>io.springfoxgroupId>
    			<artifactId>springfox-swagger-uiartifactId>
    			<version>${swagger.version}version>
    		dependency>
    		<dependency>
    			<groupId>com.qiniugroupId>
    			<artifactId>qiniu-java-sdkartifactId>
    			<version>${qiniu.version}version>
    		dependency>
    		<dependency>
    			<groupId>com.aliyun.ossgroupId>
    			<artifactId>aliyun-sdk-ossartifactId>
    			<version>${aliyun.oss.version}version>
    		dependency>
    		<dependency>
    			<groupId>com.qcloudgroupId>
    			<artifactId>cos_apiartifactId>
    			<version>${qcloud.cos.version}version>
    			<exclusions>
    				<exclusion>
    					<groupId>org.slf4jgroupId>
    					<artifactId>slf4j-log4j12artifactId>
    				exclusion>
    			exclusions>
    		dependency>
    		<dependency>
    			<groupId>joda-timegroupId>
    			<artifactId>joda-timeartifactId>
    			<version>${joda.time.version}version>
    		dependency>
    		<dependency>
    			<groupId>com.google.code.gsongroupId>
    			<artifactId>gsonartifactId>
    			<version>${gson.version}version>
    		dependency>
    		<dependency>
    			<groupId>com.alibabagroupId>
    			<artifactId>fastjsonartifactId>
    			<version>${fastjson.version}version>
    		dependency>
    		<dependency>
    			<groupId>cn.hutoolgroupId>
    			<artifactId>hutool-allartifactId>
    			<version>${hutool.version}version>
    		dependency>
    		<dependency>
    			<groupId>org.projectlombokgroupId>
    			<artifactId>lombokartifactId>
    			<version>${lombok.version}version>
    		dependency>
    	dependencies>
    
    	<build>
    		<finalName>${project.artifactId}finalName>
    		<extensions>
    			<extension>
    				<groupId>org.apache.maven.wagongroupId>
    				<artifactId>wagon-sshartifactId>
    				<version>2.8version>
    			extension>
    		extensions>
    		<plugins>
    			<plugin>
    				<groupId>org.springframework.bootgroupId>
    				<artifactId>spring-boot-maven-pluginartifactId>
    				<configuration>
    					<fork>truefork>
    				configuration>
    			plugin>
    			
    			<plugin>
    				<groupId>org.apache.maven.pluginsgroupId>
    				<artifactId>maven-surefire-pluginartifactId>
    				<configuration>
    					<skipTests>trueskipTests>
    				configuration>
    			plugin>
    			<plugin>
    				<groupId>org.codehaus.mojogroupId>
    				<artifactId>wagon-maven-pluginartifactId>
    				<version>1.0version>
    				<configuration>
    					<fromFile>target/${pack-name}fromFile>
    					<url>url>
    					<commands>
    						
    						<command>kill -9 `ps -ef |grep ${project.artifactId}.jar|grep -v "grep" |awk '{print $2}'`command>
    						
    						<command> ${service-path}/renren.log 2>&1 & ]]>command>
    						<command>command>
    						<command>command>
    					commands>
    					
    					<displayCommandOutputs>truedisplayCommandOutputs>
    				configuration>
    			plugin>
    
    			<plugin>
    				<groupId>com.spotifygroupId>
    				<artifactId>docker-maven-pluginartifactId>
    				<version>0.4.13version>
    				
    				
    				
    				
    				
    				
    				
    				
    				<configuration>
    					<imageName>renren/fastimageName>
    					<dockerDirectory>${project.basedir}dockerDirectory>
    					<resources>
    						<resource>
    							<targetPath>/targetPath>
    							<directory>${project.build.directory}directory>
    							<include>${project.build.finalName}.jarinclude>
    						resource>
    					resources>
    				configuration>
    				
    			plugin>
    		plugins>
    	build>
    
    	<repositories>
    		<repository>
    			<id>publicid>
    			<name>aliyun nexusname>
    			<url>https://maven.aliyun.com/repository/public/url>
    			<releases>
    				<enabled>trueenabled>
    			releases>
    		repository>
    	repositories>
    	<pluginRepositories>
    		<pluginRepository>
    			<id>publicid>
    			<name>aliyun nexusname>
    			<url>https://maven.aliyun.com/repository/public/url>
    			<releases>
    				<enabled>trueenabled>
    			releases>
    			<snapshots>
    				<enabled>falseenabled>
    			snapshots>
    		pluginRepository>
    	pluginRepositories>
    

    这里的那个common依赖其实是上次的那篇博客里面的可以去看看,这个是我的需求,你自己看着提取出来。

    之后就是把这个代码注释一下:
    在这里插入图片描述

    原因有两个:

    1. allowedOrigings和当前的2.26的SpringBoot有冲突,人家名字改了。
    2. 接入微服务集群后,要用网关统一处理,这里不需要额外的跨越。

    接入微服务集群

    配置

    首先是老规矩嘛,由于我导入了common包,这个包里面我是已经有nacos的服务注册发现对应的依赖的,所以我就不用导入了。

    那么这里开启注解
    在这里插入图片描述
    然后去配置地址:
    在这里插入图片描述

    然后重启服务就好了。

    网关

    现在我们要做的是前后端分离,而且需要统一转发在前端。这个跨越的话,咱们以前也做过在前端也可以做,但是现在的话试一试在后端玩玩。不过不管是哪一个端咱们都需要统一api接口。

    所以我们这里也是规定,所有的请求都需要带上api才转发,当然这个也是网关配置的一些需要嘛。

    所以我这样做如下配置:

    spring:
      cloud:
        nacos:
          discovery:
            server-addr: 127.0.0.1:8848
            service: gateway
        gateway:
          discovery:
            locator:
              enabled: true
          routes:
            #这里先做一个基本的服务转发
            - id: activiy8000
              uri: lb://activiy
              predicates:
                - Path=/api/activiy/**
              filters:
                - RewritePath=/api/activiy/(?>.*),/$\{segment}
    
            - id: blog8050
              uri: lb://blog
              predicates:
                - Path=/api/blog/**
              filters:
                - RewritePath=/api/blog/(?>.*),/$\{segment}
    
            - id: community8100
              uri: lb://community
              predicates:
                - Path=/api/community/**
              filters:
                - RewritePath=/api/community/(?>.*),/$\{segment}
    
            - id: hole8150
              uri: lb://hole
              predicates:
                - Path=/api/hole/**
              filters:
                - RewritePath=/api/hole/(?>.*),/$\{segment}
    
    
            - id: quiz8200
              uri: lb://quiz
              predicates:
                - Path=/api/quiz/**
              filters:
                - RewritePath=/api/quiz/(?>.*),/$\{segment}
    
            - id: user8250
              uri: lb://user
              predicates:
                - Path=/api/user/**
              filters:
                - RewritePath=/api/user/(?>.*),/$\{segment}
    
    
            - id: admin_route
              uri: lb://renren-fast  # 网关负载均衡的发送到renren-fast
              predicates:
                - Path=/api/**
              filters:
                - RewritePath=/api/(?>.*),/renren-fast/$\{segment}  #实现路径重写
    
    

    这里有6个微服务嘛,然后转发。

    之后是咱们的前端,也就是这里改一下:
    在这里插入图片描述

    跨越

    这部分的跨越咱们就在网关做了,记住注释掉renren-fast里面的跨越。

    @Configuration
    public class WhiteHoleCorsConfig {
    
        @Bean
        public CorsWebFilter corsWebFilter(){
            UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    
            CorsConfiguration corsConfiguration = new CorsConfiguration();
    
            //1.配置跨域
            corsConfiguration.addAllowedHeader("*");
            corsConfiguration.addAllowedMethod("*");
            corsConfiguration.addAllowedOrigin("*");
            corsConfiguration.setAllowCredentials(true);
    
            source.registerCorsConfiguration("/**",corsConfiguration);
            return new CorsWebFilter(source);
        }
    }
    

    在这里插入图片描述

    编写后台管理

    个性化处理

    现在我们把基本的玩意都准备好了,在开始之前我们在做一个个性化处理。

    首先是把这个换了
    在这里插入图片描述
    看你自己,反正我要换。
    把这个换了就好了
    在这里插入图片描述

    然后是标题
    在这里插入图片描述

    然后是首页的侧边栏
    在这里插入图片描述

    之后是详情描述页面
    也就是这个:
    在这里插入图片描述
    这个页面在这:
    在这里插入图片描述

    之后我的页面就变成了这样(这里面我后面添加了一些菜单):
    在这里插入图片描述

    ok,我们完成了基本的个性化处理,那么接下来我们来点实战。

    这里我已经做好了两个模块,现在我再为文章管理做一个模块。

    文章管理(案例)

    首先说明一下,咱们的这个代码也是通过renren-generation 生成的,这个在咱们之前有说过。在这篇博文:
    懒人方案–半天搞定一个SpringBoot单体项目

    在咱们的代码是生成了代码和vue文件已经sql的,然后我当时是暂时放在了这个地方:
    在这里插入图片描述

    第一个是sql语句,这个是用来生成菜单的,但是这个的话一般我们可能用不上,当然也可以直接用,那么是干嘛的呢,我们待会说。

    创建菜单

    我们先来创建一个菜单。
    在这里插入图片描述
    在这里插入图片描述
    之后刷新一下:
    在这里插入图片描述

    然后就创建好了,那么我们来说一下刚刚的sql语句有什么用,我们打开我们的后台数据库。
    在这里插入图片描述
    你会发现这个菜单其实是写在了数据库里面的,是动态渲染出来的,所以那个sql就是做这个事情的,把菜单写在了表里面,但是为什么不直接用那个sql要自己手动创建呢,很简单,我们看一下那个sql语句你就明白了。
    在这里插入图片描述
    它生成的一些菜单名字是按照字段来的。这个肯定是不能直接用的。

    我们在生成一下菜单,这里注意我填写的菜单路由。
    在这里插入图片描述
    然后刷新一下,页面会显示,然后数据库里面也会有对应的记录。
    在这里插入图片描述

    数据库显示:
    在这里插入图片描述

    创建页面

    之后我们创建页面,我们刚刚填写的路由是blog/blog 所以我们找到/views/modules然后创建blog文件夹blog.vue。
    在这里插入图片描述

    这个vue里面不用填写name,也就是这样

    <template>
    <div>
      我是博客查看
    div>
    template>
    
    <script>
    export default {
    
    }
    script>
    
    <style scoped>
    
    style>
    
    

    然后你再看看页面:
    在这里插入图片描述

    使用自动生成页面

    这个时候你以为要自己写页面了嘛?有些确实是的,不过还记得我们先前生成的vue文件嘛。
    在这里插入图片描述
    每次,我们把这两个文件copy过来:
    在这里插入图片描述

    记住要对得到名字,也就是你的blog.vue的名字要对上,另一个弹窗的就无所谓了。

    然后效果出来了:
    在这里插入图片描述

    在这里插入图片描述

    页面修改

    然后咱们有两个点要做,第一个是列表的名字,然后是对应的后端请求地址。

    现在美化一下:
    在这里插入图片描述

    label的修改,没有注释就没有。
    在这里插入图片描述
    之后是请求地址修改,我这里的话按照网关的配置需要加上/blog前缀
    在这里插入图片描述
    这里的话,两个文件都要改一下。
    之后把服务打开,然后刷新页面就是这样的,咱们这块还没有数据:
    在这里插入图片描述

    后端搜索实现

    之后是后端的搜索实现。

    这里的话,我们主要一下前端的代码对应的逻辑是怎么写的,
    在这里插入图片描述

    所以我们回到对应的Blog对应的Service在后端。
    在这里插入图片描述
    所以我们只需要拿到key然后判断一下是不是空,如果不是的话就进行复杂查询就好了。

        @Override
        public PageUtils queryPage(Map<String, Object> params) {
    
            String key = (String) params.get("key");
    
            IPage<BlogEntity> page_params = new Query<BlogEntity>().getPage(params);
            QueryWrapper<BlogEntity> blogEntityQueryWrapper = new QueryWrapper<>();
    
            if(key!=null){
                blogEntityQueryWrapper.like("userid",key).or().
                        like("blogid",key).or().
                        like("user_nickname",key).or().
                        like("blog_title",key);
            }
            IPage<BlogEntity> page = this.page(
                    page_params,
                    blogEntityQueryWrapper
            );
    
            return new PageUtils(page);
        }
    
    

    这里按照你的业务来哈。

    然后我们验证一下,由于我这边是没有数据的,所以我用用户的这个模块来演示一下。
    在这里插入图片描述
    在这里插入图片描述
    然后后端输出了sql日志:
    在这里插入图片描述
    当然我这里是配置了一下,你要看日志自己配置一下。

    总结

    又水了一篇博客儿~
    当然那个开始页面的那个也能改
    在这里插入图片描述

    然后在这儿
    在这里插入图片描述

  • 相关阅读:
    【微知】RDMA和拥塞控制领域中的NP和RP是什么?
    一文搞清各种来源的wmts服务加载,告别ctrl+c,v
    Android切换主题生命周期流程与onSaveInstanceState和onRestoreInstanceState,Kotlin
    TIDB日期和时间类型
    微信小程序 doc
    网站如何才能不被黑,如何做好网络安全
    香橙派orangepi c#.net霍尔水流量计+485脉冲精准测水流量实操实例-
    音频编码格式介绍-AAC
    JMeter的基本使用
    弹性数据库连接池探活策略调研(三)——DBCP
  • 原文地址:https://blog.csdn.net/FUTEROX/article/details/126977137