클로드의 예시

import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.client.WebClient;

import com.example.model.Data;

public class WebClientExample {

    public static void main(String[] args) {
        WebClient webClient = WebClient.create("http://example.com");

        Data data = new Data("Sample Data");

        webClient.post()
                .uri("/api/data")
                .contentType(MediaType.APPLICATION_JSON)
                .body(BodyInserters.fromValue(data))
                .retrieve()
                .bodyToMono(String.class)
                .map(ResponseEntity::ok)
                .onErrorResume(WebClientResponseException.class,
                        ex -> ex.getRawStatusCode() == 404 ? Mono.just(ResponseEntity.notFound().build()) : Mono.error(ex))
                .subscribe(response -> handleResponse(response));
    }

    private static void handleResponse(Object response) {
        System.out.println("Response received: " + response);
    }
}

 

이를 응용 하여 

 

@Configuration 에 빈으로 등록

 

private HttpClient httpClientConfig(int sec){
    int timeOut = sec * 1000;
    return HttpClient.create()
            .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, timeOut)
            .responseTimeout(Duration.ofMillis(timeOut))
            .doOnConnected(conn -> conn
                    .addHandlerLast(new ReadTimeoutHandler(timeOut, TimeUnit.MILLISECONDS))
                    .addHandlerLast(new WriteTimeoutHandler(timeOut, TimeUnit.MILLISECONDS)));
}

private ExchangeStrategies exchangeStrategiesConfig(){
    ExchangeStrategies exchangeStrategies = ExchangeStrategies.builder()
            .codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(1024*1024*50))
            .build();
    exchangeStrategies
            .messageWriters().stream()
            .filter(LoggingCodecSupport.class::isInstance)
            .forEach(writer -> ((LoggingCodecSupport)writer).setEnableLoggingRequestDetails(true));

    return exchangeStrategies;
}

private ExchangeFilterFunction logRequest(){
    return ExchangeFilterFunction.ofRequestProcessor(
            clientRequest -> {
                log.debug("Request: {} {}", clientRequest.method(), clientRequest.url());
                clientRequest.headers().forEach((name, values) -> values.forEach(value -> log.debug("{} : {}", name, value)));
                return Mono.just(clientRequest);
            }
    );
}

private ExchangeFilterFunction logResponse(){
    return ExchangeFilterFunction.ofResponseProcessor(
            clientResponse -> {
                log.debug("Response: {}", clientResponse.statusCode());
                clientResponse.headers().asHttpHeaders().forEach((name, values) -> values.forEach(value -> log.debug("{} : {}", name, value)));
                return Mono.just(clientResponse);
            }
    );
}

@Bean(name = "testWebClient")
    public WebClient testWebClient() {
        return WebClient.builder()
                .clientConnector(new ReactorClientHttpConnector(httpClientConfig(15)))
                .baseUrl("http://localhost:8080")
                .exchangeStrategies(exchangeStrategiesConfig())
                .filter(logRequest())
                .filter(logResponse())
                .build();

    }

 

어쩌다보니 필터 로깅 하는 거까지 하게 됬습니다.

 

 

 

@Service
@RequiredArgsConstructor
@Slf4j
public class Client {
    private final WebClient testWebClient;

    public Mono<String> testWebClient(final MultiValueMap<String, HttpEntity<?>> formData) {
        return testWebClient.post()
                .uri(uriBuilder -> uriBuilder
                        .path("/test")
                        .build())
                .contentType(MediaType.MULTIPART_FORM_DATA)
                .bodyValue(formData)
                .retrieve()
                .bodyToMono(String.class)
                .doOnNext(responseBody -> log.debug("Body: {}", responseBody.trim()));
    }
}

 

 

빈으로 등록한 웹클라이언트를 가져와서 서비스코딩 해주고

 

MultiValueMap<String, Object> formData = new LinkedMultiValueMap<>();

formData.add("subject", "테스트");

