mirror of
https://github.com/201206030/novel-plus.git
synced 2025-07-01 07:16:39 +00:00
Compare commits
15 Commits
release_v2
...
release_v2
Author | SHA1 | Date | |
---|---|---|---|
0e2e6229cd | |||
f8a669eb01 | |||
6d56399d0f | |||
1a0c1f864b | |||
b193aca288 | |||
7a6d7a4442 | |||
5505840b6e | |||
8eb3048b91 | |||
1b138c2aad | |||
f5e2dbaa6b | |||
b6cb9aaedc | |||
f9f1e474ec | |||
06bf848e99 | |||
6e171d20ed | |||
c62acc288e |
17
README.md
17
README.md
@ -1,7 +1,15 @@
|
||||
[](https://cloud.tencent.com/act/cps/redirect?redirect=1052&cps_key=736e609d66e0ac4e57813316cec6fd0b&from=console)
|
||||
[]( https://www.eve.bz/cart.php?gid=11 )
|
||||
|
||||
# 小说精品屋-plus
|
||||
|
||||
#### 新项目:小说精品屋-微服务版
|
||||
|
||||
基于小说精品屋-plus构建的Spring Cloud 微服务小说门户平台,可用于学习和商用。
|
||||
|
||||
Gitee仓库地址: https://gitee.com/xiongxyang/novel-cloud
|
||||
|
||||
GitHub仓库地址: https://github.com/201206030/novel-cloud
|
||||
|
||||
#### 演示地址
|
||||
|
||||
[点击前往](http://www.java2nb.com)(前台门户)
|
||||
@ -48,14 +56,17 @@ novel-plus -- 父工程
|
||||
| MyBatis Dynamic SQL | Mybatis动态sql
|
||||
| PageHelper | MyBatis分页插件
|
||||
| MyBatisGenerator | 持久层代码生成插件
|
||||
| Sharding-Jdbc | 代码层分库分表中间件
|
||||
| JJWT | JWT登录支持
|
||||
| SpringSecurity | 安全框架
|
||||
| Shiro | 安全框架
|
||||
| Ehcache | Java进程内缓存框架(默认缓存)
|
||||
| Redis | 分布式缓存(缓存替换方案,默认关闭,一行配置开启)
|
||||
| ElasticSearch | 搜索引擎(搜索增强方案,默认关闭,一行配置开启)
|
||||
| RabbitMq | 消息队列(流量削峰,默认关闭,一行配置开启)
|
||||
| Redisson | 实现分布式锁
|
||||
| RabbitMq | 消息队列(流量削峰,默认关闭,一行配置开启)
|
||||
| OSS | 阿里云对象存储服务(图片存储方式之一,一行配置即可切换)
|
||||
| FastDfs |开源轻量级分布式文件系统(图片存储方式之一,一行配置即可切换)
|
||||
| Redisson | 实现分布式锁
|
||||
| Lombok | 简化对象封装工具
|
||||
| Docker | 应用容器引擎
|
||||
| Mysql | 数据库服务
|
||||
|
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>novel</artifactId>
|
||||
<groupId>com.java2nb</groupId>
|
||||
<version>2.1.2</version>
|
||||
<version>2.5.1</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@ -57,6 +57,22 @@
|
||||
<version>${mybatis.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 分库分表-->
|
||||
<!-- sharding jdbc依赖 -->
|
||||
|
||||
<dependency>
|
||||
<groupId>io.shardingsphere</groupId>
|
||||
<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
|
||||
<version>${sharding.jdbc.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.shardingsphere</groupId>
|
||||
<artifactId>sharding-jdbc-spring-namespace</artifactId>
|
||||
<version>${sharding.jdbc.version}</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!--分页助手启动器-->
|
||||
<dependency>
|
||||
<groupId>com.github.pagehelper</groupId>
|
||||
|
@ -24,7 +24,7 @@ public final class BookContentDynamicSqlSupport {
|
||||
|
||||
public final SqlColumn<Long> indexId = column("index_id", JDBCType.BIGINT);
|
||||
|
||||
public final SqlColumn<String> content = column("content", JDBCType.LONGVARCHAR);
|
||||
public final SqlColumn<String> content = column("content", JDBCType.VARCHAR);
|
||||
|
||||
public BookContent() {
|
||||
super("book_content");
|
||||
|
@ -63,7 +63,7 @@ public interface BookContentMapper {
|
||||
@Results(id="BookContentResult", value = {
|
||||
@Result(column="id", property="id", jdbcType=JdbcType.BIGINT, id=true),
|
||||
@Result(column="index_id", property="indexId", jdbcType=JdbcType.BIGINT),
|
||||
@Result(column="content", property="content", jdbcType=JdbcType.LONGVARCHAR)
|
||||
@Result(column="content", property="content", jdbcType=JdbcType.VARCHAR)
|
||||
})
|
||||
List<BookContent> selectMany(SelectStatementProvider selectStatement);
|
||||
|
||||
|
@ -1,11 +1,8 @@
|
||||
spring:
|
||||
profiles:
|
||||
include: [common]
|
||||
datasource:
|
||||
url: jdbc:mysql://127.0.0.1:3306/novel_plus?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
|
||||
username: root
|
||||
password:
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
main:
|
||||
allow-bean-definition-overriding: true
|
||||
#Redis服务器IP
|
||||
redis:
|
||||
host: 127.0.0.1
|
||||
@ -25,12 +22,58 @@ spring:
|
||||
min-idle: 0
|
||||
#连接超时时间(毫秒)
|
||||
timeout: 30000
|
||||
datasource:
|
||||
url: jdbc:mysql://127.0.0.1:3306/novel_plus?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
|
||||
username: root
|
||||
password: test123456
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
|
||||
####使用shardingJdbc时,
|
||||
####所有的jdbcType都不能是LONGVARCHAR,否则会导致java.io.NotSerializableException: java.io.StringReader错误
|
||||
##### 应该替换所有的 LONGVARCHAR 类型为VARCHAR
|
||||
|
||||
sharding:
|
||||
jdbc:
|
||||
datasource:
|
||||
names: ds0 #,ds1
|
||||
ds0:
|
||||
type: com.zaxxer.hikari.HikariDataSource
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
jdbc-url: jdbc:mysql://localhost:3306/novel_plus?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
|
||||
username: root
|
||||
password: test123456
|
||||
# ds1:
|
||||
# type: com.alibaba.druid.pool.DruidDataSource
|
||||
# driver-class-name: com.mysql.jdbc.Driver
|
||||
# url: jdbc:mysql://localhost:3306/novel_plus2
|
||||
# username: root
|
||||
# password: test123456
|
||||
config:
|
||||
sharding:
|
||||
props:
|
||||
sql.show: true
|
||||
tables:
|
||||
book_content: #book_content表
|
||||
key-generator-column-name: id #主键
|
||||
actual-data-nodes: ds${0}.book_content${0..9} #数据节点
|
||||
# database-strategy: #分库策略
|
||||
# inline:
|
||||
# sharding-column: book_id
|
||||
# algorithm-expression: ds${book_id % 10}
|
||||
table-strategy: #分表策略
|
||||
inline:
|
||||
shardingColumn: index_id
|
||||
algorithm-expression: book_content${index_id % 10}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
pic:
|
||||
save:
|
||||
type: 2 #图片保存方式, 1不保存,使用网络图片 ,2本地保存
|
||||
type: 2 #图片保存方式, 1不保存,使用爬取的网络图片 ,2保存在自己的存储介质
|
||||
storage: local #存储介质,local:本地,OSS:阿里云对象存储,fastDfs:分布式文件系统
|
||||
path: /var/pic #图片保存路径
|
||||
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>novel</artifactId>
|
||||
<groupId>com.java2nb</groupId>
|
||||
<version>2.1.2</version>
|
||||
<version>2.5.1</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@ -25,6 +25,8 @@
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
@ -96,8 +96,12 @@ public class CrawlParser {
|
||||
|
||||
String desc = bookDetailHtml.substring(bookDetailHtml.indexOf(ruleBean.getDescStart()) + ruleBean.getDescStart().length());
|
||||
desc = desc.substring(0, desc.indexOf(ruleBean.getDescEnd()));
|
||||
//过滤掉简介中的a标签
|
||||
desc = desc.replaceAll("<a[^<]+</a>","");
|
||||
//过滤掉简介中的特殊标签
|
||||
desc = desc.replaceAll("<a[^<]+</a>","")
|
||||
.replaceAll("<font[^<]+</font>","")
|
||||
.replaceAll("<p>\\s*</p>","")
|
||||
.replaceAll("<p>","")
|
||||
.replaceAll("</p>","<br/>");
|
||||
//设置书籍简介
|
||||
book.setBookDesc(desc);
|
||||
if (StringUtils.isNotBlank(ruleBean.getStatusPatten())) {
|
||||
|
@ -61,7 +61,7 @@ public class StarterListener implements ServletContextListener {
|
||||
Book book = CrawlParser.parseBook(ruleBean, needUpdateBook.getCrawlBookId());
|
||||
//这里只做老书更新
|
||||
book.setId(needUpdateBook.getId());
|
||||
if(needUpdateBook.getPicUrl()!=null && needUpdateBook.getPicUrl().startsWith(Constants.LOCAL_PIC_PREFIX)) {
|
||||
if(needUpdateBook.getPicUrl()!=null && needUpdateBook.getPicUrl().contains(Constants.LOCAL_PIC_PREFIX)) {
|
||||
//本地图片则不更新
|
||||
book.setPicUrl(null);
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>novel</artifactId>
|
||||
<groupId>com.java2nb</groupId>
|
||||
<version>2.1.2</version>
|
||||
<version>2.5.1</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@ -39,12 +39,33 @@
|
||||
<version>${jest.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!--aliyunOSS-->
|
||||
<dependency>
|
||||
<groupId>com.aliyun.oss</groupId>
|
||||
<artifactId>aliyun-sdk-oss</artifactId>
|
||||
<version>${aliyun-sdk-oss.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-fileupload</groupId>
|
||||
<artifactId>commons-fileupload</artifactId>
|
||||
<version>${commons-fileupload.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!--FastDfs-->
|
||||
<dependency>
|
||||
<groupId>com.github.tobato</groupId>
|
||||
<artifactId>fastdfs-client</artifactId>
|
||||
<version>${fastdfs-client.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
|
||||
|
||||
<!--引入redisson分布式锁-->
|
||||
<!-- <dependency>
|
||||
<groupId>org.redisson</groupId>
|
||||
@ -56,7 +77,7 @@
|
||||
<dependency>
|
||||
<groupId>com.alipay.sdk</groupId>
|
||||
<artifactId>alipay-sdk-java</artifactId>
|
||||
<version>4.9.153.ALL</version>
|
||||
<version>${alipay-sdk-java.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
@ -1,10 +1,13 @@
|
||||
package com.java2nb.novel;
|
||||
|
||||
import com.github.tobato.fastdfs.FdfsClientConfig;
|
||||
import io.shardingsphere.shardingjdbc.spring.boot.SpringBootConfiguration;
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cache.annotation.EnableCaching;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.scheduling.TaskScheduler;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
|
||||
@ -18,6 +21,7 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
@EnableScheduling
|
||||
@EnableCaching
|
||||
@MapperScan(basePackages = {"com.java2nb.novel.mapper"})
|
||||
@Import(FdfsClientConfig.class)
|
||||
public class FrontNovelApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
@ -0,0 +1,13 @@
|
||||
package com.java2nb.novel.core.config;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.EnableMBeanExport;
|
||||
import org.springframework.jmx.support.RegistrationPolicy;
|
||||
|
||||
/**
|
||||
* @author 11797
|
||||
*/
|
||||
@Configuration
|
||||
@EnableMBeanExport(registration= RegistrationPolicy.IGNORE_EXISTING)
|
||||
public class FdfsConfiguration {
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package com.java2nb.novel.core.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @author 11797
|
||||
*/
|
||||
@Data
|
||||
@Component
|
||||
@ConfigurationProperties(prefix="novel.file")
|
||||
public class OssProperties{
|
||||
|
||||
private String endpoint;
|
||||
|
||||
private String keyId;
|
||||
|
||||
private String keySecret;
|
||||
|
||||
private String fileHost;
|
||||
|
||||
private String bucketName;
|
||||
|
||||
private String webUrl;
|
||||
|
||||
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package com.java2nb.novel.core.schedule;
|
||||
|
||||
import com.java2nb.novel.core.utils.Constants;
|
||||
import com.java2nb.novel.entity.Book;
|
||||
import com.java2nb.novel.service.BookService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@ -13,7 +14,7 @@ import org.springframework.stereotype.Service;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 网络图片转存本地任务
|
||||
* 将爬取的网络图片转存为自己的存储介质(本地、OSS、fastDfs)任务
|
||||
*
|
||||
* @author Administrator
|
||||
*/
|
||||
@ -21,7 +22,7 @@ import java.util.List;
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
public class Network2LocalPicSchedule {
|
||||
public class CrawlPicTransSchedule {
|
||||
|
||||
private final BookService bookService;
|
||||
|
||||
@ -41,7 +42,7 @@ public class Network2LocalPicSchedule {
|
||||
log.info("Network2LocalPicSchedule。。。。。。。。。。。。");
|
||||
|
||||
|
||||
List<Book> networkPicBooks = bookService.queryNetworkPicBooks(100);
|
||||
List<Book> networkPicBooks = bookService.queryNetworkPicBooks(Constants.LOCAL_PIC_PREFIX,100);
|
||||
for (Book book : networkPicBooks) {
|
||||
bookService.updateBookPicToLocal(book.getPicUrl(), book.getId());
|
||||
//3秒钟转化一张图片,10分钟转化200张
|
@ -12,7 +12,7 @@ public class Constants {
|
||||
public static final String TEMPLATE_PATH_PREFIX_KEY = "templatePathPrefixKey";
|
||||
|
||||
/**
|
||||
* 本地图片保存前缀
|
||||
* 保存图片到自己的存储介质路径前缀
|
||||
* */
|
||||
public static final String LOCAL_PIC_PREFIX = "/localPic/";
|
||||
|
||||
|
@ -22,7 +22,7 @@ public interface FrontBookMapper extends BookMapper {
|
||||
|
||||
void addCommentCount(@Param("bookId") Long bookId);
|
||||
|
||||
List<Book> queryNetworkPicBooks(@Param("limit") Integer limit);
|
||||
List<Book> queryNetworkPicBooks(@Param("localPicPrefix") String localPicPrefix, @Param("limit") Integer limit);
|
||||
|
||||
/**
|
||||
* 按评分随机查询小说集合
|
||||
|
@ -180,15 +180,17 @@ public interface BookService {
|
||||
|
||||
/**
|
||||
* 查询网络图片的小说
|
||||
*
|
||||
* @param localPicPrefix
|
||||
* @param limit 查询条数
|
||||
* @return 返回小说集合
|
||||
* */
|
||||
List<Book> queryNetworkPicBooks(Integer limit);
|
||||
List<Book> queryNetworkPicBooks(String localPicPrefix, Integer limit);
|
||||
|
||||
|
||||
/**
|
||||
* 更新小说网络图片到本地
|
||||
* @param picUrl 网络图片路径
|
||||
* 更新爬取的小说网络图片到自己的存储介质(本地、OSS、fastDfs)
|
||||
* @param picUrl 爬取的网络图片路径
|
||||
* @param bookId 小说ID
|
||||
*/
|
||||
void updateBookPicToLocal(String picUrl, Long bookId);
|
||||
@ -198,6 +200,7 @@ public interface BookService {
|
||||
* @param userId 用户ID
|
||||
* @param page 页码
|
||||
* @param pageSize 分页大小
|
||||
* @return 小说集合
|
||||
* */
|
||||
List<Book> listBookPageByUserId(Long userId, int page, int pageSize);
|
||||
|
||||
|
@ -0,0 +1,17 @@
|
||||
package com.java2nb.novel.service;
|
||||
|
||||
|
||||
/**
|
||||
* @author 11797
|
||||
*/
|
||||
public interface FileService {
|
||||
|
||||
/**
|
||||
* 将爬取的网络图片转存为自己的存储介质(本地、OSS、fastDfs)
|
||||
* @param picSrc 爬取的网络图片路径
|
||||
* @param picSavePath 保存路径
|
||||
* @return 新图片地址
|
||||
* */
|
||||
String transFile(String picSrc, String picSavePath);
|
||||
|
||||
}
|
@ -14,6 +14,7 @@ import com.java2nb.novel.mapper.*;
|
||||
import com.java2nb.novel.search.BookSP;
|
||||
import com.java2nb.novel.service.AuthorService;
|
||||
import com.java2nb.novel.service.BookService;
|
||||
import com.java2nb.novel.service.FileService;
|
||||
import com.java2nb.novel.service.SearchService;
|
||||
import com.java2nb.novel.vo.BookCommentVO;
|
||||
import com.java2nb.novel.vo.BookSettingVO;
|
||||
@ -82,6 +83,8 @@ public class BookServiceImpl implements BookService {
|
||||
|
||||
private final SearchService searchService;
|
||||
|
||||
private final FileService fileService;
|
||||
|
||||
|
||||
@SneakyThrows
|
||||
@Override
|
||||
@ -460,14 +463,14 @@ public class BookServiceImpl implements BookService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Book> queryNetworkPicBooks(Integer limit) {
|
||||
return bookMapper.queryNetworkPicBooks(limit);
|
||||
public List<Book> queryNetworkPicBooks(String localPicPrefix, Integer limit) {
|
||||
return bookMapper.queryNetworkPicBooks(localPicPrefix,limit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBookPicToLocal(String picUrl, Long bookId) {
|
||||
|
||||
picUrl = FileUtil.network2Local(picUrl, picSavePath, Constants.LOCAL_PIC_PREFIX);
|
||||
picUrl = fileService.transFile(picUrl, picSavePath);
|
||||
|
||||
bookMapper.update(update(book)
|
||||
.set(BookDynamicSqlSupport.picUrl)
|
||||
|
@ -0,0 +1,60 @@
|
||||
package com.java2nb.novel.service.impl;
|
||||
|
||||
import com.github.tobato.fastdfs.domain.StorePath;
|
||||
import com.github.tobato.fastdfs.service.FastFileStorageClient;
|
||||
import com.java2nb.novel.core.utils.Constants;
|
||||
import com.java2nb.novel.core.utils.FileUtil;
|
||||
import com.java2nb.novel.service.FileService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
|
||||
/**
|
||||
* @author 11797
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
@ConditionalOnProperty(prefix = "pic.save", name = "storage", havingValue = "fastDfs")
|
||||
public class FastDfsFileServiceImpl implements FileService {
|
||||
|
||||
private final FastFileStorageClient storageClient;
|
||||
|
||||
@Value("${fdfs.webUrl}")
|
||||
private String webUrl;
|
||||
|
||||
@Override
|
||||
public String transFile(String picSrc, String picSavePath) {
|
||||
|
||||
File file;
|
||||
String filePath = FileUtil.network2Local(picSrc, picSavePath, Constants.LOCAL_PIC_PREFIX);
|
||||
if (filePath.contains(Constants.LOCAL_PIC_PREFIX)) {
|
||||
file = new File(picSavePath + filePath);
|
||||
} else {
|
||||
//默认图片不存储
|
||||
return filePath;
|
||||
}
|
||||
|
||||
try {
|
||||
FileInputStream inputStream = new FileInputStream(file);
|
||||
StorePath storePath = storageClient.uploadFile(inputStream, file.length(),
|
||||
FilenameUtils.getExtension(file.getName()), null);
|
||||
//这里额外加上LOCAL_PIC_PREFIX路径,表明该图片是个人资源,而不是爬虫爬取的网络资源,不需要再次进行转换,
|
||||
// 实际访问时,再通过nginx的rewite指令来重写路径,去掉LOCAL_PIC_PREFIX
|
||||
return webUrl+Constants.LOCAL_PIC_PREFIX+storePath.getFullPath();
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
} finally {
|
||||
//删除
|
||||
file.delete();
|
||||
}
|
||||
|
||||
return "/images/default.gif";
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package com.java2nb.novel.service.impl;
|
||||
|
||||
import com.java2nb.novel.core.utils.Constants;
|
||||
import com.java2nb.novel.core.utils.FileUtil;
|
||||
import com.java2nb.novel.service.FileService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* @author 11797
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@ConditionalOnProperty(prefix = "pic.save", name = "storage", havingValue = "local")
|
||||
public class LocalFileServiceImpl implements FileService {
|
||||
|
||||
@Override
|
||||
public String transFile(String picSrc, String picSavePath){
|
||||
|
||||
return FileUtil.network2Local(picSrc, picSavePath, Constants.LOCAL_PIC_PREFIX);
|
||||
}
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
package com.java2nb.novel.service.impl;
|
||||
|
||||
import com.aliyun.oss.OSSClient;
|
||||
import com.aliyun.oss.model.CannedAccessControlList;
|
||||
import com.aliyun.oss.model.CreateBucketRequest;
|
||||
import com.aliyun.oss.model.PutObjectRequest;
|
||||
import com.aliyun.oss.model.PutObjectResult;
|
||||
import com.java2nb.novel.core.config.OssProperties;
|
||||
import com.java2nb.novel.core.utils.Constants;
|
||||
import com.java2nb.novel.core.utils.FileUtil;
|
||||
import com.java2nb.novel.service.FileService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* @author 11797
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@ConditionalOnProperty(prefix = "pic.save", name = "storage", havingValue = "OSS")
|
||||
@Slf4j
|
||||
public class OssFileServiceImpl implements FileService {
|
||||
|
||||
private final OssProperties ossProperties;
|
||||
|
||||
@Override
|
||||
public String transFile(String picSrc, String picSavePath) {
|
||||
|
||||
File file;
|
||||
String filePath = FileUtil.network2Local(picSrc, picSavePath, Constants.LOCAL_PIC_PREFIX);
|
||||
if (filePath.contains(Constants.LOCAL_PIC_PREFIX)) {
|
||||
file = new File(picSavePath+filePath);
|
||||
} else {
|
||||
//默认图片不存储
|
||||
return filePath;
|
||||
}
|
||||
|
||||
filePath = filePath.replaceFirst(picSavePath,"");
|
||||
|
||||
filePath = filePath.startsWith("/") ? filePath.replaceFirst("/","") : filePath;
|
||||
|
||||
|
||||
OSSClient ossClient = new OSSClient(ossProperties.getEndpoint(), ossProperties.getKeyId(), ossProperties.getKeySecret());
|
||||
try {
|
||||
//容器不存在,就创建
|
||||
if (!ossClient.doesBucketExist(ossProperties.getBucketName())) {
|
||||
ossClient.createBucket(ossProperties.getBucketName());
|
||||
CreateBucketRequest createBucketRequest = new CreateBucketRequest(ossProperties.getBucketName());
|
||||
createBucketRequest.setCannedACL(CannedAccessControlList.PublicRead);
|
||||
ossClient.createBucket(createBucketRequest);
|
||||
}
|
||||
//上传文件
|
||||
PutObjectResult result = ossClient.putObject(new PutObjectRequest(ossProperties.getBucketName(), filePath, file));
|
||||
//设置权限 这里是公开读
|
||||
ossClient.setBucketAcl(ossProperties.getBucketName(), CannedAccessControlList.PublicRead);
|
||||
|
||||
if(result != null) {
|
||||
return ossProperties.getWebUrl() + "/" + filePath;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
} finally {
|
||||
//关闭
|
||||
ossClient.shutdown();
|
||||
file.delete();
|
||||
}
|
||||
|
||||
return "/images/default.gif";
|
||||
}
|
||||
|
||||
|
||||
}
|
16
novel-front/src/main/resources/application-fastdfs.yml
Normal file
16
novel-front/src/main/resources/application-fastdfs.yml
Normal file
@ -0,0 +1,16 @@
|
||||
#FastDfs的配置 ====================================
|
||||
#读取inputsream阻塞时间
|
||||
fdfs:
|
||||
connect-timeout: 600
|
||||
so-timeout: 1500
|
||||
#tracker地址
|
||||
trackerList: 127.0.0.1:22122
|
||||
#缩略图配置
|
||||
thumbImage:
|
||||
height: 150
|
||||
width: 150
|
||||
#通过nginx 访问地址
|
||||
webUrl: http://127.0.0.1/
|
||||
#获取连接池最大数量
|
||||
pool.max-total: 200
|
||||
|
9
novel-front/src/main/resources/application-oss.yml
Normal file
9
novel-front/src/main/resources/application-oss.yml
Normal file
@ -0,0 +1,9 @@
|
||||
#OSS
|
||||
novel:
|
||||
file:
|
||||
endpoint: oss-cn-shenzhen.aliyuncs.com #不同的服务器,地址不同
|
||||
key-id: dhjjrue6767778878 #去OSS控制台获取
|
||||
key-secret: dssdkkrkelrkellk44554 #去OSS控制台获取
|
||||
bucket-name: novel #这个自己创建bucket时的命名,控制台创建也行,代码创建也行
|
||||
file-host: pic #文件路径
|
||||
web-url: https://xxyimg.oss-cn-hangzhou.aliyuncs.com #OSS文件的web访问地址
|
@ -4,7 +4,7 @@ server:
|
||||
spring:
|
||||
profiles:
|
||||
active: dev
|
||||
include: alipay
|
||||
include: alipay,oss,fastdfs
|
||||
|
||||
|
||||
rabbitmq:
|
||||
|
@ -56,6 +56,7 @@
|
||||
select
|
||||
id,pic_url from book
|
||||
where pic_url like 'http%'
|
||||
and pic_url not like concat('%',#{localPicPrefix},'%')
|
||||
limit #{limit}
|
||||
</select>
|
||||
|
||||
|
7
pom.xml
7
pom.xml
@ -5,7 +5,7 @@
|
||||
|
||||
<groupId>com.java2nb</groupId>
|
||||
<artifactId>novel</artifactId>
|
||||
<version>2.1.2</version>
|
||||
<version>2.5.1</version>
|
||||
<modules>
|
||||
<module>novel-common</module>
|
||||
<module>novel-front</module>
|
||||
@ -40,6 +40,11 @@
|
||||
<jest.version>6.3.1</jest.version>
|
||||
<redis.version>1.4.1.RELEASE</redis.version>
|
||||
<redisson.version>3.12.5</redisson.version>
|
||||
<sharding.jdbc.version>3.0.0</sharding.jdbc.version>
|
||||
<aliyun-sdk-oss.version>2.4.0</aliyun-sdk-oss.version>
|
||||
<commons-fileupload.version>1.3.1</commons-fileupload.version>
|
||||
<fastdfs-client.version>1.26.1-RELEASE</fastdfs-client.version>
|
||||
<alipay-sdk-java.version>4.9.153.ALL</alipay-sdk-java.version>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
|
2
sql/20200608.sql
Normal file
2
sql/20200608.sql
Normal file
@ -0,0 +1,2 @@
|
||||
INSERT INTO `crawl_source` (`id`, `source_name`, `crawl_rule`, `source_status`, `create_time`, `update_time`) VALUES
|
||||
(6, '新笔趣阁', '{\n \"bookListUrl\": \"http://www.xbiquge.la/fenlei/{catId}_{page}.html\",\n \"catIdRule\": {\n \"catId1\": \"1\",\n \"catId2\": \"2\",\n \"catId3\": \"3\",\n \"catId4\": \"4\",\n \"catId5\": \"6\",\n \"catId6\": \"5\"\n },\n \"bookIdPatten\": \"<a\\\\s+href=\\\"http://www.xbiquge.la/(\\\\d+/\\\\d+)/\\\"\\\\s+target=\\\"_blank\\\">\",\n \"pagePatten\": \"<em\\\\s+id=\\\"pagestats\\\">(\\\\d+)/\\\\d+</em>\",\n \"totalPagePatten\": \"<em\\\\s+id=\\\"pagestats\\\">\\\\d+/(\\\\d+)</em>\",\n \"bookDetailUrl\": \"http://www.xbiquge.la/{bookId}/\",\n \"bookNamePatten\": \"<h1>([^/]+)</h1>\",\n \"authorNamePatten\": \"者:([^/]+)</p>\",\n \"picUrlPatten\": \"src=\\\"(http://www.xbiquge.la/files/article/image/\\\\d+/\\\\d+/\\\\d+s\\\\.jpg)\\\"\",\n \"bookStatusRule\": {},\n \"descStart\": \"<div id=\\\"intro\\\">\",\n \"descEnd\": \"</div>\",\n \"upadateTimePatten\": \"<p>最后更新:(\\\\d+-\\\\d+-\\\\d+\\\\s\\\\d+:\\\\d+:\\\\d+)</p>\",\n \"upadateTimeFormatPatten\": \"yyyy-MM-dd HH:mm:ss\",\n \"bookIndexUrl\": \"http://www.xbiquge.la/{bookId}/\",\n \"indexIdPatten\": \"<a\\\\s+href=\'/\\\\d+/\\\\d+/(\\\\d+)\\\\.html\'\\\\s+>[^/]+</a>\",\n \"indexNamePatten\": \"<a\\\\s+href=\'/\\\\d+/\\\\d+/\\\\d+\\\\.html\'\\\\s+>([^/]+)</a>\",\n \"bookContentUrl\": \"http://www.xbiquge.la/{bookId}/{indexId}.html\",\n \"contentStart\": \"<div id=\\\"content\\\">\",\n \"contentEnd\": \"<p>\"\n}', 0, '2020-05-23 22:46:58', '2020-05-23 22:46:58');
|
@ -1691,4 +1691,122 @@ INSERT INTO `user_read_history` VALUES ('113', '1255060328322027520', '125467697
|
||||
INSERT INTO `user_read_history` VALUES ('117', '1255060328322027520', '1254946661743603712', '1254946914001629184', '2020-04-30 19:37:09', '2020-04-30 19:37:09');
|
||||
INSERT INTO `user_read_history` VALUES ('118', '1255060328322027520', '1254957312633352192', '3335449', '2020-04-30 19:37:36', '2020-04-30 19:37:36');
|
||||
|
||||
|
||||
|
||||
DROP TABLE IF EXISTS `book_content0`;
|
||||
CREATE TABLE `book_content0` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
|
||||
`index_id` bigint(20) DEFAULT NULL COMMENT '目录ID',
|
||||
`content` mediumtext COMMENT '小说章节内容',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `key_uq_indexId` (`index_id`) USING BTREE
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1155 DEFAULT CHARSET=utf8mb4 COMMENT='小说内容表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for book_content1
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `book_content1`;
|
||||
CREATE TABLE `book_content1` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
|
||||
`index_id` bigint(20) DEFAULT NULL COMMENT '目录ID',
|
||||
`content` mediumtext COMMENT '小说章节内容',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `key_uq_indexId` (`index_id`) USING BTREE
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=406 DEFAULT CHARSET=utf8mb4 COMMENT='小说内容表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for book_content2
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `book_content2`;
|
||||
CREATE TABLE `book_content2` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
|
||||
`index_id` bigint(20) DEFAULT NULL COMMENT '目录ID',
|
||||
`content` mediumtext COMMENT '小说章节内容',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `key_uq_indexId` (`index_id`) USING BTREE
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1222 DEFAULT CHARSET=utf8mb4 COMMENT='小说内容表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for book_content3
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `book_content3`;
|
||||
CREATE TABLE `book_content3` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
|
||||
`index_id` bigint(20) DEFAULT NULL COMMENT '目录ID',
|
||||
`content` mediumtext COMMENT '小说章节内容',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `key_uq_indexId` (`index_id`) USING BTREE
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=410 DEFAULT CHARSET=utf8mb4 COMMENT='小说内容表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for book_content4
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `book_content4`;
|
||||
CREATE TABLE `book_content4` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
|
||||
`index_id` bigint(20) DEFAULT NULL COMMENT '目录ID',
|
||||
`content` mediumtext COMMENT '小说章节内容',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `key_uq_indexId` (`index_id`) USING BTREE
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1188 DEFAULT CHARSET=utf8mb4 COMMENT='小说内容表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for book_content5
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `book_content5`;
|
||||
CREATE TABLE `book_content5` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
|
||||
`index_id` bigint(20) DEFAULT NULL COMMENT '目录ID',
|
||||
`content` mediumtext COMMENT '小说章节内容',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `key_uq_indexId` (`index_id`) USING BTREE
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=416 DEFAULT CHARSET=utf8mb4 COMMENT='小说内容表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for book_content6
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `book_content6`;
|
||||
CREATE TABLE `book_content6` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
|
||||
`index_id` bigint(20) DEFAULT NULL COMMENT '目录ID',
|
||||
`content` mediumtext COMMENT '小说章节内容',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `key_uq_indexId` (`index_id`) USING BTREE
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1180 DEFAULT CHARSET=utf8mb4 COMMENT='小说内容表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for book_content7
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `book_content7`;
|
||||
CREATE TABLE `book_content7` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
|
||||
`index_id` bigint(20) DEFAULT NULL COMMENT '目录ID',
|
||||
`content` mediumtext COMMENT '小说章节内容',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `key_uq_indexId` (`index_id`) USING BTREE
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=404 DEFAULT CHARSET=utf8mb4 COMMENT='小说内容表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for book_content8
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `book_content8`;
|
||||
CREATE TABLE `book_content8` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
|
||||
`index_id` bigint(20) DEFAULT NULL COMMENT '目录ID',
|
||||
`content` mediumtext COMMENT '小说章节内容',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `key_uq_indexId` (`index_id`) USING BTREE
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1134 DEFAULT CHARSET=utf8mb4 COMMENT='小说内容表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for book_content9
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `book_content9`;
|
||||
CREATE TABLE `book_content9` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
|
||||
`index_id` bigint(20) DEFAULT NULL COMMENT '目录ID',
|
||||
`content` mediumtext COMMENT '小说章节内容',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `key_uq_indexId` (`index_id`) USING BTREE
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=415 DEFAULT CHARSET=utf8mb4 COMMENT='小说内容表';
|
||||
UPDATE `crawl_source` SET `source_name` = '书趣阁', `crawl_rule` = '{\n \"bookListUrl\": \"http://m.shuquge.com/sort/{catId}/0_{page}.html\",\n \"catIdRule\": {\n \"catId1\": \"1\",\n \"catId2\": \"2\",\n \"catId3\": \"3\",\n \"catId4\": \"4\",\n \"catId5\": \"7\",\n \"catId6\": \"6\",\n \"catId7\": \"8\"\n },\n \"bookIdPatten\": \"href=\\\"/s/(\\\\d+)\\\\.html\\\"\",\n \"pagePatten\": \"第(\\\\d+)/\\\\d+页\",\n \"totalPagePatten\": \"第\\\\d+/(\\\\d+)页\",\n \"bookDetailUrl\": \"http://m.shuquge.com/s/{bookId}.html\",\n \"bookNamePatten\": \"<a\\\\s+href=\\\"/s/\\\\d+\\\\.html\\\"><h2>([^/]+)</h2></a>\",\n \"authorNamePatten\": \"<p>作者:([^/]+)</p>\",\n \"picUrlPatten\": \"src=\\\"(http://www.shuquge.com/files/article/image/\\\\d+/\\\\d+/\\\\d+s\\\\.jpg)\\\"\",\n \"statusPatten\": \"<p>状态:([^/]+)</p>\",\n \"bookStatusRule\": {\n \"连载中\": 0,\n \"完本\": 1\n },\n \"descStart\": \"<div class=\\\"intro_info\\\">\",\n \"descEnd\": \"最新章节推荐地址\",\n \"bookIndexUrl\": \"http://www.shuquge.com/txt/{bookId}/index.html\",\n \"bookIndexStart\": \"<dt>《\",\n \"indexIdPatten\": \"<dd><a\\\\s+href=\\\"(\\\\d+)\\\\.html\\\">[^/]+</a></dd>\",\n \"indexNamePatten\": \"<dd><a\\\\s+href=\\\"\\\\d+\\\\.html\\\">([^/]+)</a></dd>\",\n \"bookContentUrl\": \"http://www.shuquge.com/txt/{bookId}/{indexId}.html\",\n \"contentStart\": \"<div id=\\\"content\\\" class=\\\"showtxt\\\">\",\n \"contentEnd\": \"http://www.shuquge.com\"\n}', `source_status` = 1, `create_time` = '2020-05-18 12:02:34', `update_time` = '2020-05-18 12:02:34' WHERE `id` = 4;
|
Reference in New Issue
Block a user