《花100块做个摸鱼小网站! 》第六篇—将小网站部署到云服务器上

⭐️基础链接导航⭐️

服务器 → ☁️ 阿里云活动地址

看样例 → 🐟 摸鱼小网站地址

学代码 → 💻 源码库地址

一、前言

到这一篇我们终于把环境搭好,也做好了几个热搜小组件,为了让我们方便展示成果或者方便自己摸鱼,我们需要将这个小网站部署上云。整体流程并不复杂,但有很多个小细节。如果某个细节处理不当,可能会导致部署失败,因此这是一个不断尝试和调整的过程。基本流程包括:修改配置、打包、上传、运行和调试,然后反复进行,直到成功。

二、前端资源打包

1. 修改配置

找到apiService.js文件,将baseURL改成自己的服务器的IP地址,端口建议使用80,因为http协议默认端口是80,https协议默认端口是443,这个应该都知道吧,如下:

1// apiService.js 2import axios from "axios"; 3 4// 创建axios实例并配置基础URL 5const apiClient = axios.create({ 6 baseURL: "http://ip:80/api", 7 headers: { 8 "Content-Type": "application/json" 9 }, 10}); 11 12export default { 13 // 封装Get接口 14 get(fetchUrl) { 15 return apiClient.get(fetchUrl); 16 } 17};

找到vue.config.js文件,将下面的配置替换一下,主要用于优化打包出来的文件,将一些不必要的文件去掉,如下:

