zoukankan      html  css  js  c++  java
  • SpringCloud入门(九): Zuul 上传&回退&异常处理&跨域

    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);
        }
    }
  • 相关阅读:
    【LeetCode】456. 132 Pattern
    【Python&Sort】QuickSort
    Python虚拟环境的配置
    【LeetCode】459. Repeated Substring Pattern
    【LeetCode】462. Minimum Moves to Equal Array Elements II
    【LeetCode】20. Valid Parentheses
    radio 获取选中值
    页面加载时自动执行(加载)js的几种方法
    加一个字段: updateTime 更新时间
    多用户同时处理同一条数据解决办法
  • 原文地址:https://www.cnblogs.com/jiangyaxiong1990/p/12649664.html
Copyright © 2011-2022 走看看