乐优商城笔记二:分类与品牌模块
分类模块与品牌模块实现

分类模块与品牌模块实现

准备工作

使用nginx,通过域名访问本地项目

  1. 下载nginx压缩包(我这里直接下载的windows包,解压后编写配置文件,即可使用)
  2. nginx.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
...
# 配置两个server节点即可
server {
listen 80;
server_name manage.leyou.com;

#charset koi8-r;

#access_log logs/host.access.log main;

location / {
proxy_pass http://127.0.0.1:9001;
proxy_connect_timeout 600;
proxy_read_timeout 600;
}
}

server {
listen 80;
server_name api.leyou.com;

#charset koi8-r;

#access_log logs/host.access.log main;

location / {
proxy_pass http://127.0.0.1:10001;
proxy_connect_timeout 600;
proxy_read_timeout 600;
}
}
...

跨域问题解决(采用CORS)

  1. ly-gateway中配置bean即可
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package com.leyou.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

@Configuration
public class CorsConfig {

@Bean
public CorsFilter corsFilter() {
//1.添加CORS配置信息
CorsConfiguration config = new CorsConfiguration();
//1) 允许的域,不要写*,否则cookie就无法使用了
config.addAllowedOrigin("http://manage.leyou.com");
//2) 是否发送Cookie信息
config.setAllowCredentials(true);
//3) 允许的请求方式
config.addAllowedMethod("OPTIONS");
config.addAllowedMethod("HEAD");
config.addAllowedMethod("GET");
config.addAllowedMethod("PUT");
config.addAllowedMethod("POST");
config.addAllowedMethod("DELETE");
config.addAllowedMethod("PATCH");
// 4)允许的头信息
config.addAllowedHeader("*");
// 5) 设置第一次跨域通过后,往后的请求不需要再次发送跨域预请求
config.setMaxAge(7200L);

//2.添加映射路径,我们拦截一切请求
UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
configSource.registerCorsConfiguration("/**", config);

//3.返回新的CorsFilter.
return new CorsFilter(configSource);
}
}

创建数据库

  1. 创建数据库leyou

  2. 导入数据库文件

    leyou.sql

分类管理模块

后端

添加实体类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.leyou.pojo;

import lombok.Data;
import tk.mybatis.mapper.annotation.KeySql;

import javax.persistence.Id;
import javax.persistence.Table;

@Table(name="tb_category")
@Data
public class Category {
@Id
@KeySql(useGeneratedKeys = true)
private Long id;
private String name;
private Long parentId;
private Boolean isParent;
private Integer sort;
}

注意:

​ 实体类放到ly-item-interface

​ 实体类中使用的注解需要引入mapper-core的依赖。

编写mapper

1
2
3
4
5
6
7
package com.leyou.item.mapper;

import com.leyou.pojo.Category;
import tk.mybatis.mapper.common.Mapper;

public interface CategoryMapper extends Mapper<Category> {
}

注意:

​ 需要在启动类上加入@MapperScan(com.leyou.item.mapper)注解

编写service

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
package com.leyou.item.service;

import com.leyou.common.enums.LyExceptionEnum;
import com.leyou.common.exception.LyException;
import com.leyou.item.mapper.CategoryMapper;
import com.leyou.pojo.Category;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.List;

