前言

老规矩,冒个泡,不知道为啥最近也是懒,一点点动力都没有了,可能是由于几个星星导致的精神萎靡吧,也可能是财富岛太迷人了。那么今天也是带来第二个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.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.3.2.RELEASE</version>
		<relativePath   />
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
		<mybatisplus.version>3.3.1</mybatisplus.version>
		<mysql.version>8.0.28</mysql.version>
		<mssql.version>4.0</mssql.version>
		<oracle.version>11.2.0.3</oracle.version>
		<druid.version>1.1.13</druid.version>
		<quartz.version>2.3.0</quartz.version>
		<commons.lang.version>2.6</commons.lang.version>
		<commons.fileupload.version>1.2.2</commons.fileupload.version>
		<commons.io.version>2.5</commons.io.version>
		<commons.codec.version>1.10</commons.codec.version>
		<commons.configuration.version>1.10</commons.configuration.version>
		<shiro.version>1.9.0</shiro.version>
		<jwt.version>0.7.0</jwt.version>
		<kaptcha.version>0.0.9</kaptcha.version>
		<qiniu.version>7.2.23</qiniu.version>
		<aliyun.oss.version>2.8.3</aliyun.oss.version>
		<qcloud.cos.version>4.4</qcloud.cos.version>
		<swagger.version>2.7.0</swagger.version>
		<joda.time.version>2.9.9</joda.time.version>
		<gson.version>2.8.5</gson.version>
		<fastjson.version>1.2.79</fastjson.version>
		<hutool.version>4.1.1</hutool.version>
		<lombok.version>1.18.4</lombok.version>

		<!--wagon plugin 配置-->
		<service-path>/work/renren</service-path>
		<pack-name>${project.artifactId}-${project.version}.jar</pack-name>
		<remote-addr>192.168.1.10:22</remote-addr>
		<remote-username>root</remote-username>
		<remote-passwd>123456</remote-passwd>
	</properties>

	<dependencies>

		<dependency>
			<groupId>com.huterox.whitehole.common</groupId>
			<artifactId>whiteholo-common</artifactId>
			<version>0.0.1-SNAPSHOT</version>
		</dependency>


		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-aop</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context-support</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-redis</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-validation</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-configuration-processor</artifactId>
			<optional>true</optional>
		</dependency>
		<!--<dependency>-->
		<!--<groupId>org.springframework.boot</groupId>-->
		<!--<artifactId>spring-boot-devtools</artifactId>-->
		<!--<optional>true</optional>-->
		<!--</dependency>-->
		<dependency>
			<groupId>com.baomidou</groupId>
			<artifactId>mybatis-plus-boot-starter</artifactId>
			<version>${mybatisplus.version}</version>
			<exclusions>
				<exclusion>
					<groupId>com.baomidou</groupId>
					<artifactId>mybatis-plus-generator</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>${mysql.version}</version>
		</dependency>
		<!--oracle驱动-->
		<dependency>
			<groupId>com.oracle</groupId>
			<artifactId>ojdbc6</artifactId>
			<version>${oracle.version}</version>
		</dependency>
		<!--mssql驱动-->
		<dependency>
			<groupId>com.microsoft.sqlserver</groupId>
			<artifactId>sqljdbc4</artifactId>
			<version>${mssql.version}</version>
		</dependency>
		<!--postgresql驱动-->
		<dependency>
			<groupId>org.postgresql</groupId>
			<artifactId>postgresql</artifactId>
		</dependency>
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>druid-spring-boot-starter</artifactId>
			<version>${druid.version}</version>
		</dependency>
		<dependency>
			<groupId>org.quartz-scheduler</groupId>
			<artifactId>quartz</artifactId>
			<version>${quartz.version}</version>
			<exclusions>
				<exclusion>
					<groupId>com.mchange</groupId>
					<artifactId>c3p0</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>commons-lang</groupId>
			<artifactId>commons-lang</artifactId>
			<version>${commons.lang.version}</version>
		</dependency>
		<dependency>
			<groupId>commons-fileupload</groupId>
			<artifactId>commons-fileupload</artifactId>
			<version>${commons.fileupload.version}</version>
		</dependency>
		<dependency>
			<groupId>commons-io</groupId>
			<artifactId>commons-io</artifactId>
			<version>${commons.io.version}</version>
		</dependency>
		<dependency>
			<groupId>commons-codec</groupId>
			<artifactId>commons-codec</artifactId>
			<version>${commons.codec.version}</version>
		</dependency>
		<dependency>
			<groupId>commons-configuration</groupId>
			<artifactId>commons-configuration</artifactId>
			<version>${commons.configuration.version}</version>
		</dependency>
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-core</artifactId>
			<version>${shiro.version}</version>
		</dependency>
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-spring</artifactId>
			<version>${shiro.version}</version>
		</dependency>
		<dependency>
			<groupId>io.jsonwebtoken</groupId>
			<artifactId>jjwt</artifactId>
			<version>${jwt.version}</version>
		</dependency>
		<dependency>
			<groupId>com.github.axet</groupId>
			<artifactId>kaptcha</artifactId>
			<version>${kaptcha.version}</version>
		</dependency>
		<dependency>
			<groupId>io.springfox</groupId>
			<artifactId>springfox-swagger2</artifactId>
			<version>${swagger.version}</version>
		</dependency>
		<dependency>
			<groupId>io.springfox</groupId>
			<artifactId>springfox-swagger-ui</artifactId>
			<version>${swagger.version}</version>
		</dependency>
		<dependency>
			<groupId>com.qiniu</groupId>
			<artifactId>qiniu-java-sdk</artifactId>
			<version>${qiniu.version}</version>
		</dependency>
		<dependency>
			<groupId>com.aliyun.oss</groupId>
			<artifactId>aliyun-sdk-oss</artifactId>
			<version>${aliyun.oss.version}</version>
		</dependency>
		<dependency>
			<groupId>com.qcloud</groupId>
			<artifactId>cos_api</artifactId>
			<version>${qcloud.cos.version}</version>
			<exclusions>
				<exclusion>
					<groupId>org.slf4j</groupId>
					<artifactId>slf4j-log4j12</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>joda-time</groupId>
			<artifactId>joda-time</artifactId>
			<version>${joda.time.version}</version>
		</dependency>
		<dependency>
			<groupId>com.google.code.gson</groupId>
			<artifactId>gson</artifactId>
			<version>${gson.version}</version>
		</dependency>
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>fastjson</artifactId>
			<version>${fastjson.version}</version>
		</dependency>
		<dependency>
			<groupId>cn.hutool</groupId>
			<artifactId>hutool-all</artifactId>
			<version>${hutool.version}</version>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<version>${lombok.version}</version>
		</dependency>
	</dependencies>

	<build>
		<finalName>${project.artifactId}</finalName>
		<extensions>
			<extension>
				<groupId>org.apache.maven.wagon</groupId>
				<artifactId>wagon-ssh</artifactId>
				<version>2.8</version>
			</extension>
		</extensions>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
				<configuration>
					<fork>true</fork>
				</configuration>
			</plugin>
			<!-- 跳过单元测试 -->
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-surefire-plugin</artifactId>
				<configuration>
					<skipTests>true</skipTests>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.codehaus.mojo</groupId>
				<artifactId>wagon-maven-plugin</artifactId>
				<version>1.0</version>
				<configuration>
					<fromFile>target/${pack-name}</fromFile>
					<url><![CDATA[scp://${remote-username}:${remote-passwd}@${remote-addr}${service-path}]]></url>
					<commands>
						<!-- Kill Old Process -->
						<command>kill -9 `ps -ef |grep ${project.artifactId}.jar|grep -v "grep" |awk '{print $2}'`</command>
						<!-- Restart jar package,write result into renren.log -->
						<command><![CDATA[nohup java -jar ${service-path}/${pack-name} --spring.profiles.active=test > ${service-path}/renren.log 2>&1 & ]]></command>
						<command><![CDATA[netstat -nptl]]></command>
						<command><![CDATA[ps -ef | grep java | grep -v grep]]></command>
					</commands>
					<!-- 运行命令 mvn clean package wagon:upload-single wagon:sshexec-->
					<displayCommandOutputs>true</displayCommandOutputs>
				</configuration>
			</plugin>

			<plugin>
				<groupId>com.spotify</groupId>
				<artifactId>docker-maven-plugin</artifactId>
				<version>0.4.13</version>
				<!--<executions>-->
				<!--<execution>-->
				<!--<phase>package</phase>-->
				<!--<goals>-->
				<!--<goal>build</goal>-->
				<!--</goals>-->
				<!--</execution>-->
				<!--</executions>-->
				<configuration>
					<imageName>renren/fast</imageName>
					<dockerDirectory>${project.basedir}</dockerDirectory>
					<resources>
						<resource>
							<targetPath>/</targetPath>
							<directory>${project.build.directory}</directory>
							<include>${project.build.finalName}.jar</include>
						</resource>
					</resources>
				</configuration>
				<!-- 运行命令 mvn clean package docker:build 打包并生成docker镜像 -->
			</plugin>
		</plugins>
	</build>

	<repositories>
		<repository>
			<id>public</id>
			<name>aliyun nexus</name>
			<url>https://maven.aliyun.com/repository/public/</url>
			<releases>
				<enabled>true</enabled>
			</releases>
		</repository>
	</repositories>
	<pluginRepositories>
		<pluginRepository>
			<id>public</id>
			<name>aliyun nexus</name>
			<url>https://maven.aliyun.com/repository/public/</url>
			<releases>
				<enabled>true</enabled>
			</releases>
			<snapshots>
				<enabled>false</enabled>
			</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>.*),/$\{segment}

        - id: blog8050
          uri: lb://blog
          predicates:
            - Path=/api/blog/**
          filters:
            - RewritePath=/api/blog/(?<segment>.*),/$\{segment}

        - id: community8100
          uri: lb://community
          predicates:
            - Path=/api/community/**
          filters:
            - RewritePath=/api/community/(?<segment>.*),/$\{segment}

        - id: hole8150
          uri: lb://hole
          predicates:
            - Path=/api/hole/**
          filters:
            - RewritePath=/api/hole/(?<segment>.*),/$\{segment}


        - id: quiz8200
          uri: lb://quiz
          predicates:
            - Path=/api/quiz/**
          filters:
            - RewritePath=/api/quiz/(?<segment>.*),/$\{segment}

        - id: user8250
          uri: lb://user
          predicates:
            - Path=/api/user/**
          filters:
            - RewritePath=/api/user/(?<segment>.*),/$\{segment}


        - id: admin_route
          uri: lb://renren-fast  # 网关负载均衡的发送到renren-fast
          predicates:
            - Path=/api/**
          filters:
            - RewritePath=/api/(?<segment>.*),/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日志:
在这里插入图片描述
当然我这里是配置了一下,你要看日志自己配置一下。

总结

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

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

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