乐优商城项目总结day(8)
@PostMapping
public ResponseEntity<Void> saveBrand(Brand brand, @RequestParam(value = "cids") List<Long> cids) {
brandService.saveBrand(brand, cids);
return ResponseEntity.status(HttpStatus.CREATED).build();
}
SpringMvc能够自动将字符串"id1,id2,id3,..."
自动转化成List<T>
public void saveBrand(Brand brand, List<Long> cids) {
brand.setId(null);
int count = brandDao.insert(brand);
if(count != 1) {
throw new LyException(ExceptionEnum.BRAND_SAVE_ERROR);
}
cids.stream().forEach(cid -> {
int ct = brandDao.insertCategoryBrand(cid, brand.getId());
if(ct != 1) {
throw new LyException(ExceptionEnum.BRAND_SAVE_ERROR);
}
});
}
通用mapper进行insert添加实体类后,如果实体类的主键带有自增策略,会对添加的实体类对象的主键进行写回。
@Repository
public interface BrandDao extends BaseMapper<Brand> {
@Insert("INSERT INTO tb_category_brand (category_id, brand_id) VALUES (#{cid}, #{bid})")
int insertCategoryBrand(@Param("cid") Long cid, @Param("bid") Long bid);
@Select("SELECT b.id,b.name,b.image,b.letter FROM tb_brand b INNER JOIN tb_category_brand cb ON b.id = cb.brand_id WHERE cb.category_id = #{cid}")
List<Brand> queryByCategoryId(@Param("cid") Long cid);
}
使用通用mapper也能配合原来的mybatis注解、xml等使用方式。
文件上传
servlet:
multipart:
max-file-size: 5MB # 限制文件上传的大小
@PostMapping(value = "/image")
public ResponseEntity<String> uploadImage(@RequestParam("file") MultipartFile file) {
return ResponseEntity.ok(uploadService.uploadImage(file));
}
限制文件上传的大小,并从request参数中获取名为file的的文件数据,对应SpringMvc中的MultipartFile
。
http {
include mime.types;
default_type application/octet-stream;
client_max_body_size 10m;
以上除了servlet会对文件上传的大小进行限制之外,nginx也会对请求体的最大值进行限制,可以通过nginx的配置文件进行修改。
// 校验文件类型
String contentType = file.getContentType();
if(!uploadProperties.getAllowTypes().contains(contentType)) {
throw new LyException(ExceptionEnum.INVALID_FILE_TYPE);
}
// 校验文件内容
BufferedImage image = ImageIO.read(file.getInputStream());
if(image == null) {
throw new LyException(ExceptionEnum.INVALID_FILE_TYPE);
}
文件上传到本地或者FastDFS之前需要进行文件类型以及内容的校验(此项目中文件为图片类型)
绕过网关缓存
图片上传是文件的传输,如果也经过Zuul网关的代理,文件就会经过多次网路传输,造成不必要的网络负担。在高并发时,可能导致网络阻塞,Zuul网关不可用。这样我们的整个系统就瘫痪了。所以,我们上传文件的请求就不经过网关来处理了。
可以使用nginx方向代理对请求到的路由进行rewrite重写,在/api/upload
前面加上/zuul/
,这样就能跳过zuul对文件请求的缓存等处理,减少网关的压力,提高网关的可用性。
rewrite规则如上所示。
FastDFS的使用
具体服务器上的安装可参考网上教程,同时可以配合FastDFS相关的nginx模块非常方便的开启http方式的文件访问。
FastDFS的作者提供了一个Java客户端,但是作为一个C程序员,写的java代码可想而知。而且已经很久不维护了。
这里推荐一个开源的FastDFS客户端,支持最新的SpringBoot2.0。
配置使用极为简单,支持连接池,支持自动生成缩略图,狂拽酷炫吊炸天啊,有木有。
地址:tobato/FastDFS_client
<fastDFS.client.version>1.26.1-RELEASE</fastDFS.client.version>
<dependency>
<groupId>com.github.tobato</groupId>
<artifactId>fastdfs-client</artifactId>
</dependency>
在父工程中管理依赖的版本,在子工程中即可直接引入依赖。
使用极其方便,详细可参考上面github的地址。
@Configuration
@Import(FdfsClientConfig.class)
// 解决jmx重复注册bean的问题
@EnableMBeanExport(registration = RegistrationPolicy.IGNORE_EXISTING)
public class FastClientImporter {
}
将FastDFS-Client客户端引入本地化项目的方式非常简单,在SpringBoot项目/src/[com.xxx.主目录]/conf当中配置,只需要一行注解@Import(FdfsClientConfig.class)
就可以拥有带有连接池的FastDFS Java客户端了。
fdfs:
so-timeout: 2500
connect-timeout: 600
thumb-image: # 缩略图
width: 60
height: 60
tracker-list: # tracker地址
- 192.168.159.128:22122
以上是一些参数的简单配置。
@Autowired
private FastFileStorageClient fastFileStorageClient;
// 上传到FastDFS
String extension = StringUtils.substringAfterLast(file.getOriginalFilename(), ".");
StorePath storePath = fastFileStorageClient.uploadFile(file.getInputStream(), file.getSize(), extension, null);
// 返回文件路径
return uploadProperties.getBaseUrl() + storePath.getFullPath();
注入FastFileStorageClient
即可获取对应的storage并进行文件上传,uploadFile
方法主要接受的参数依次为文件的输入流、文件大小以及文件的后缀名。storePath.getFullPath()
返回存储文件后的带分组的文件路径,可以和FastDFS的nginx模块相结合进行文件的访问。
来源:CSDN
作者:风&浩
链接:https://blog.csdn.net/NEBEEEEEEK2/article/details/90145877