@Service
public class CategoryService {

@Autowired
private CategoryMapper categoryMapper;

/**
* 按分类父ID查询分类列表
* @param pid 父ID
* @return 分类列表
*/
public List<Category> queryCategoryListByPid(Long pid) {
Category category = new Category();
category.setParentId(pid);
List<Category> categoryList = categoryMapper.select(category);
if (CollectionUtils.isEmpty(categoryList)) {
throw new LyException(LyExceptionEnum.CATEGORY_LIST_NOT_FOUND);
}
return categoryList;
}

/**
* 新增分类
* @param category 分类
* @return 分类
*/
public Category addCategory(Category category) {
// 判断其父节点是否为父节点
if (category.getParentId() != CategoryConstans.FIRST_CATEGORY_PARENT_ID) {
Category pCategory = categoryMapper.selectByPrimaryKey(category.getParentId());
if (pCategory != null) {
// 判断是否已经是父菜单
if (!pCategory.getIsParent()) {// 不为父菜单
// 设置为父菜单并保存
pCategory.setIsParent(true);
categoryMapper.updateByPrimaryKey(pCategory);
}
} else {
throw new LyException(LyExceptionEnum.PARENT_CATEGORY_NOT_FOUND);
}
}
if (categoryMapper.insert(category) != 1) {
throw new LyException(LyExceptionEnum.SAVE_FAILURE);
}
return category;
}

/**
* 编辑分类
* @param category 分类
* @return 分类
*/
public Category saveCategory(Category category) {
if (categoryMapper.updateByPrimaryKey(category) != 1) {
throw new LyException(LyExceptionEnum.SAVE_FAILURE);
}
return category;
}

/**
* 删除费雷
* @param categoryId 分类id
* @return 被删除的分类
*/
public Category deleteCategory(Long categoryId) {
Category category = categoryMapper.selectByPrimaryKey(categoryId);
if (category == null) {
throw new LyException(LyExceptionEnum.CATEGORY_NOT_FOUND);
}
// 判断该分类是否为父分类,若为父分类判断分类下是否有子分类
if (category.getIsParent()) {
Category param = new Category();
param.setParentId(categoryId);
if (categoryMapper.select(param).size() > 0) {
throw new LyException(LyExceptionEnum.DELETE_INVALID);
}
}
if (categoryMapper.delete(category) != 1) {
throw new LyException(LyExceptionEnum.SAVE_FAILURE);
}
return category;
}
}

新增异常枚举:

1
2
3
4
5
6
7
> CATEGORY_LIST_NOT_FOUND(404, "未查询到分类列表"),
> CATEGORY_NOT_FOUND(404, "该分类不存在"),
> PARENT_CATEGORY_NOT_FOUND(404, "该父分类不存在"),
> SAVE_FAILURE(500, "保存失败"),
> DELETE_FAILURE(500, "删除失败"),
> DELETE_INVALID(500, "该分类下含有子分类,请先删除其子分类"),
>

新增分类常量类:

1
2
3
4
5
6
7
> package com.leyou.pojo;
>
> public final class CategoryConstans {
> // 分类一级菜单的父ID
> public static final long FIRST_CATEGORY_PARENT_ID = 0;
> }
>

编写controller

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
package com.leyou.item.cotroller;

import com.leyou.common.enums.LyExceptionEnum;
import com.leyou.common.exception.LyException;
import com.leyou.item.service.CategoryService;
import com.leyou.pojo.Category;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/category")
public class CategoryController {

@Autowired
private CategoryService categoryService;

@GetMapping("/list")
public ResponseEntity<List<Category>> queryCategoryListByPid(@RequestParam(value = "pid", defaultValue = "0") Long pid) {
return ResponseEntity.ok(categoryService.queryCategoryListByPid(pid));
}

@PostMapping()
public ResponseEntity<Category> addCategory(@RequestBody Category category) {
if (category == null) {
throw new LyException(LyExceptionEnum.PARAM_CANNOT_BE_NULL);
}
return ResponseEntity.status(HttpStatus.CREATED).body(categoryService.addCategory(category));
}

@PutMapping()
public ResponseEntity<Category> saveCategory(@RequestBody Category category) {
if (category == null) {
throw new LyException(LyExceptionEnum.PARAM_CANNOT_BE_NULL);
}
return ResponseEntity.ok(categoryService.saveCategory(category));
}

@DeleteMapping("/{categoryId}")
public ResponseEntity<Category> deleteCategory(@PathVariable("categoryId") Long categoryId) {
if (categoryId == null) {
throw new LyException(LyExceptionEnum.PARAM_CANNOT_BE_NULL);
}
return ResponseEntity.ok(categoryService.deleteCategory(categoryId));
}
}

前端

Category.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
<template>
<v-card>
<v-flex xs12 sm10>
<v-tree url="/item/category/list"
:isEdit="isEdit"
@handleAdd="handleAdd"
@handleEdit="handleEdit"
@handleDelete="handleDelete"
@handleClick="handleClick"
/>
</v-flex>
</v-card>
</template>

