RestTemplate上传文件

1、HttpPoolProperties 类

@Component
//@PropertySource(value= {"classpath:properties/httpConfig.properties"})
//@ConfigurationProperties(prefix = "http.pool.conn")
@Data
public class HttpPoolProperties {

    // 最大连接数
    private Integer maxTotal = 20;

    // 同路由并发数
    private Integer defaultMaxPerRoute =20 ;

    private Integer connectTimeout = 2000;

    private Integer connectionRequestTimeout=2000;

    private Integer socketTimeout= 2000;

    // 线程空闲多久后进行校验
    private Integer validateAfterInactivity= 2000;

    // 重试次数
    private Integer retryTimes = 2;

    // 是否开启重试
    private boolean enableRetry = true;

    // 重试的间隔:可实现 ServiceUnavailableRetryStrategy 接口
    private Integer retryInterval= 2000;

}

2、HttpClientPoolUtils 类

@Configuration
public class HttpClientPoolUtils {
    @Autowired
    private HttpPoolProperties httpPoolProperties;

    /**
     * 首先实例化一个连接池管理器
     * 设置最大连接数、并发连接数
     * @return
     */
    @Bean(name = "httpClientConnectionManager")
    public PoolingHttpClientConnectionManager getHttpClientConnectionManager(){
        Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", PlainConnectionSocketFactory.getSocketFactory())
                .register("https", SSLConnectionSocketFactory.getSocketFactory())
                .build();

        PoolingHttpClientConnectionManager httpClientConnectionManager = new PoolingHttpClientConnectionManager(registry);
        //最大连接数
        httpClientConnectionManager.setMaxTotal(httpPoolProperties.getMaxTotal());
        //并发数
        httpClientConnectionManager.setDefaultMaxPerRoute(httpPoolProperties.getDefaultMaxPerRoute());

        httpClientConnectionManager.setValidateAfterInactivity(httpPoolProperties.getValidateAfterInactivity());

        return httpClientConnectionManager;
    }

    /**
     * 实例化连接池,设置连接池管理器。
     * 这里需要以参数形式注入上面实例化的连接池管理器
     * @param httpClientConnectionManager
     * @return
     */
    @Bean(name = "httpClientBuilder")
    public HttpClientBuilder getHttpClientBuilder(@Qualifier("httpClientConnectionManager")PoolingHttpClientConnectionManager httpClientConnectionManager){

        //HttpClientBuilder中的构造方法被protected修饰,所以这里不能直接使用new来实例化一个HttpClientBuilder,可以使用HttpClientBuilder提供的静态方法create()来获取HttpClientBuilder对象
        HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();

        httpClientBuilder.setConnectionManager(httpClientConnectionManager);

        if (httpPoolProperties.isEnableRetry()){
            // 重试次数
            httpClientBuilder.setRetryHandler(new DefaultHttpRequestRetryHandler(httpPoolProperties.getRetryTimes(), true));
            // 若需要自定义http 的重试策略,可以重新实现ServiceUnavailableRetryStrategy 或 HttpRequestRetryHandler接口,比如对指定异常或制定状态码进行重试,并指定充实的次数。
        }else {
            httpClientBuilder.disableAutomaticRetries();
        }
        // 另外httpClientBuilder 可以设置长连接策略,dns解析器,代理,拦截器以及UserAgent等等。可根据业务需要进行实现

        return httpClientBuilder;
    }


    /* 注入连接池,用于获取httpClient
     * @param httpClientBuilder
     * @return
     */
    @Bean("httpClient")
    public CloseableHttpClient httpClient(@Qualifier("httpClientBuilder") HttpClientBuilder httpClientBuilder){
        return httpClientBuilder.build();
    }

    /**
     * Builder是RequestConfig的一个内部类
     * 通过RequestConfig的custom方法来获取到一个Builder对象
     * 设置builder的连接信息
     * 这里还可以设置proxy,cookieSpec等属性。有需要的话可以在此设置
     * @return
     */
    @Bean(name = "builder")
    public RequestConfig.Builder getBuilder(){
        RequestConfig.Builder builder = RequestConfig.custom();
        return builder.setConnectTimeout(httpPoolProperties.getConnectTimeout()) //连接上服务器(握手成功)的时间,超出抛出connect timeout
                //从连接池中获取连接的超时时间,超时间未拿到可用连接,会抛出org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool
                .setConnectionRequestTimeout(httpPoolProperties.getConnectionRequestTimeout())
                //服务器返回数据(response)的时间,超过抛出read timeout
                .setSocketTimeout(httpPoolProperties.getSocketTimeout());
    }

