Zuul的上傳
1、建構一個上傳類
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.io.*;
@RestController
@RequestMapping("/file")
public class FileUploadController {
@PostMapping(value = "/upload", consumes = "multipart/form-data")
public Object upload(@RequestParam("file") MultipartFile file) throws IOException {
File temp = new File("D:/" + file.getOriginalFilename());
if(!temp.getParentFile().exists()){
temp.getParentFile().mkdir();
}
try {
file.transferTo(temp); //儲存檔案
return Boolean.TRUE;
} catch (IllegalStateException e) {
e.printStackTrace();
return Boolean.FALSE;
} catch (IOException e) {
e.printStackTrace();
return Boolean.FALSE;
}
}
}
2、配置屬性檔案
zuul預設檔案上傳的時候,會走Spring DispatcherServlet,這個時候會對檔案大小進行判斷,預設為10M;如果要傳大檔案需要對檔案大小進行設定。
zuul.ignored-services=*
zuul.routes.use-routing.serviceId=ms-provider-order
zuul.routes.use-routing.path=/order-service/**
zuul.routes.use-routing.sensitiveHeaders=
spring.servlet.multipart.max-file-size=4000MB
spring.servlet.multipart.max-request-size=4000MB
通過/zuul來通路,可以繞過DispatcherServlet轉為zuulServlet,在上傳大檔案的時候不需要設定檔案大小,但是需要設定hystrix和ribbon的逾時時間。
zuul.ignored-services=*
zuul.routes.use-routing.serviceId=ms-provider-order
zuul.routes.use-routing.path=/order-service/**
zuul.routes.use-routing.sensitiveHeaders=
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=600000
ribbon.ConnectTimeout=100000
ribbon.ReadTimeout=100000
3、通過PostMan測試

zuul的回退
1、自定義一個回退類
import org.springframework.cloud.netflix.zuul.filters.route.FallbackProvider;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.client.ClientHttpResponse;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
public class CustomZuulFallBack implements FallbackProvider {
@Override
public String getRoute() {
return "*"; //*表示為所有微服務提供回退
//return "ms-provider-order" //指定某個微服務回退
}
@Override
public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
return new ClientHttpResponse() {
@Override
public HttpStatus getStatusCode() throws IOException {
return HttpStatus.OK;
}
@Override
public int getRawStatusCode() throws IOException {
return HttpStatus.OK.value();
}
@Override
public String getStatusText() throws IOException {
return HttpStatus.OK.getReasonPhrase();
}
@Override
public void close() {
}
@Override
public InputStream getBody() throws IOException {
return new ByteArrayInputStream("後端服務不可用".getBytes());
}
@Override
public HttpHeaders getHeaders() {
HttpHeaders headers = new HttpHeaders();
//和body中的内容編碼一緻,否則容易亂碼
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
return headers;
}
};
}
}
zuul的回退隻支援當機回退(服務挂了)和逾時回退(服務請求逾時)兩種;
如果服務自己抛出的異常(404,500等),zuul的回退監控不到;原因就在于RibbonRoutingFilter的攔截器,在攔截器run中的forward方法,隻争對了HystrixRuntimeException的攔截,500等異常會直接由SpringBoot的BasicErrorController接管抛出到頁面;
protected ClientHttpResponse forward(RibbonCommandContext context) throws Exception {
Map<String, Object> info = this.helper.debug(context.getMethod(),
context.getUri(), context.getHeaders(), context.getParams(),
context.getRequestEntity());
RibbonCommand command = this.ribbonCommandFactory.create(context);
try {
ClientHttpResponse response = command.execute();
this.helper.appendDebug(info, response.getRawStatusCode(), response.getHeaders());
return response;
}
catch (HystrixRuntimeException ex) {
return handleException(info, ex);
}
}
zuul的全局異常處理
1、自定義一個異常處理類
import com.alibaba.fastjson.JSON;
import com.netflix.zuul.context.RequestContext;
import org.springframework.cloud.netflix.zuul.filters.post.SendErrorFilter;
import org.springframework.stereotype.Component;
import org.springframework.util.ReflectionUtils;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;
@Component
public class CustomErrorFilter extends SendErrorFilter {
@Override
public Object run() {
try {
RequestContext ctx = RequestContext.getCurrentContext();
ExceptionHolder exception = findZuulException(ctx.getThrowable());
//HttpServletRequest request = ctx.getRequest();
HttpServletResponse response = ctx.getResponse();
response.setContentType("text/html; charset=UTF-8");
response.setCharacterEncoding("UTF-8");
Map<String,Object> errorMap = new HashMap<>();
errorMap.put("code","203");
errorMap.put("errMsg",exception.getThrowable().getCause().getMessage());
response.getWriter().write(JSON.toJSONString(errorMap));
}
catch (Exception ex) {
ReflectionUtils.rethrowRuntimeException(ex);
}
return null;
}
}
2、禁用系統自帶的異常處理類
zuul.SendErrorFilter.error.disable=true
zuul的跨域問題
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() {
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
final CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true); // 允許cookies跨域
config.addAllowedOrigin("*");// #允許向該伺服器送出請求的URI,*表示全部允許,在SpringMVC中,如果設成*,會自動轉成目前請求頭中的Origin
config.addAllowedHeader("*");// #允許通路的頭資訊,*表示全部
config.setMaxAge(18000L);// 預檢請求的緩存時間(秒),即在這個時間段裡,對于相同的跨域請求不會再預檢了
config.addAllowedMethod("*");// 允許送出請求的方法,*表示全部允許
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}