<script>
export default {
name: "category",
data() {
return {
isEdit:true
}
},
methods: {
handleAdd(node) {
// console.log("add .... ");
console.log(node);
this.$http.post('/item/category', {
"name": node.name,
"sort": node.sort,
"parentId": node.parentId,
"isParent": node.isParent
}).then((response) => {
if (response.status === 201) {
this.$message.info('添加成功');
} else {
this.$message.error(response['message']);
}
}).catch(() => {
this.$message.error('添加失败');
})
},
handleEdit(id, name) {
console.log("edit... id: " + id + ", name: " + name)
// 这个树菜单的编辑,我也没玩明白。23333333

},
handleDelete(id) {
// console.log("delete ... " + id)
this.$http.delete('/item/category/' + id)
.then((response) => {
if (response.status === 200) {
this.$message.info("删除成功")
} else {
this.$message.error(response['message'])
}
})
.catch(() => {
this.$message.error("删除失败")
})
},
handleClick(node) {
}
}
};
</script>

<style scoped>

</style>

树菜单的编辑,我也没玩明白,有玩明白了可以留言一下。

品牌管理模块

后端

添加实体类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.leyou.pojo;

import lombok.Data;
import tk.mybatis.mapper.annotation.KeySql;

import javax.persistence.Id;
import javax.persistence.Table;

@Table(name = "tb_brand")
@Data
public class Brand {
@Id
@KeySql(useGeneratedKeys = true)
private Long id;
private String name;
private String image;
private Character letter;
}

编写mapper

1
2
3
4
5
6
7
package com.leyou.item.mapper;

import com.leyou.pojo.Brand;
import tk.mybatis.mapper.common.Mapper;

public interface BrandMapper extends Mapper<Brand> {
}

编写service

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
package com.leyou.item.service;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.leyou.common.enums.LyExceptionEnum;
import com.leyou.common.exception.LyException;
import com.leyou.common.vo.PageResult;
import com.leyou.item.mapper.BrandMapper;
import com.leyou.pojo.Brand;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import java.util.List;

@Service
@Transactional
public class BrandService {

@Autowired
private BrandMapper brandMapper;

/**
* 分页查询品牌列表
*
* @param page 当前页码
* @param rows 每页记录数
* @param sortBy 排序字段
* @param desc 是否降序
* @param key 查询关键字
* @return 品牌分页列表
*/
public PageResult<Brand> queryBrandByPage(int page, int rows, String sortBy, Boolean desc, String key) {
// 分页查询
PageHelper.startPage(page, rows);
// 封装查询条件
Example example = new Example(Brand.class);
if (StringUtils.isNoneBlank(key)) {
example.createCriteria().andLike("name", "%" + key + "%");
}
// 排序
if (StringUtils.isNoneBlank(sortBy)) {
example.setOrderByClause(sortBy + (desc ? " DESC" : " ASC"));
}
List<Brand> brands = brandMapper.selectByExample(example);
if (brands.size() < 1) {
throw new LyException(LyExceptionEnum.BRAND_LIST_NOT_FOUND);
}
// 获取分页信息并返回
PageInfo<Brand> pageInfo = new PageInfo<>(brands);
return new PageResult<>(pageInfo.getTotal(), brands);
}

/**
* 新增品牌
*
* @param brand 品牌
* @param categories 品牌所属分类
* @return 品牌
*/
public Brand addBrand(Brand brand, List<Long> categories) {
// 新增品牌
if (brandMapper.insert(brand) != 1) {
throw new LyException(LyExceptionEnum.SAVE_FAILURE);
}
// 添加关联的品牌分类
insertCategoryBrand(brand, categories);

return brand;
}

/**
* 编辑品牌
*
* @param brand 品牌
* @param categories 品牌所属分类
* @return 品牌
*/
public Brand saveBrand(Brand brand, List<Long> categories) {
// 更新品牌
if (brandMapper.updateByPrimaryKeySelective(brand) != 1) {
throw new LyException(LyExceptionEnum.SAVE_FAILURE);
}
// 更新关联的品牌分类
brandMapper.deleteCategoryBrandByBrandId(brand.getId());
insertCategoryBrand(brand, categories);
return brand;
}

/**
* 新增品牌分类关联数据(品牌 1 -> n 分类)
*
* @param brand 品牌
* @param categories 分类
*/
private void insertCategoryBrand(Brand brand, List<Long> categories) {
categories.forEach(categoryId -> {
if (brandMapper.insertCategoryBrand(categoryId, brand.getId()) != 1) {
throw new LyException(LyExceptionEnum.SAVE_FAILURE);
}
});
}

/**
* 删除品牌
*
* @param brandId 品牌ID
* @return 被删除的品牌
*/
public Brand deleteBrand(long brandId) {
// 查询要删除的品牌
Brand brand = brandMapper.selectByPrimaryKey(brandId);
if (brand == null) {
throw new LyException(LyExceptionEnum.BRAND_LIST_NOT_FOUND);
}
// 删除品牌
if(brandMapper.delete(brand) != 1){
throw new LyException(LyExceptionEnum.DELETE_FAILURE);
}
// 删除品牌的关联分类数据
brandMapper.deleteCategoryBrandByBrandId(brandId);
return brand;
}
}