client.testWebClient(formData, fsr.contentLength()).subscribe(
                        responseString -> { //이하생략

 

 

반응형

가와사키병은 일본에서 처음 발견된 바이러스에 의한 감염성 질환입니다. 이 병은 일본의 가와사키 시에서 1967년에 처음 보고되어 그 이름을 따서 지어졌습니다. 주로 영유아와 어린이에게 영향을 미치며, 주요 증상은 고열, 발진, 눈의 충혈, 입안의 작은 궤양 등이 있습니다.

 

가와사키병의 원인은 여전히 명확히 알려지지 않았지만, 바이러스나 환경 요인이 관련되어 있다고 여겨집니다. 현재까지는 가와사키병을 완전히 예방하는 백신은 개발되지 않았습니다. 그러나 일부 산과나 병원에서 추천하는 예방 방법이 있습니다:

 

  1. 규칙적인 손씻기: 손씻기는 모든 전염병을 예방하는 가장 기본적이고 효과적인 방법 중 하나입니다. 특히 음식을 만들거나 먹기 전, 화장실을 다녀온 후, 코를 풀거나 기침, 재채기 후에는 손씻기를 해야 합니다.
  2. 감염된 사람과의 접촉 피하기: 가와사키병 환자와 접촉을 피하는 것이 중요합니다. 특히 발진이 있는 사람과의 접촉을 피해야 합니다.
  3. 호흡기 감염 예방: 가와사키병은 호흡기를 통해 전파될 수 있으므로, 사람들 간에 기침이나 재채기를 할 때는 입과 코를 가리는 등의 예방 수단을 취해야 합니다.
  4. 공동 사용 물품의 사용을 피하기: 학교나 어린이집 등에서 공동으로 사용되는 장난감이나 용품은 가능한한 개인용으로 구비하고, 정기적으로 청소해야 합니다.
  5. 영양 균형있는 식사: 영양이 풍부한 식사는 아이들의 면역력을 높일 수 있습니다. 신선한 과일과 채소를 섭취하고, 충분한 수분을 섭취하는 것이 중요합니다.

가와사키병은 주로 겨울과 봄철에 유행하기 때문에 이 기간에 특히 주의를 기울여야 합니다. 만약 어린이가 발진, 고열 및 다른 증상을 보인다면, 가능한 빨리 의료 전문가의 진료를 받아야 합니다.

 

반응형

MySQL: MySQL에서는 LIKE 검색을 위해 SQL 쿼리에서 다음과 같이 사용합니다.이 쿼리는 "your_column"이라는 컬럼에서 "keyword"를 포함하는 모든 레코드를 선택합니다.

 

<select id="selectByKeyword" parameterType="String" resultType="YourResultType">

SELECT * FROM your_table WHERE your_column LIKE CONCAT('%', #{keyword}, '%')

</select>

 

Oracle: Oracle에서는 LIKE 검색을 위해 다음과 같이 사용합니다.이 쿼리는 "your_column"이라는 컬럼에서 "keyword"를 포함하는 모든 레코드를 선택합니다. Oracle에서는 문자열 연결 연산자로 "||"를 사용합니다.

 

<select id="selectByKeyword" parameterType="String" resultType="YourResultType">

SELECT * FROM your_table WHERE your_column LIKE '%' || #{keyword} || '%'

</select>

 

MSSQL: MSSQL에서는 다음과 같이 LIKE 검색을 수행할 수 있습니다.이 쿼리는 "your_column"이라는 컬럼에서 "keyword"를 포함하는 모든 레코드를 선택합니다. MSSQL에서는 문자열 연결을 위해 "+"를 사용합니다.

 

<select id="selectByKeyword" parameterType="String" resultType="YourResultType">

SELECT * FROM your_table WHERE your_column LIKE '%' + #{keyword} + '%'

</select>

반응형

B2C와 B2B는 두 가지 다른 유형의 비즈니스 모델을 나타냅니다.

  1. B2C (Business-to-Consumer):
    • B2C는 기업과 소비자 간의 관계를 나타냅니다.
    • 이 모델에서 기업은 제품이나 서비스를 개인 소비자에게 직접 판매합니다.
    • 일반적으로 대부분의 소매업체, 온라인 쇼핑몰, 서비스 제공 업체 등이 B2C 비즈니스 모델을 채택합니다.
    • 예를 들어, 온라인 의류 쇼핑몰에서 개인 소비자가 옷을 구매하는 것이 B2C의 예입니다.
  2. B2B (Business-to-Business):
    • B2B는 기업 간의 관계를 나타냅니다.
    • 이 모델에서 기업은 다른 기업에 제품이나 서비스를 판매합니다.
    • 대부분의 제조업체, 도매업체, 기술 및 소프트웨어 회사 등이 B2B 비즈니스 모델을 사용합니다.
    • 예를 들어, 소프트웨어 회사가 다른 기업에게 소프트웨어 라이센스를 판매하는 것이 B2B의 예입니다.

간단히 말해서, B2C는 기업과 개인 소비자 간의 거래를 나타내고, B2B는 기업 간의 거래를 나타냅니다. 이러한 모델들은 각각 다른 시장과 고객층을 대상으로 하며, 비즈니스 전략과 마케팅 방법이 서로 다를 수 있습니다.

반응형

'궁금증' 카테고리의 다른 글

태양열 에너지를 획득하는 구조  (0) 2024.04.29

태양열 에너지를 획득하는 구조는 태양광 시스템을 사용합니다. 이 시스템은 주로 태양광 패널이라는 장치를 사용합니다. 태양광 패널은 일반적으로 다음과 같은 구성 요소로 이루어져 있어요.

  • 태양전지(솔라셀): 태양광 패널의 가장 중요한 부분이에요. 태양전지는 태양의 빛을 전기로 변환하는 역할을 합니다. 이 솔라셀은 일반적으로 실리콘 소재로 만들어져 있어요.
  • 프레임(프레임워크): 태양전지를 지지하고 보호하기 위한 구조물입니다. 프레임은 주로 알루미늄이나 강철로 만들어져 있어요.

 

  • 유리판(강화유리): 태양광 패널을 보호하고 외부 요소로부터 안전하게 유지하기 위한 투명한 판입니다. 유리판은 태양광 패널의 앞쪽에 위치하며, 고효율의 태양광 성능을 유지하는 데 도움이 됩니다.

 

  • 역률 변환 장치(인버터): 태양광 패널에서 생성된 직류 전기를 가정이나 전력 그리드에 연결할 수 있는 교류 전기로 변환하는 장치입니다. 이 장치는 발전된 전기를 일정한 전압과 주파수로 유지하고 에너지 효율성을 최적화하는 역할을 합니다.

 

태양광 패널은 일반적으로 지붕이나 대규모 태양광 발전 시설의 표면에 설치되어 태양의 에너지를 직접 수집합니다. 수집된 에너지는 인버터를 통해 교류 전기로 변환되어 건물 내 전력 네트워크에 공급되거나 전력 그리드에 연결되어 주변 지역에 전력을 공급합니다.

반응형

'궁금증' 카테고리의 다른 글

B2B , B2C 뭐가 다른거야?  (0) 2024.04.29

요즘 부하가 걸릴정도의 트레픽을 다루는 서비스를 유지보수 하는일을 하고있다.

동접자가 6000까지 올라갈 정도로 인기? 가많은 서비스 인데 업데이트 실수가 있었다.

 

 범인은 바로 index .... 

 

쿼리 튜닝에 있어 index 는 기본중에 기본인데 오늘 새로 알았던 사실을 적어본다.

 

left join on 사용자정보.userId= 주문정보.userId

 

이런식의 조인 결과가 있었는데 

 

테이블 구조는 이렇다.

 

사용자 정보 테이블

 

주문정보

 

대충 이러한 구조인데 ... 이상한점을 금방 눈치차린 사람도 있겠지만 ... 초반에는 아무런 생각조차 못하고 있었다

 

물론 사용자테이블의 userId 는 기본키라 인덱스가 걸려있었고

주문테이블의 userId 는 인덱스 생성을 한 상태

 

당연히 인덱스끼리의 조인이라 별 문제 없을줄 알았으나 이는 slowquery 를 유발 했다

 

explain 으로도 엄청난 자원을 소모 하고 있었고 그이유는 타입 int 형과 타입 char 의 서로 상이한 타입과의 조인 이었다.

 

사용자테이블의 userId 는 int, 주문테이블의 사용자 아이디는 varchar 여서 서로 문제가 되었다.

 

이는 CAST 함수를 사용해서 해결 했다.

 

left join on CAST(사용자정보.userId AS CHAR)= 주문정보.userId

 

조인하는 한쪽을 형변환 하여 조인 하니 index 가 잘 걸리는 것을 확인 하였다.

 

cast 함수를 찾아보니

 

CAST(value AS datatype)

https://www.w3schools.com/sql/func_mysql_cast.asp

인자값은 다양하게 지원 하고 있는것을 확인 했다.

 

다음에 요기나게 사용 해볼수 있을 듯

반응형

Ehache로 추가하고 삭제하고.. 글이 참 많지만

모든 캐시들을 삭제하는 건 글이 별로 없기에 작성한다!

 

Ehcache에 대한 설명과 Config 만드는 법은 아래 글을 참고!

https://kagoon.tistory.com/56

 

spring cache 를 사용 하기 위한 ehcache 사용법

강준한 입니다. 감동을 줄 뻔한 이야기로 시작해보죠. 아들이 치매에 걸린 아버지와 같이 있습니다. 아버지는 멀리 있는 새를 보고 아들에게 물었습니다, 저게 무어냐? 아들이 말하죠... 까마귀

kagoon.tistory.com

 

Class 안에 아래 코드를 적어준다!

 

@Autowired
    private CacheConfig ehcacheManager;

    public void cacheClear () {
    
        CacheManager cacheManager = ehcacheManager.EhcacheManager();
        cacheManager.getCacheNames().forEach(cacheName -> cacheManager.getCache(cacheName).clear());
        
    }

 

그럼 만들어둔 캐싱을 하나씩 불러와 결론적으로 전체 삭제가 되는 것을 확인할 수 있다!

필자의 경우 혹시 모를 실패나 성공 여부를 확인하기 위해 cacheClaer메소드 안을 try catch로 잡았고,

String을 리턴값으로 줘 확인 가능하도록 코드를 구성했다 ㅎㅎ

반응형

뒤로가기 막는 방법이 아니라

지금 페이지가 뒤로가기로 왔는지 아는 방법을 써보려고 한다!

 

// onpageshow의 경우 page 호출되면 무조건 실행됨

window.onpageshow = function (event){

    //뒤로가기로 페이지 접근했는지 확인
    if(event.persisted || (window.performance && window.performance.navigation.type == 2)){

        //쓰고 싶은 코드
        
    }
}

 

이렇게 하면 지금 해당 페이지가 뒤로가기로 접근했는지 확인할 수 있다!

하지만 막상 코드를 입력해보면 navigation.type == 2 부분이 deprecated 되어 취소선이 그어져있는 걸 볼 수 있다.

그대로 써도 기능은 하지만 영 찝찝하다면 밑에 내용으로 쓰면 된다!

 

// onpageshow의 경우 page 호출되면 무조건 실행됨

window.onpageshow = function (event){     //뒤로가기로 페이지 접근했는지 확인
    if(event.persisted || (window.performance && window.performance.navigation.type == 2) || (window.performance.getEntriesByType("navigation")[0].type == "back_forward")){

        //쓰고 싶은 코드
        
    }
}

 

if문 안에 새롭게 window.performance.getEntriesByType("navigation")[0].type == "back_forward" 가 추가된 걸 볼 수 있다.

window.performance.getEntriesByType("navigation")[0].type은 웹페이지의 탐색유형을 반환하는 코드이고,

back_foward는 해당 페이지가 뒤로가기나 앞으로가기로 왔는지 인식해준다!

 

반응형

개발중에 작은 오류 하나에 ... 헛방을 키다 기록용으로 남겨 놓습니다.

mybatis 를 이용한 DB 쿼리 조회에서 

select 안에 join 한 다른 테이블의 리스트 형을 처리 하고자 mybatis의 collection을 이용 하고 있습니다

 

<resultMap type="testVo" id="Map">
    <id property="seq" column="seq"/>
    <result property="userId" column="userId"/>
    <result property="userPw" column="userPw" />
    <collection property="info" javaType="List" ofType="myVo">
        <result property="nameSeq" column="nameSeq"/>
        <result property="testId" column="testId"/>
    </collection>
</resultMap>

resultMap 을 사용 해야 하고 컬렉션 안에는 조인 결과가 많은 리스트로 생성 됩니다

 

실행 결과는 argument type mismatch.....

 

이는 VO 와 DB테이블과 무언가의 변수차이가 난다는 에러 이므로 저와 같은 상황에서는 

myVo 에 info 라는 변수가 존재 해야 하고 info 는 List 타입이어야 해결 됬습니다.

 

반응형

+ Recent posts