目录
功能实现后项目结构一览
建立微服务项目
我们把上传单独做成一个模块,遵循软件的开闭原则
引入依赖
在pom文件中引入依赖
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
</dependencies>
新建yml文件配置项目信息
这里面的主要内容有两个,一是把upload服务注入到eureka容器中,二是限制文件上传的大小。
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:10086/eureka
instance:
lease-renewal-interval-in-seconds: 5 # 每隔5秒发送一次心跳
lease-expiration-duration-in-seconds: 10 # 10秒不发送就过期
新建项目启动引导类
记得书写注解
@SpringBootApplication
@EnableDiscoveryClient
public class LeyouUploadApplication {
public static void main(String[] args) {
SpringApplication.run(LeyouUploadApplication.class, args);
}
}
Controller
@Controller
@RequestMapping("upload")
public class UploadController {
@Autowired
private UploadService uploadService;
@PostMapping("image")
public ResponseEntity<String> uploadImage(@RequestParam("file") MultipartFile file){
String url =this.uploadService.uploadImage(file);
if(StringUtils.isBlank(url)) {
return ResponseEntity.badRequest().build();
}
return ResponseEntity.status(HttpStatus.CREATED).body(url);
}
}
Service
@Service
public class UploadService {
private static final List<String> CONTENT_TYPES = Arrays.asList("image/gif", "image/jpeg", "image/jpg");
private static final Logger LOGGER = LoggerFactory.getLogger(UploadService.class);
public String uploadImage(MultipartFile file) {
String originalFilename = file.getOriginalFilename();
//校验文件类型
String contentType = file.getContentType();
if(!CONTENT_TYPES.contains(contentType)) {
LOGGER.info("文件类型不合法: {}", originalFilename);
return null;
}
//校验文件内容
try {
BufferedImage bufferedImage = ImageIO.read(file.getInputStream());
if(bufferedImage == null) {
LOGGER.info("文件内容不合法: {}", originalFilename);
return null;
}
//保存到服务器
file.transferTo(new File("G:\\software\\FastDFS\\image\\" + originalFilename));
//返回url,进行回显
return "http://image.leyou.com/" + originalFilename;
} catch (IOException e) {
LOGGER.info("服务器内部错误: " + originalFilename);
e.printStackTrace();
}
return null;
}
}
跨域配置
上传下载这种传输服务走网关会造成网络拥堵,最终导致Zuul不可用而让整个项目瘫痪。因此需要在upload微服务中新建跨域配置,因此这个微服务不再走网关了,网关微服务的跨域配置不会对其生效。
@Configuration
public class LeyouCorsConfiguration {
@Bean
public CorsFilter corsFilter() {
//初始化cors配置
CorsConfiguration configuration =new CorsConfiguration();
//允许跨域的域名,如果要携带cookie不能写*.*代表所有域名都可以跨域访问
configuration.addAllowedOrigin("http://manage.leyou.com");
configuration.setAllowCredentials(true); //允许携带cookie
configuration.addAllowedMethod("*"); //代表所有请求方式,post。。。
configuration.addAllowedHeader("*"); //允许携带任何头信息
//初始化cors配置源对象
UrlBasedCorsConfigurationSource corsConfigurationSource = new UrlBasedCorsConfigurationSource();
corsConfigurationSource.registerCorsConfiguration("/**", configuration);
//返回corsFilter实例,参数:cors配置源对象
return new CorsFilter(corsConfigurationSource);
}
}
Nginx配置
之所以要改nginx.conf是因为我们采取的办法是不让文件上传的请求被网关拦截。于是我们新建了一个location来映射上传微服务的地址。映射到的地址仍然是以/api打头的,为了防止它被转发到网关微服务。我们用正则表达式进行了重新,重写之后去掉了/api保证了保留给外界的是/api路径,但实际请求的确实upload自己的路径
修改nginx.conf文件,要把upload服务的配置写在其他服务的配置之上,并且编写完成后记得重启nginx服务
server {
listen 80;
server_name api.leyou.com;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 上传路径的映射
location /api/upload {
proxy_pass http://127.0.0.1:8082;
proxy_connect_timeout 600;
proxy_read_timeout 600;
rewrite "^/api/(.*)$" /$1 break;
}
location / {
proxy_pass http://127.0.0.1:10010;
proxy_connect_timeout 600;
proxy_read_timeout 600;
}
}
效果展示