编写controller

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
package com.leyou.item.cotroller;

import com.leyou.common.enums.LyExceptionEnum;
import com.leyou.common.exception.LyException;
import com.leyou.common.vo.PageResult;
import com.leyou.item.service.BrandService;
import com.leyou.pojo.Brand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("brand")
public class BrandController {

@Autowired
private BrandService brandService;

@GetMapping("/page")
public ResponseEntity<PageResult<Brand>> queryBrandByPage(@RequestParam(value = "page", defaultValue = "1") int page,
@RequestParam(value = "rows", defaultValue = "5") int rows,
@RequestParam("sortBy") String sortBy,
@RequestParam(value = "desc",defaultValue = "false") Boolean desc,
@RequestParam("key") String key) {
return ResponseEntity.ok(brandService.queryBrandByPage(page, rows, sortBy, desc, key));
}

@PostMapping
public ResponseEntity<Brand> addBrand(@RequestBody Brand brand,
@RequestParam("categories") List<Long> categories) {
if (CollectionUtils.isEmpty(categories)) {
throw new LyException(LyExceptionEnum.PARAM_INVALID);
}
return ResponseEntity.status(HttpStatus.CREATED).body(brandService.addBrand(brand, categories));
}

@PutMapping
public ResponseEntity<Brand> editBrand(@RequestBody Brand brand,
@RequestParam("categories") List<Long> categories) {
if (CollectionUtils.isEmpty(categories) || brand.getId() == null) {
throw new LyException(LyExceptionEnum.PARAM_INVALID);
}
return ResponseEntity.ok(brandService.saveBrand(brand, categories));
}

@DeleteMapping("/{brandId}")
public ResponseEntity<Brand> deleteBrand(@PathVariable("brandId") long brandId) {
return ResponseEntity.ok(brandService.deleteBrand(brandId));
}


}

文件上传微服务

在品牌管理模块的新增和修改中,需要进行上传图片。所以我们将其抽离出来,形成专门的微服务,以后所有文件上传,无论是图片或者是其他文件,都可以通过此文件上传微服务完成。

搭建项目

创建maven项目

  • GroupId:com.leyou.service
  • ArtifactId:ly-upload

编写pom.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>parent</artifactId>
<groupId>com.leyou</groupId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<groupId>com.leyou.service</groupId>
<artifactId>ly-upload</artifactId>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>com.leyou.common</groupId>
<artifactId>ly-common</artifactId>
<version>${leyou.latest.version}</version>
</dependency>
</dependencies>
</project>

启动类

1
2
3
4
5
6
7
8
9
10
11
12
13
package com.leyou;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient
public class LyUpload {
public static void main(String[] args) {
SpringApplication.run(LyUpload.class, args);
}
}

注意在网关中添加文件上传微服务的路由

编写application.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
server:
port: 8082
spring:
application:
name: upload-service
servlet:
multipart:
# 限制单个文件的大小
max-file-size: 5MB
# Eureka
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:9999/eureka

ly:
upload:
imageServer: http://image.leyou.com/
imageTypes:
- image/jpeg
- image/bmp
- image/png

优化

默认情况下,请求通过Zuul网关,Spring MVC会对请求做预处理和缓存,但是文件一旦缓存,会给服务器造成不必要的负担。所以我们需要上传文件的请求不进行缓存。官方给出的解决方案就是在请求的最前面加上/zuul这样就可以绕开请求的缓存,直接将请求路由到指定的微服务。

配置nginx路径重写

修改nginx.conf配置文件

分布式文件系统FastDFS

FastDFS简介

参考:http://www.xushuai.fun/2018/12/22/FastDFS简介/

FastDFS安装

参考:http://www.xushuai.fun/2018/12/22/FastDFS安装/

引入FastDFS-client依赖

  1. java-客户端

  1. 编辑pom.xml文件,新增依赖

    1
    2
    3
    4
    <dependency>
    <groupId>com.github.tobato</groupId>
    <artifactId>fastdfs-client</artifactId>
    </dependency>