1const { defineConfig } = require('@vue/cli-service') 2module.exports = defineConfig({ 3 transpileDependencies: true, 4 // 去除Vue打包后js目录下生成的一些.map文件,用于加速生产环境构建。 5 productionSourceMap: false, 6 // 去除Vue打包后.css和.js文件名称中8位hash值,跟缓存有关;一般为true就行。 7 filenameHashing:false 8})

2. 执行打包命令

打开命令行,输入打包命令,如下:

1npm run build

打包结束后,会有一个dist文件夹,里面包括html、js、css等文件,如下:

3. 提供资源访问接口

summo-sbmy-start这个module的resources目录下创建一个static文件,把dist里面的内容复制进去(ps:不包括dist目录本身),如下:

在application.properties中添加thymeleaf配置,如下:

1spring.thymeleaf.prefix=classpath:/static/ 2spring.thymeleaf.suffix=.html 3spring.thymeleaf.mode=HTML

最后在在summo-sbmy-web这个module下创建IndexController.java,如下:

1package com.summo.sbmy.web.controller; 2 3import org.springframework.stereotype.Controller; 4import org.springframework.web.bind.annotation.GetMapping; 5 6@Controller 7public class IndexController { 8 9 @GetMapping("/") 10 public String index(){ 11 return "index"; 12 } 13} 14

这些做好之后,启动应用,访问http://localhost/,没有问题的话,应该就可以访问了。

如果你发现图标加载不出来,那可能是有个打包配置没有弄好,将<include>**/*.svg</include>这行配置放到summo-sbmy-start这个module的 <build>标签下,如下:

1<resources> 2 <resource> 3 <!-- 指定配置文件所在的resource目录 --> 4 <directory>src/main/resources</directory> 5 <includes> 6 <include>application.properties</include> 7 <include>logback-spring.xml</include> 8 <include>**/*.html</include> 9 <include>**/*.js</include> 10 <include>**/*.css</include> 11 <include>**/*.svg</include> 12 </includes> 13 <filtering>true</filtering> 14 </resource> 15 <resource> 16 <!-- 指定配置文件所在的resource目录 --> 17 <directory>src/main/resources</directory> 18 <includes> 19 <include>**/*.woff</include> 20 <include>**/*.ttf</include> 21 <include>**/*.xdb</include> 22 <include>**/*.jks</include> 23 <include>**/*.svg</include> 24 </includes> 25 <filtering>false</filtering> 26 </resource> 27</resources>

配置和接口都弄好之后,启动应用重新访问一下,这时应该就可以看到图标了。

三、后端应用打包

在打包上传之前我们先做一些小准备,打开我们的idea工具,找到插件管理,一般是File —> Settings —> Plugins,搜索Alibaba Cloud Toolkit,下载安装一下,如下:

下载安装好之后,有一个Alibaba Cloud View,这里可以直接连接到我们买的阿里云ECS服务器,如下:

这个插件可以上传文件,也可以直接打开终端,这样就不用下载专门的软件连接ECS了,很方便。

1. xxl-job应用部署

(1) 应用打包

找到Maven插件,执行package命令,如下:

打包出来,如下:

(2) 应用上传

使用刚才下载的阿里云插件,可以直接将打包出来的jar包上传到指定的目录,我设置的是/home/admin/xxl-job,如下:

上传后,打开终端,可以启动一下,看看有没有问题,如下:

(3) 执行脚本

在我们使用SpringBoot框架开发完一个项目后,需要将该项目打成jar包,放到用于生产的服务器上去运行。一般都是执行 java -jar xxx.jar &命令运行,但是这样是有问题的。

比如启动时需要加入参数,如-Dxxx=xxx,这个命令就会很长不易读且容易忘。所以,最好是使用shell脚本将配置与命令维护起来。

新建一个shell脚本,名为start.sh,如下:

1#!/bin/bash 2#这里可替换为你自己的执行程序,其他代码无需更改 3APP_NAME=xxx.jar 4 5#使用说明,用来提示输入参数 6usage() { 7 echo "Usage: sh 脚本名.sh [start|stop|restart|status]" 8 exit 1 9} 10 11#检查程序是否在运行 12is_exist(){ 13 pid=`ps -ef|grep $APP_NAME|grep -v grep|awk '{print $2}' ` 14 #如果不存在返回1,存在返回0 15 if [ -z "${pid}" ]; then 16 return 1 17 else 18 return 0 19 fi 20} 21 22#启动方法 23start(){ 24 is_exist 25 if [ $? -eq "0" ]; then 26 echo "${APP_NAME} is already running. pid=${pid} ." 27 else 28 nohup java -jar /home/admin/$APP_NAME > /dev/null 2>&1 & 29 echo "${APP_NAME} start success" 30 fi 31} 32 33#停止方法 34stop(){ 35 is_exist 36 if [ $? -eq "0" ]; then 37 kill -9 $pid 38 else 39 echo "${APP_NAME} is not running" 40 fi 41} 42 43#输出运行状态 44status(){ 45 is_exist 46 if [ $? -eq "0" ]; then 47 echo "${APP_NAME} is running. Pid is ${pid}" 48 else 49 echo "${APP_NAME} is NOT running." 50 fi 51} 52 53#重启 54restart(){ 55 stop 56 start 57} 58 59#根据输入参数,选择执行对应方法,不输入则执行使用说明 60case "$1" in 61 "start") 62 start 63 ;; 64 "stop") 65 stop 66 ;; 67 "status") 68 status 69 ;; 70 "restart") 71 restart 72 ;; 73 *) 74 usage 75 ;; 76esac

使用方式如下:

  • 给start.sh文件授权:chmod 744 start.sh
  • 启动服务,在当前目录下执行:./start.sh start
  • 关闭服务,在当前目录下执行:./start.sh stop
  • 重启服务,在当前目录下执行:./start.sh restart
  • 查看服务状态,在当前目录下执行:./start.sh status

2. summo-sbmy应用部署

打包、上传、启动和上面的xxl-job应用一样的步骤,我就不赘述了。

这里说一点别的:在打包时如何指定配置文件?

就是开发的时候我们一般会有两个配置文件(或者更多):日常的application-dev.properties;线上的application-publish.properties。这两个文件配置是一样的,但是使用的资源不同,开发和线上的MySQL、Redis等资源是两套,就像这样,如下:

这里可能有同学有疑惑,既然有了日常和线上环境的配置文件,为啥还要有application.properties这个文件? 这里的application.properties我们可以当做是一个配置文件容器,它可以将其他配置文件的内容加到这里来。还有一个原因就是因为SpringBoot项目启动的时候只认识application.properties文件,不认识其他的。

(1) 环境配置区分

首先我们在这个module下添加环境配置,如下:

1 <!-- 添个环境的变量,变量名为environment --> 2<profiles> 3 <profile> 4 <id>dev</id> 5 <activation> 6 <activeByDefault>true</activeByDefault> 7 </activation> 8 <properties> 9 <environment>dev</environment> 10 </properties> 11 </profile> 12 <profile> 13 <id>publish</id> 14 <properties> 15 <environment>publish</environment> 16 </properties> 17 </profile> 18</profiles> 19 20<build> 21 <finalName>summo-sbmy</finalName> 22 <resources> 23 <resource> 24 <!-- 指定配置文件所在的resource目录 --> 25 <directory>src/main/resources</directory> 26 <includes> 27 <include>application.properties</include> 28 <include>application-${environment}.properties</include> 29 </includes> 30 <filtering>true</filtering> 31 </resource> 32 ... 其他配置 33 </resources> 34</build>

刷新一下Maven插件,这两个配置就会被扫描到了,如下:

(2) 使用spring.profiles.active指定环境

在application.properties文件中加入spring.profiles.active=@environment@配置,将那些不变的配置也可以放进来,如下:

1#通过配置的方式激活环境 2spring.profiles.active=@environment@ 3 4# 项目名称 5spring.application.name=summo-sbmy 6# 服务器端口 7server.port=80 8 9# 资源扫描配置 10spring.thymeleaf.prefix=classpath:/static/ 11spring.thymeleaf.suffix=.html 12spring.thymeleaf.mode=HTML 13 14# Mybatis自动映射 15mybatis.configuration.auto-mapping-behavior=full 16# Mybatis自动映射下划线到驼峰格式 17mybatis.configuration.map-underscore-to-camel-case=true 18# MyBatis-Plus Mapper的XML映射文件路径 19mybatis-plus.mapper-locations=classpath*:/mybatis/mapper/*.xml 20

(3) 打包命令

  • 日常环境打包指令
1mvn clean package -Dmaven.test.skip=true -P=daily
  • 正式环境打包指令
mvn clean package -Dmaven.test.skip=true -P=publish

四、小结一下

上面说的在打包时指定配置文件,如果大家嫌麻烦的话,也可以只用一份application.properties文件,省的麻烦。我是开发环境和线上环境的数据库是两套,所以使用不同的配置文件。

包打好之后上传到云服务器这一步不难,启动方式建议使用我推荐的start.sh脚本,这个应该也不难。阿里云ECS的安全组规则好像默认对80、443端口是全量放开的,所以只要你启动没有什么问题的话,在浏览器输入你的机器公网IP就可以访问达到你的小网站了。

因为部署的细节比较多,可能大家会出现这样那样的问题,如果有问题的话,欢迎评论区留言。

番外:百度贴吧热榜爬虫

1. 爬虫方案评估

百度贴吧热榜是这样的, 接口是:https://tieba.baidu.com/hottopic/browse/topicList?res_type=1

这又是一个网页版热搜榜,网页版的数据解析需要用户到jsoup,这个工具的使用在前面已经说过了,我直接放代码了。

2. 网页解析代码

TiebaHotSearchJob.java

1package com.summo.sbmy.job.tieba; 2 3import java.io.IOException; 4import java.net.URI; 5import java.net.URLDecoder; 6import java.nio.charset.StandardCharsets; 7import java.util.Calendar; 8import java.util.HashMap; 9import java.util.List; 10import java.util.Map; 11import java.util.stream.Collectors; 12 13import javax.annotation.PostConstruct; 14 15import com.google.common.collect.Lists; 16import com.summo.sbmy.common.model.dto.HotSearchDetailDTO; 17import com.summo.sbmy.dao.entity.SbmyHotSearchDO; 18import com.summo.sbmy.service.SbmyHotSearchService; 19import com.summo.sbmy.service.convert.HotSearchConvert; 20import com.xxl.job.core.biz.model.ReturnT; 21import com.xxl.job.core.handler.annotation.XxlJob; 22import lombok.extern.slf4j.Slf4j; 23import org.apache.commons.collections4.CollectionUtils; 24import org.apache.commons.lang3.StringUtils; 25import org.jsoup.Jsoup; 26import org.jsoup.nodes.Document; 27import org.jsoup.select.Elements; 28import org.springframework.beans.factory.annotation.Autowired; 29import org.springframework.stereotype.Component; 30 31import static com.summo.sbmy.common.cache.SbmyHotSearchCache.CACHE_MAP; 32import static com.summo.sbmy.common.enums.HotSearchEnum.TIEBA; 33 34/** 35 * @author summo 36 * @version DouyinHotSearchJob.java, 1.0.0 37 * @description 贴吧热搜Java爬虫代码 38 * @date 2024年08月09 39 */ 40@Component 41@Slf4j 42public class TiebaHotSearchJob { 43 44 @Autowired 45 private SbmyHotSearchService sbmyHotSearchService; 46 47 @PostConstruct 48 public void init() { 49 try { 50 // 调用 hotSearch 方法 51 hotSearch(null); 52 } catch (IOException e) { 53 log.error("启动时调用热搜爬虫任务异常", e); 54 } 55 } 56 57 @XxlJob("tiebaHotSearchJob") 58 public ReturnT<String> hotSearch(String param) throws IOException { 59 log.info("贴吧热搜爬虫任务开始"); 60 try { 61 String url = "https://tieba.baidu.com/hottopic/browse/topicList?res_type=1"; 62 List<SbmyHotSearchDO> sbmyHotSearchDOList = Lists.newArrayList(); 63 Document doc = Jsoup.connect(url).get(); 64 //标题 65 Elements titles = doc.select(".topic-top-item-desc"); 66 //热搜链接 67 Elements urls = doc.select(".topic-text"); 68 //热搜指数 69 Elements levels = doc.select(".topic-num"); 70 for (int i = 0; i < levels.size(); i++) { 71 SbmyHotSearchDO sbmyHotSearchDO = SbmyHotSearchDO.builder().hotSearchResource(TIEBA.getCode()).build(); 72 //设置文章标题 73 sbmyHotSearchDO.setHotSearchTitle(titles.get(i).text().trim()); 74 //设置文章连接 75 sbmyHotSearchDO.setHotSearchUrl(urls.get(i).attr("href")); 76 //设置知乎三方ID 77 sbmyHotSearchDO.setHotSearchId(getValueFromUrl(sbmyHotSearchDO.getHotSearchUrl(), "topic_id")); 78 //设置热搜热度 79 sbmyHotSearchDO.setHotSearchHeat(levels.get(i).text().trim().replace("W实时讨论", "") + "万"); 80 //按顺序排名 81 sbmyHotSearchDO.setHotSearchOrder(i + 1); 82 sbmyHotSearchDOList.add(sbmyHotSearchDO); 83 } 84 if (CollectionUtils.isEmpty(sbmyHotSearchDOList)) { 85 return ReturnT.SUCCESS; 86 } 87 //数据加到缓存中 88 CACHE_MAP.put(TIEBA.getCode(), HotSearchDetailDTO.builder() 89 //热搜数据 90 .hotSearchDTOList( 91 sbmyHotSearchDOList.stream().map(HotSearchConvert::toDTOWhenQuery).collect(Collectors.toList())) 92 //更新时间 93 .updateTime(Calendar.getInstance().getTime()).build()); 94 //数据持久化 95 sbmyHotSearchService.saveCache2DB(sbmyHotSearchDOList); 96 log.info("贴吧热搜爬虫任务结束"); 97 } catch (IOException e) { 98 log.error("获取贴吧数据异常", e); 99 } 100 return ReturnT.SUCCESS; 101 } 102 103 /** 104 * 从链接中获取参数 105 * 106 * @param url 链接 107 * @param param 想要提取出值的参数 108 * @return 109 * @throws Exception 110 */ 111 public static String getValueFromUrl(String url, String param) { 112 if (StringUtils.isAnyBlank(url, param)) { 113 throw new RuntimeException("从链接中获取参数异常,url或param为空"); 114 } 115 try { 116 URI uri = new URI(url); 117 String query = uri.getQuery(); 118 Map<String, String> queryPairs = new HashMap<>(); 119 String[] pairs = query.split("&"); 120 for (String pair : pairs) { 121 int idx = pair.indexOf("="); 122 String key = URLDecoder.decode(pair.substring(0, idx), StandardCharsets.UTF_8.name()); 123 String value = URLDecoder.decode(pair.substring(idx + 1), StandardCharsets.UTF_8.name()); 124 queryPairs.put(key, value); 125 } 126 return queryPairs.get(param); 127 } catch (Exception e) { 128 log.error("提取参数发生异常", e); 129 throw new RuntimeException("从链接中获取参数异常"); 130 } 131 } 132} 133
点赞
收藏

评论区

加载中...

相关推荐

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

springboot2之优雅处理返回值

前言最近项目组有个老项目要进行前后端分离改造,应前端同学的要求,其后端提供的返回值格式需形如{"status":0,"message":"success","data":{}}方便前端数据处理。要实现前端同学这个需求,其实也挺简单的,

京东小程序CI工具实践

本文从整体介绍了京东小程序CI工具的用途及工作流程,读者可以通过本文了解到一种全新的京东小程序上传方式,同时结合构建脚本和流水线,可大大提高小程序的部署和发布效率。

Jenkins+Ansible+Gitlab自动化部署三剑客

JenkinsAnsibleGitlab自动化部署三剑客小中大showerlee2016031113:00Ansible(https://www.oschina.net/action/GoToLink?urlhttp%3A%2F%2Fwww.

Color Hunt 漂亮炫酷的配色小程序

利用自己的业余时间,开发了一款颜色配色方案的小程序ColorHunt。小程序主要参考ColorHunt(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fcolorhunt.co%2F)这个网站,这个网站设计真的很棒,个人也经常用,所以小程序也秉承网站的风格,没有做调整,

《花100块做个摸鱼小网站! 》第五篇—通过xxl-job定时获取热搜数据

我们已经成功实现了一个完整的热搜组件,从后端到前端,构建了这个小网站的核心功能。接下来,我们将不断完善其功能,使其更加美观和实用。今天的主题是如何定时获取热搜数据。如果热搜数据无法定时更新,小网站将失去其核心价值。之前,我采用了@Scheduled注解来实现定时任务,但这种方式灵活性不足,因此我决定用更灵活的XXLJob组件来替代它。