Configuração de Dependências
<properties>
<spring.boot.version>2.5.5</spring.boot.version>
<lombok.version>1.18.16</lombok.version>
</properties>
<dependencies>
<!--Inicialização do Spring Boot-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>${spring.boot.version}</version>
</dependency>
<!--Spring Boot Web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${spring.boot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
<version>${spring.boot.version}</version>
</dependency>
<!--Ferramenta Lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
<!-- Dependências OSS específicas para cada projeto conforme necessário -->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.10.2</version>
</dependency>
<!--Dependências de teste-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.3.26-SNAPSHOT</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
<version>${spring.boot.version}</version>
<scope>test</scope>
</dependency>
<!--Guava-->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>30.1-jre</version>
</dependency>
</dependencies>
appliaction.propreties
server.port=8001
spring.application.name=Servico-SMS
#----Configuração de SMS-------
sms.codigo-app=8b620f10437441f5889d91caa0267a06
sms.id-template=JM1000372
ServicoSMS
import com.xtw.config.ConfiguracaoSMS;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
@Component
@Slf4j
public class ServicoSMS {
@Autowired
private RestTemplate modeloRestTemplate;
@Autowired
private ConfiguracaoSMS configuracaoSms;
/**
* Modelo de URL para API de envio de SMS
*/
private static final String MODELO_URL = "https://jmsms.market.alicloudapi.com/sms/send?mobile=%s&templateId=%s&value=%s";
/**
* Enviar código de verificação
*/
public void enviar(String destinatario, String template, String valor){
String url = String.format(MODELO_URL, destinatario, template, valor);
HttpHeaders cabecalhosHttp = new HttpHeaders();
cabecalhosHttp.set("Authorization","APPCODE "+configuracaoSms.getCodigoApp());
HttpEntity<Object> entidade = new HttpEntity<>(cabecalhosHttp);
ResponseEntity<String> respostaEntidade = modeloRestTemplate.exchange(url, HttpMethod.POST, entidade, String.class);
if(respostaEntidade.getStatusCode().is2xxSuccessful()){
log.info("Código de verificação enviado com sucesso");
}else {
log.error("Falha no envio do SMS: {}",respostaEntidade.getBody());
}
}
}
ConfiguracaoSMS
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@ConfigurationProperties(prefix = "sms")
@Configuration
@Data
public class ConfiguracaoSMS {
/**
* Código de app para envio de SMS
*/
private String codigoApp;
/**
* ID do template de conteúdo SMS
*/
private String idTemplate;
}
ConfiguracaoRestTemplate (Usando protooclo HTTP para requisições)
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
@Configuration
public class ConfiguracaoRestTemplate {
@Bean
public RestTemplate modeloRestTemplate(ClientHttpRequestFactory fabricaRequisicaoHttp){
return new RestTemplate(fabricaRequisicaoHttp);
}
@Bean
public ClientHttpRequestFactory fabricaRequisicaoHttp(){
return new HttpComponentsClientHttpRequestFactory();
}
@Bean
public HttpClient clienteHttp(){
Registry<ConnectionSocketFactory> registro = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.getSocketFactory())
.register("https", SSLConnectionSocketFactory.getSocketFactory())
.build();
PoolingHttpClientConnectionManager gerenciadorConexao = new PoolingHttpClientConnectionManager(registro);
//Define o máximo de 500 conexões no pool
gerenciadorConexao.setMaxTotal(500);
//MaxPerRoute é uma subdivisão do maxtotal, com máximo de 300 conexões por host
gerenciadorConexao.setDefaultMaxPerRoute(300);
RequestConfig configuracaoRequisicao = RequestConfig.custom()
//Timeout para recebimento de dados
.setSocketTimeout(20000)
//Timeout para conexão com o servidor
.setConnectTimeout(10000)
//Timeout para obter conexão do pool
.setConnectionRequestTimeout(1000)
.build();
return HttpClientBuilder.create().setDefaultRequestConfig(configuracaoRequisicao)
.setConnectionManager(gerenciadorConexao)
.build();
}
}
Testes
import com.xtw.AplicacaoSms;
import com.xtw.component.ServicoSMS;
import com.xtw.config.ConfiguracaoSMS;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest(classes= AplicacaoSms.class)
@Slf4j
public class TestesSms {
@Autowired
private ConfiguracaoSMS configuracaoSms;
@Autowired
private ServicoSMS servicoSms;
@Test
public void testarPropriedades(){
System.out.println(configuracaoSms.getCodigoApp());
}
@Test
public void testarEnvio(){
servicoSms.enviar("15070159890", configuracaoSms.getIdTemplate(), "652421");
}
}
Configuração Assíncrona
@Configuration
@EnableAsync
public class ConfiguracaoTarefaAssincrona {
@Bean("executorTarefaPool")
public ThreadPoolTaskExecutor executorTarefaPool(){
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
//Número de threads principais
executor.setCorePoolSize(16);
//Capacidade da fila de bloqueio
executor.setQueueCapacity(3000);
//Número máximo de threads
executor.setMaxPoolSize(300);
//Tempo de vida de threads não principais ociosas (30s)
executor.setKeepAliveSeconds(30);
//Se allowCoreThreadTimeout=true, threads principais também serão liberadas
executor.setAllowCoreThreadTimeOut(false);
//Prefixo do nome da thread
executor.setThreadNamePrefix("PoolThreadsPersonalizados-");
//Política de tratamento de estouro de threads
//CallerRunsPolicy(): A thread que chamou executa a tarefa
//AbortPolicy(): Política padrão, lança RejectedExecutionException
//DiscardPolicy(): Descarta a tarefa sem exceção
//DiscardOldestPolicy(): Descarta a tarefa mais antiga na fila
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
//Inicialização
executor.initialize();
return executor;
}
}
Utilização Assíncrona
@Async("executorTarefaPool")
public void enviar(String destinatario, String template, String valor) {
String url = String.format(MODELO_URL, destinatario, template, valor);
HttpHeaders cabecalhosHttp = new HttpHeaders();
cabecalhosHttp.set("Authorization","APPCODE "+configuracaoSms.getCodigoApp());
HttpEntity<Object> entidade = new HttpEntity<>(cabecalhosHttp);
ResponseEntity<String> respostaEntidade = modeloRestTemplate.exchange("http://localhost:8002/api/visit_stats/v1/str", HttpMethod.POST, entidade, String.class);
if(respostaEntidade.getStatusCode().is2xxSuccessful()){
log.info("Código de verificação enviado com sucesso");
}else {
log.error("Falha no envio do SMS: {}",respostaEntidade.getBody());
}
}