新增配置

1
2
3
4
5
6
7
8
fdfs:
so-timeout: 1501
connect-timeout: 601
thumb-image: #缩略图生成参数
width: 150
height: 150
tracker-list: #TrackerList参数,支持多个
- 192.168.136.100:22122

引入配置类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.leyou.upload.config;

import com.github.tobato.fastdfs.FdfsClientConfig;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableMBeanExport;
import org.springframework.context.annotation.Import;
import org.springframework.jmx.support.RegistrationPolicy;

/**
* 导入FastDFS-Client组件
*
* @author tobato
*
*/
@Configuration
@Import(FdfsClientConfig.class)
// 解决jmx重复注册bean的问题
@EnableMBeanExport(registration = RegistrationPolicy.IGNORE_EXISTING)
public class ComponetImport {
// 导入依赖组件
}

编写上传逻辑

  • service

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    package com.leyou.upload.service;

    import com.github.tobato.fastdfs.domain.StorePath;
    import com.github.tobato.fastdfs.service.FastFileStorageClient;
    import com.leyou.common.enums.LyExceptionEnum;
    import com.leyou.common.exception.LyException;
    import com.leyou.upload.constans.FileTypeConstans;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.stereotype.Service;
    import org.springframework.web.multipart.MultipartFile;

    import javax.imageio.ImageIO;
    import java.awt.image.BufferedImage;
    import java.io.IOException;

    @Service
    @Slf4j
    public class UploadService {

    @Autowired
    private FastFileStorageClient fastFileStorageClient;

    @Autowired
    private ImageTypeConfigProperty imageTypeConfigProperty;

    /**
    * 文件上传
    *
    * @param file 文件
    * @return 文件url
    */
    public String uploadFile(MultipartFile file, String fileType) {
    String url = null;
    switch (fileType) {
    case FileTypeConstans.IMAGE:
    url = uploadImage(file);
    break;
    default:
    throw new LyException(LyExceptionEnum.FILE_TYPE_ERROR);
    }
    return url;
    }

    /**
    * 图片上传
    *
    * @param file 图片
    * @return 图片url
    */
    private String uploadImage(MultipartFile file) {
    try {
    // 校验图片内容,防止修改后缀名恶意上传
    BufferedImage image = ImageIO.read(file.getInputStream());
    if (image == null || image.getWidth() == 0 || image.getHeight() == 0) {
    throw new LyException(LyExceptionEnum.FILE_TYPE_ERROR);
    }
    // 获取文件后缀名
    String filename = file.getOriginalFilename();
    String suffix = filename.substring(filename.indexOf(".") + 1);

    // 上传文件
    StorePath storePath = fastFileStorageClient.uploadFile(file.getInputStream(), file.getSize(), suffix, null);
    // 返回文件路径
    return imageTypeConfigProperty.getImageServer() + storePath.getFullPath();
    } catch (IOException e) {
    log.error("读取文件内容发生IO异常. e = {}", e);
    throw new LyException(LyExceptionEnum.READ_FILE_FAILURE);
    }
    }
    }
  • controller

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    package com.leyou.upload.controller;

    import com.leyou.common.enums.LyExceptionEnum;
    import com.leyou.common.exception.LyException;
    import com.leyou.upload.config.ImageTypeConfigProperty;
    import com.leyou.upload.constans.FileTypeConstans;
    import com.leyou.upload.service.UploadService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.multipart.MultipartFile;

    import java.util.List;

    @RestController
    @RequestMapping("/upload")
    public class UploadController {

    @Autowired
    private UploadService uploadService;

    @Autowired
    private ImageTypeConfigProperty imageTypeConfigProperty;

    @PostMapping("/image")
    public String uploadImage(@RequestParam("file") MultipartFile file) {
    // 判断图片类型
    if (!imageTypeConfigProperty.getImageTypes().contains(file.getContentType())) {
    throw new LyException(LyExceptionEnum.FILE_TYPE_ERROR);
    }

    return uploadService.uploadFile(file, FileTypeConstans.IMAGE);
    }
    }
文章作者: imxushuai
文章链接: https://www.imxushuai.com/2002/01/01/乐友商城笔记二:分类与品牌模块/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 imxushuai
支付宝打赏
微信打赏