(1)创建并查看 AccessKey
Java开发文档
(1)新建一个 service-oss 模块
(2)引入依赖
<dependency>
<groupId>com.aliyun.ossgroupId>
<artifactId>aliyun-sdk-ossartifactId>
dependency>
<dependency>
<groupId>joda-timegroupId>
<artifactId>joda-timeartifactId>
<version>2.9.9version>
dependency>
(3)编写 application.properties
#服务端口
server.port=8002
#服务名
spring.application.name=service-oss
#环境设置:dev、test、prod
spring.profiles.active=dev
#阿里云 OSS
#不同的服务器,地址不同:注意,这里填你自己的
aliyun.oss.file.endpoint=oss-cn-beijing.aliyuncs.com
aliyun.oss.file.keyid=LTAI5t9Gx1VdoJRW152qW6
aliyun.oss.file.keysecret=gEZiEZlPocddxIsFE2T101pTOhrwgN
#bucket可以在控制台创建,也可以使用java代码创建
aliyun.oss.file.bucketname=yanghui-guli
# 设置上传文件大小
spring.servlet.multipart.max-file-size=10MB
(4)创建启动类
/**
* exclude = DataSourceAutoConfiguration.class:排除数据库自动配置
* @ClassName OssApplication
* @Author YH
* @Date 2021/8/25
* @Version 1.0
*/
@Slf4j
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
@ComponentScan(value = {"com.yanghui"})
public class OssApplication {
public static void main(String[] args) {
SpringApplication.run(OssApplication.class, args);
log.info("http://localhost:8001");
}
}
(1)编写常量类
@Component
public class ConstantPropertiesUtils implements InitializingBean {
@Value("${aliyun.oss.file.endpoint}")
private String endpoint;
@Value("${aliyun.oss.file.keyid}")
private String keyId;
@Value("${aliyun.oss.file.keysecret}")
private String keySecret;
@Value("${aliyun.oss.file.bucketname}")
private String bucketName;
public static String END_POINT;
public static String KEY_ID;
public static String KEY_SECRET;
public static String BUCKET_NAME;
/**
* 初始化 Bean 完成之后执行
* @throws Exception
*/
@Override
public void afterPropertiesSet() throws Exception {
END_POINT = endpoint;
KEY_ID = keyId;
KEY_SECRET = keySecret;
BUCKET_NAME = bucketName;
}
}
(2)编写 Controller
@RestController
@RequestMapping("/edu/oss")
@CrossOrigin
public class OssController {
@Autowired
private OssService ossService;
/**
* 上传文件
* @param file
* @return 文件的链接
*/
@PostMapping
public Result uploadFile(MultipartFile file) {
String url = ossService.uploadFile(file);
Map<String, Object> map = new HashMap<>();
map.put("url", url);
return Result.ok().data(map);
}
}
(3)编写 Service 接口
public interface OssService {
/**
* 上传文件
* @param file
* @return
*/
String uploadFile(MultipartFile file);
}
(4)编写 Service 接口实现类
@Service
public class OssServiceImpl implements OssService {
@Override
public String uploadFile(MultipartFile file){
// yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
String endpoint = ConstantPropertiesUtils.END_POINT;
// 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
String accessKeyId = ConstantPropertiesUtils.KEY_ID;
String accessKeySecret = ConstantPropertiesUtils.KEY_SECRET;
String bucketName = ConstantPropertiesUtils.BUCKET_NAME;
try {
// 创建 OSSClient 实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
// 获取文件输入流
InputStream inputStream = file.getInputStream();
// 文件路径
// 唯一值,避免相同文件名不能上传
String uuid = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 7);
// 按照日期分类(获取当前日期),调用 joda 的工具类
String dateTime = new DateTime().toString("yyyy/MM/dd");
String filePath = dateTime + "/" + uuid + file.getOriginalFilename();
// 依次填写Bucket名称(例如examplebucket)和Object完整路径(例如exampledir/exampleobject.txt)。Object完整路径中不能包含Bucket名称。
ossClient.putObject(bucketName, filePath, inputStream);
// 关闭OSSClient。
ossClient.shutdown();
Date expiration = new Date(System.currentTimeMillis() + 3600L * 1000 * 24 * 365 * 10);
// 返回文件链接,没有对应的方法,需要自己拼接(老师的方法),经过查资料,企业中一般不这样干
// String url = "https://" + bucketName + "." + endpoint + "/" + filePath;
/**
* 企业中常用的方式
*/
URL url = ossClient.generatePresignedUrl(bucketName, filePath, expiration);
return url.toString();
} catch (Exception e) {
e.printStackTrace();;
}
return null;
}
}
(5)开始测试(使用 Swagger)
nginx下载
解压后,cmd 进入所在目录,运行 nginx.exe 就可以启动了
停止命令:nginx -s stop
(1)修改 nginx.conf 文件(在 nginx 安装目录 conf 目录下)
在 http
下添加以下内容:
# 添加配置
server {
listen 9001;
server_name localhost;
location ~ /eduservice/ {
proxy_pass http://localhost:8001;
}
location ~ /eduoss/ {
proxy_pass http://localhost:8002;
}
}
(2)修改前端地址
(3)重启 nginx
运行命令 nginx -s stop
,然后再启动
(4)进行测试
CREATE TABLE `edu_subject` (
`id` char(19) NOT NULL COMMENT '课程类别ID',
`title` varchar(10) NOT NULL COMMENT '类别名称',
`parent_id` char(19) NOT NULL DEFAULT '0' COMMENT '父ID',
`sort` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '排序字段',
`gmt_create` datetime NOT NULL COMMENT '创建时间',
`gmt_modified` datetime NOT NULL COMMENT '更新时间',
PRIMARY KEY (`id`),
KEY `idx_parent_id` (`parent_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=COMPACT COMMENT='课程科目';
#
# Data for table "edu_subject"
#
INSERT INTO `edu_subject` VALUES ('1178214681118568449','后端开发','0',1,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178214681139539969','Java','1178214681118568449',1,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178214681181483010','前端开发','0',3,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178214681210843137','JavaScript','1178214681181483010',4,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178214681231814658','云计算','0',5,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178214681252786178','Docker','1178214681231814658',5,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178214681294729217','Linux','1178214681231814658',6,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178214681324089345','系统/运维','0',7,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178214681353449473','Linux','1178214681324089345',7,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178214681382809602','Windows','1178214681324089345',8,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178214681399586817','数据库','0',9,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178214681428946945','MySQL','1178214681399586817',9,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178214681454112770','MongoDB','1178214681399586817',10,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178214681483472898','大数据','0',11,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178214681504444418','Hadoop','1178214681483472898',11,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178214681529610242','Spark','1178214681483472898',12,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178214681554776066','人工智能','0',13,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178214681584136193','Python','1178214681554776066',13,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178214681613496321','编程语言','0',14,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178214681626079234','Java','1178214681613496321',14,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178585108407984130','Python','1178214681118568449',2,'2019-09-30 16:19:22','2019-09-30 16:19:22'),('1178585108454121473','HTML/CSS','1178214681181483010',3,'2019-09-30 16:19:22','2019-09-30 16:19:22');
EasyExcel 特点:
Java领域解析、生成Excel比较有名的框架有Apache poi、jxl等。但他们都存在一个严重的问题就是非常的耗内存。如果你的系统并发量不大的话可能还行,但是一旦并发上来后一定会OOM 或者 JVM 频繁的full gc。
EasyExcel 是阿里巴巴开源的一个excel处理框架,以使用简单、节省内存著称。EasyExcel能大大减少占用内存的主要原因是在解析Excel时没有将文件数据一次性全部加载到内存中,而是从磁盘上一行行读取数据,逐个解析。
EasyExcel 采用一行一行的解析模式,并将一行的解析结果以观察者的模式通知处理(AnalysisEventListener)。
(1)引入依赖
<dependency>
<groupId>com.alibabagroupId>
<artifactId>easyexcelartifactId>
<version>2.1.1version>
dependency>
<dependency>
<groupId>org.apache.poigroupId>
<artifactId>poiartifactId>
<version>3.17version>
dependency>
(2)编写实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class DemoData {
/**
* 设置表头
*/
@ExcelProperty("学生编号")
private Integer sno;
/**
* 属性值必须为小写,否则无法写入
*/
@ExcelProperty("学生姓名")
private String sname;
}
(3)编写测试类
public class EasyExcelTest {
public static void main(String[] args) {
// 1 设置文件位置
String fileName = "D:\\JAVA\\项目\\谷粒学院资料\\write.xlsx";
// 2 实现写操作,学生列表:工作表名称
EasyExcel.write(fileName, DemoData.class).sheet("学生列表").doWrite(getDemoData());
}
private static List<DemoData> getDemoData() {
List<DemoData> demoDataList = new ArrayList<>();
for (int i = 0; i < 10; i++) {
DemoData data = new DemoData();
data.setSno(i);
data.setSname("yang" + i);
System.out.println(data);
demoDataList.add(data);
}
return demoDataList;
}
}
(1)创建实体类
// 设置表头和添加的数据字段
@Data
@ToString
public class ReadData {
/**
* 设置 excel表头名称
* index 代表 excel表格字段索引
*/
@ExcelProperty(value = "学生序号", index = 0)
private Integer sno;
/**
* 设置 excel表头名称
* index代表excel表格字段索引
*/
@ExcelProperty(value = "学生姓名", index = 1)
private String sname;
}
(2)创建监听器
其实对数据的操作就是在这里完成的。
public class ExcelListener extends AnalysisEventListener<ReadData> {
/**
* 一行一行读取内容
* @param data
* @param context
*/
@Override
public void invoke(ReadData data, AnalysisContext context) {
System.out.println("一、" + data);
}
/**
* 读取完成之后
* @param context
*/
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
}
/**
* 读取表头内容
* @param headMap
* @param context
*/
@Override
public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
System.out.println("表头:" + headMap);
}
}
(3)测试类
public class EasyExcelReadTest {
public static void main(String[] args) {
String fileName = "D:\\JAVA\\项目\\谷粒学院资料\\write.xlsx";
EasyExcel.read(fileName, ReadData.class, new ExcelListener()).sheet().doRead();
}
}
(4)运行结果
<dependency>
<groupId>com.alibabagroupId>
<artifactId>easyexcelartifactId>
<version>2.1.1version>
dependency>
@Data
public class Subject {
@ExcelProperty(index = 0)
private String oneSubjectName;
@ExcelProperty(index = 1)
private String twoSubjectName;
}
@RestController
@RequestMapping("/eduservice/edu-subject")
public class EduSubjectController {
@Autowired
private EduSubjectService eduSubjectService;
/**
* 添加课程分类
* 获取上传过来的文件
*/
@PostMapping("/addSubject")
public Result addSubject(MultipartFile multipartFile) {
eduSubjectService.saveSubject(multipartFile, eduSubjectService);
return Result.ok();
}
}
public interface EduSubjectService extends IService<EduSubject> {
/**
* 添加课程分类
* @param multipartFile
* @param eduSubjectService
*/
void saveSubject(MultipartFile multipartFile, EduSubjectService eduSubjectService);
}
@Service
public class EduSubjectServiceImpl extends ServiceImpl<EduSubjectMapper, EduSubject> implements EduSubjectService {
@Override
public void saveSubject(MultipartFile multipartFile, EduSubjectService eduSubjectService) {
try {
InputStream inputStream = multipartFile.getInputStream();
EasyExcel.read(inputStream, Subject.class, new SubjectExcelListener(eduSubjectService)).sheet().doRead();
} catch (Exception e) {
}
}
}
public class SubjectExcelListener extends AnalysisEventListener<Subject> {
private EduSubjectService eduSubjectService;
public SubjectExcelListener() {
}
public SubjectExcelListener(EduSubjectService eduSubjectService) {
this.eduSubjectService = eduSubjectService;
}
@Override
public void invoke(Subject subject, AnalysisContext context) {
if (subject == null) {
throw new GuliException(500, "文件内容为空");
}
/**
* 一级分类添加
*/
EduSubject oneSubject = this.existOneSubject(this.eduSubjectService, subject.getOneSubjectName());
// 如果没有相同的,就添加
if (oneSubject == null) {
oneSubject = new EduSubject();
oneSubject.setParentId("0");
oneSubject.setTitle(subject.getOneSubjectName());
eduSubjectService.save(oneSubject);
}
/**
* 主要是利用了 MybatisPlus 的添加之后会回显对象
* 得到其父级 id
*/
String parentId = oneSubject.getId();
/**
* 二级分类添加
*/
EduSubject twoSubject = this.existTwoSubject(this.eduSubjectService, subject.getOneSubjectName(), parentId);
// 如果没有相同的,就添加
if (twoSubject == null) {
EduSubject eduSubject = new EduSubject();
eduSubject.setParentId(parentId);
eduSubject.setTitle(subject.getTwoSubjectName());
eduSubjectService.save(eduSubject);
}
}
/**
* 判断一级分类不能重复添加
*/
private EduSubject existOneSubject(EduSubjectService eduSubjectService, String name) {
QueryWrapper<EduSubject> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("title", name);
queryWrapper.eq("parent_id", "0");
EduSubject eduSubject = eduSubjectService.getOne(queryWrapper);
return eduSubject;
}
/**
* 判断二级分类不能重复添加
*/
private EduSubject existTwoSubject(EduSubjectService eduSubjectService, String name, String parentId) {
QueryWrapper<EduSubject> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("title", name);
queryWrapper.eq("parent_id", parentId);
EduSubject eduSubject = eduSubjectService.getOne(queryWrapper);
return eduSubject;
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
}
}