    /**
     * 使用builder构建一个RequestConfig对象
     * @param builder
     * @return
     */
    @Bean
    public RequestConfig getRequestConfig(@Qualifier("builder") RequestConfig.Builder builder){
        return builder.build();
    }

    /**
     * RestTemplate 指定httpClient 及连接池
     *
     * @param httpClient
     * @return
     */
    @Bean(name = "httpClientTemplate")
    public RestTemplate restTemplate(@Qualifier("httpClient") CloseableHttpClient httpClient) {
        HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
        factory.setHttpClient(httpClient);
        RestTemplate restTemplate = new RestTemplate();
        restTemplate.setRequestFactory(factory);
        restTemplate.getMessageConverters().add(new StringHttpMessageConverter());
        return restTemplate;
    }

    // pool监测线程,定期移除过期连接、空闲连接
/*
    public static class IdleConnectionMonitorThread extends Thread {

        private final HttpClientConnectionManager connMgr;
        public IdleConnectionMonitorThread(HttpClientConnectionManager connMgr) {
            super();
            this.connMgr = connMgr;
        }

        @Override
        public void run() {
            try {
                while (true) {
                    synchronized (this) {
                        Thread.sleep(5000);
                        connMgr.closeExpiredConnections();
                        connMgr.closeIdleConnections(5, TimeUnit.SECONDS);
                    }
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
*/
}

3、IdleConnectionEvictor 类

@Component
public class IdleConnectionEvictor extends Thread{
    @Autowired
    private HttpClientConnectionManager connMgr;

    private volatile boolean shutdown;

    public IdleConnectionEvictor() {
        super();
        super.start();
    }

    @Override
    public void run() {
        try {
            while (!shutdown) {
                synchronized (this) {
                    wait(5000);
                    // 关闭失效的连接
                    connMgr.closeExpiredConnections();
                }
            }
        } catch (InterruptedException ex) {
            // 结束
        }
    }

    //关闭清理无效连接的线程
    public void shutdown() {
        shutdown = true;
        synchronized (this) {
            notifyAll();
        }
    }
}

4、Service 类



public interface Service<T> {

    public void UploadFile(List<T> list);
}

5、ServiceImpl 类

@Service
@Transactional(rollbackFor = Exception.class)
public class ServiceImpl<T> implements Service<T> {

    @Autowired
    private RestTemplate httpClientTemplate;

    @Async
    @Override
    public void UploadFile(List<T> list) {
        if(list.size() == 0){
            return;
        }else{
            final String url = "http://localhost:8888/fileManager/gz";
            // 设置请求头
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.MULTIPART_FORM_DATA);
            // 设置请求体,注意是 LinkedMultiValueMap
            MultiValueMap<String, Object> form = new LinkedMultiValueMap<>();
            list.forEach(e->{
                form.add("file",new FileSystemResource(e.toString()));
            });
            HttpEntity<MultiValueMap<String, Object>> files = new HttpEntity<>(form, headers);
            httpClientTemplate.postForObject(url, files, JSONObject.class);
        }

    }
}

6、FileManagerController 接收Controller

@RestController
@RequestMapping("/fileManager")
public class FileManagerController {

    @RequestMapping("/gz")
    public Map fileUpload(@RequestParam("file") MultipartFile[] files, HttpServletRequest request) throws Exception {
        for (MultipartFile file : files) {
            if (!file.isEmpty() && file.getSize() > 0) {
                String fileName = file.getOriginalFilename();
                File dest = new File(new File("C:\\files").getAbsolutePath()+ "/" + fileName);
                if (!dest.getParentFile().exists()) {
                    dest.getParentFile().mkdirs();
                }
                file.transferTo(dest);
            }
        }
        Map<String,String> map = new HashMap<>();
        map.put("200","ok");
        return map;
    }

}

7、测试类

@SpringBootTest(classes= IndexApplication.class)
@RunWith(SpringRunner.class)
public class IndexTest {

    @Resource
    private Service service;

    @Test
    public void testUploadFile(){
        List<String> list = new ArrayList<>();
        list.add("C:\\Users\\Pictures\\Saved Pictures\\tupian\\图片1.png");
        list.add("C:\\Users\\Pictures\\Saved Pictures\\tupian\\图片2.png");
        service.UploadFile(list);
    }

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值