Skip to content

Instantly share code, notes, and snippets.

@rolroralra
Last active July 13, 2022 09:47
Show Gist options
  • Save rolroralra/3d2ad210fb6e5a1db64dd7d29b9091ae to your computer and use it in GitHub Desktop.
Save rolroralra/3d2ad210fb6e5a1db64dd7d29b9091ae to your computer and use it in GitHub Desktop.
Java

@Valid

https://cchoimin.tistory.com/entry/Valid-%EC%84%B8%ED%8C%85-%EB%B0%8F-%EC%82%AC%EC%9A%A9%EB%B2%95


lombok annotations

https://www.daleseo.com/lombok-useful-annotations/

  • @NonNull

롬복에서 제공하는 @NonNull은 메서드의 인자에 사용하면 null이 들어올 시 NullPointerException을 발생시킨다.


Optional 올바르게 사용하기

https://homoefficio.github.io/2019/10/03/Java-Optional-%EB%B0%94%EB%A5%B4%EA%B2%8C-%EC%93%B0%EA%B8%B0/


Generic explicit type parameter

https://stackoverflow.com/questions/15629552/uses-for-the-strange-looking-explicit-type-argument-declaration-syntax-in-java


Java Developer Roadmap

Details

Java Developer Roadmap


Enum

https://www.baeldung.com/a-guide-to-java-enums


CGLib (Code Generator Library) (Proxy Bean)

https://javacan.tistory.com/entry/114

https://nhj12311.tistory.com/469


Try With Resources

https://hianna.tistory.com/546


Servlet

https://mangkyu.tistory.com/14

https://jeong-pro.tistory.com/222


@RequiredArgsConstructor, @Qualifier

https://stackoverflow.com/questions/38549657/is-it-possible-to-add-qualifiers-in-requiredargsconstructoronconstructor

https://www.inflearn.com/questions/71872


✅ Jasypt (Java Simplified Encryption)

https://velog.io/@sixhustle/Jasypt

Details

@Configuration
@EnableConfigurationProperties(JasyptConfigProperties.class)
@RequiredArgsConstructor
public class JasyptConfig {
    private final JasyptConfigProperties jasyptConfigProperties;

    @Bean(name = "jasyptStringEncryptor")
    public StringEncryptor stringEncryptor() {
        PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
        SimpleStringPBEConfig config = new SimpleStringPBEConfig();

        config.setPassword(System.getProperty("jasypt.encryptor.password"));
        config.setAlgorithm(jasyptConfigProperties.getAlgorithm());
        config.setKeyObtentionIterations(jasyptConfigProperties.getKeyObtentionIterations());
        config.setIvGeneratorClassName(jasyptConfigProperties.getIvGeneratorClassName());
        config.setPoolSize(jasyptConfigProperties.getPoolSize());
        config.setSaltGeneratorClassName(jasyptConfigProperties.getSaltGeneratorClassName());
        config.setStringOutputType(jasyptConfigProperties.getStringOutputType());
        encryptor.setConfig(config);
        return encryptor;
    }
}
@Component
@ConfigurationProperties(value = "jasypt.encryptor")
@Data
public class JasyptConfigProperties {
    private String algorithm = "PBEWITHHMACSHA512ANDAES_256";
    private String keyObtentionIterations = "1000";
    private String poolSize = "1";
    private String saltGeneratorClassName = "org.jasypt.salt.RandomSaltGenerator";
    private String stringOutputType = "base64";
    private String ivGeneratorClassName = "org.jasypt.iv.RandomIvGenerator";
}
bootRun {
	if ( project.hasProperty('jvmArgs') ) {
		jvmArgs = (project.jvmArgs.split("\\s+") as List)
	}
}		
jasypt:
  encryptor:
    bean: jasyptStringEncryptor
    password: password.         # VM Options을 통해서 실행하면 생략가능.
# Way1. Application run (Add VM Options)
$ java -jar xxx.jar -Djasypt.encrpytor.password=password
		
# Way2. gradle bootrun
$ gradle bootRun -PjvmArgs="-Djasypt.encryptor.password=password"


✅ Guava (Guava: Google Core Libraries for Java)

https://blog.outsider.ne.kr/710

pom.xml

<dependency>
  <groupId>com.google.guava</groupId>
  <artifactId>guava</artifactId>
  <version>31.0.1-jre</version>
  <!-- or, for Android: -->
  <version>31.0.1-android</version>
</dependency>

build.gradle

dependencies {
  // Pick one:

  // 1. Use Guava in your implementation only:
  implementation("com.google.guava:guava:31.0.1-jre")

  // 2. Use Guava types in your public API:
  api("com.google.guava:guava:31.0.1-jre")

  // 3. Android - Use Guava in your implementation only:
  implementation("com.google.guava:guava:31.0.1-android")

  // 4. Android - Use Guava types in your public API:
  api("com.google.guava:guava:31.0.1-android")
}


Apache Commons Lang

https://recordsoflife.tistory.com/474

pom.xml

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.12.0</version>
</dependency>		

build.gradle

implementation 'org.apache.commons:commons-lang3:3.12.0'	


GraalVM

https://giljae.medium.com/graalvm-%EC%86%8C%EA%B0%9C-84ac547f8df2

https://meetup.toast.com/posts/273


How to Install Java in Ubuntu

Details

#################################
# How to install Java in Ubuntu #
#################################

# 기존 버전 설치 여부 확인
$ java -version
$ dpkg -l | grep openjdk
$ whereis java
$ which java
 
# https://www.azul.com/downloads/zulu/ 
# Openjdk-8-jdk Local Install
$ sudo su
$ tar -xzvf java-8-openjdk-amd64.tar.gz -C /usr/lib/jvm
 
 
# /usr/bin/java 라는 파일이 없을 때, 심볼릭 링크 생성
$ ln -s /usr/lib/java-openjdk-8-amd64/bin/java /usr/bin/java
 
 
$ update-alternatives --install "/usr/bin/java" "java" "/usr/lib/jdk/java-openjdk-8-amd64/bin/java" 1
 
 
# 운영체제 Architecture 확인 방법 (amd vs arm)
$ dpkg --print-architecture
 
 
# 설치 확인
$ java -version


✅ How to get the certificate of some host

Details

$ git clone https://github.com/rolroralra/InstallCert

$ javac InstallCert.java

$ ls InstallCert*.class
InstallCert$SavingTrustManager.class   InstallCert.class

# Download Cetificate from "plugins.jetbrains.com" 
# And then Import Certificate to "$JAVA_HOME/jre/lib/security/cacerts"
$ java InstallCert plugins.jetbrains.com

$ cd $JAVA_HOME/jre/lib/security

$ keystore -exportcert -alias plugins.jetbrains.com -keystore ./cacerts -storepass changeit -file plugins.jetbrains.com.cer
	 
$ keytool -keystore ${JAVA_HOME}\jre\lib\security\cacerts -importcert -alias sds -file C:\Users\SDS\SDS.crt


✅ How to add cert to Java's keystore (for Maven Build)

Details

# get $JAVA_HOME
$ which java
$ whereis java

$ cd $JAVA_HOME/jre/lib/security;
$ keytool -import -file ${CERT_FILE_PATH} -keystore ./cacerts -storepass "changeit"


XSS 공격 방지 (Cross Site Scripting)

Detail

public final class RequestWrapper extends HttpServletRequestWrapper {
	
	public RequestWrapper(HttpServletRequest request) {
		super(request);
	}
	
	public String[] getParameterValues(String parameter) {
		String[] values = super.getParameterValues(parameter);
		if (values == null) {
			return null;
		}
		int count = values.length;
		String[] encodeValues = new String[count];
		for (int i = 0; i < count; i++) {
			encodeValues[i] = cleanXSS(values[i]);
		}
		return encodeValues;
	}
	public String getParameter(String parameter) {
		String value = super.getParameter(parameter);
		if (value == null) {
			return null;
		}
		return cleanXSS(value);
	}
	public String getHeader(String name) {
		String value = super.getHeader(name);
		if (value == null) {
			return null;
		}
		return cleanXSS(value);
	}
	
	private String cleanXSS(String value) {
		value = value.replaceAll("<",  "& lt;").replaceAll(">", "& gt;");
		value = value.replaceAll("\\(", "& #40;").replaceAll("\\),", "& 41;");
		value = value.replaceAll("'", "& #39;");
		value = value.replaceAll("eval\\((.*)\\)", "");
		value = value.replaceAll("[\\\"\\'][\\s]*javascript:", "\"\"");
		value = value.replaceAll("[\\\"\\'][\\s]*vbscript:", "\"\"");
		value = value.replaceAll("script", "");
		value = value.replaceAll("document.cookie", "&lt;&#100;&#111;&#99;&#117;&#109;&#101;&#110;&#116;&#46;&#99;&#111;&#111;&#107;&#105;&#101");
		value = value.replaceAll("<iframe", "&lt;iframe");
		value = value.replaceAll("<object", "&lt;object");
		value = value.replaceAll("<embed", "&lt;embed");
		value = value.replaceAll("onload", "no_onload");
		value = value.replaceAll("expression", "no_expression");
		value = value.replaceAll("onmouseover", "no_onmouseover");
		value = value.replaceAll("onmouseout", "no_onmouseout");
		value = value.replaceAll("onclick", "no_onclick");
		return value;
	}
}


Spring Cloud Gateway

Spring Getting Started: https://spring.io/guides/gs/gateway/

Detail

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.factory.RemoveRequestHeaderGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.RemoveResponseHeaderGatewayFilterFactory;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@Configuration
public class RouteConfig {

    @Autowired
    private Properties properties;
    
    @Bean
    public RouteLocator myRoute(RouteLocatorBuilder builder) {
    	GatewayFilter requestFilter = new RequestHistoryFilter();
	
        GatewayFilter addRequestHeaderApiServiceFilter = new AddRequestHeaderApiServiceFilter();
	
        GatewayFilter removeRequestHeaderAuthKeyFilter = 
		BeanUtil.getBean(RemoveRequestHeaderGatewayFilterFactory.class).apply(c->c.setName("Authorization"));
	
        GatewayFilter removeRequestHeaderCookieFilter = 
		BeanUtil.getBean(RemoveRequestHeaderGatewayFilterFactory.class).apply(c->c.setName("Cookie"));
        GatewayFilter removeResponseHeaderCookieFilter = 
		BeanUtil.getBean(RemoveResponseHeaderGatewayFilterFactory.class).apply(c->c.setName("cookie"));
    
    
        String[] url = {
                "/get", "/login", "/logout", "/home"
        };

        return builder.routes().route(p -> p
                .path(url)
                .uri("http://endpoint:port")
                .build();
    }
}

class AddRequestHeaderApiServiceFilter implements GatewayFilter {
    private static final Logger LOGGER = LoggerFactory.getLogger(AddRequestHeaderApiServiceFilter.class);

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest().mutate().header("HEADER_NAME", "xxx").build();
	
        return chain.filter(exchange.mutate().request(request).build());
    }
}


InputStream to OutputStream in Java

https://www.baeldung.com/java-inputstream-to-outputstream

Detail

Java 8
void copy(InputStream source, OutputStream target) throws IOException {
    byte[] buf = new byte[8192];
    int length;
    while ((length = source.read(buf)) > 0) {
        target.write(buf, 0, length);
    }
}
Java 9
@Test
public void givenUsingJavaNine_whenCopyingInputStreamToOutputStream_thenCorrect() throws IOException {
    String initialString = "Hello World!";
 
    try (InputStream inputStream = new ByteArrayInputStream(initialString.getBytes());
         ByteArrayOutputStream targetStream = new ByteArrayOutputStream()) {
        inputStream.transferTo(targetStream);
 
        assertEquals(initialString, new String(targetStream.toByteArray()));
    }
}


Lambda

Detail

// Method Reference

// 1. static method reference
IntStream.range(-10,10).map(Math::abs)
// IntStream.range(-10,10).map(x -> Math.abs(x));
IntStream.range(1,32).mapToObj(Integer::toHexString);
//IntStream.range(1,32).map(x -> Ingeger.toHexString(x));

// 2. object instance method reference
IntStream.range(1,10).forEach(System.out::println);
// IntStream.range(1,10).forEach(x -> System.out.println(x);

// 3. class instance method reference
someOperation(XClass:double)
someOperation((x, y) -> x.double(y))


Functional Interface

Detail

@FunctionalInterface
public interface Function<T, R> {
	R apply(T t);
}

@FunctionalInterface
public interface Predicate<T> {
	boolean test(T t);
}

@FunctionalInterface
public interface Supplier<T> {
	T get();
}

@FunctionalInterface
public interface Consumer<T> {
	void accept(T t);
}

@FunctionalInterface
public interface BiConsumer<T, U> {
	void accept(T t, U u);
}

@FunctionalInterface
public interface BiFunction<T, U, R> {
	R apply(T t, U u);
}

// Bifunction<T, T, T>
@FunctionalInterface
public interface BinaryOperator<T> {
	T apply(T t1, T t2);
}

/// Function<T, T>
@FunctionalInterface
public interface UnaryOperator<T> {
	T apply(T t);
}

// IntFunction<R>
@FunctionalInterface
public interface IntFunction<R> {
	R apply(int t);
}

// LongFunction<R>
@FunctionalInterface
public interface LongFunction<R> {
	R apply(long t);
}

// DoubleFunction<R>
@FunctionalInterface
public interface DoubleFunction<R> {
	R apply(double t);
}

// ToIntFunction<T>
@FunctionalInterface
public interface ToIntFunction<T> {
	int applyAsInt(T t);
}

// ToLongFunction<T>
@FunctionalInterface
public interface ToLongFunction<T> {
	long applyAsLong(T t);
}

// ToDoubleFunction<T>
@FunctionalInterface
public interface ToDoubleFunction<T> {
	double applyAsDouble(T t);
}

// ToIntBiFunction<T, U>
@FunctionalInterface
public interface ToIntBiFunction<T, U> {
	int applyAsInt(T t, U u);
}

// ToLongBiFunction<T, U>
@FunctionalInterface
public interface ToLongBiFunction<T, U> {
	long applyAsLong(T t, U u);
}

// ToDoubleBiFunction<T, U>
@FunctionalInterface
public interface ToDoubleBiFunction<T, U> {
	double applyAsDouble(T t, U u);
}


default method, static method in Interface

default method

추가된 인터페이스의 하위 호환성 보장
Class의 method가 Interface의 default method보다 우선 순위
Diamond Problem (Interface01.super.method()) 기본적으로 Java는 다중 상속(extends) 허용치 않음. 인터페이스 다중 구현은 허용.

Diamond Problem
Detail

interface MyInterface1{
   public static int num = 100;
   public default void display() {
      System.out.println("display method of MyInterface1");
   }
}
interface MyInterface2{
   public static int num = 1000;
   public default void display() {
      System.out.println("display method of MyInterface2");
   }
}
public class InterfaceExample implements MyInterface1, MyInterface2{
   public void display() {
      MyInterface1.super.display();
      //or,
      MyInterface2.super.display();
   }
   public static void main(String args[]) {
      InterfaceExample obj = new InterfaceExample();
      obj.display();
   }
}

static method

Interface에 필요한 Utility Class 따로 만들 필요 없음.

static import

Detail

import static org.junit.Assert.*;
import static java.lang.Math.*;


Stream API

http://iloveulhj.github.io/posts/java/java-stream-api.html

Detail

1. Stream 생성

카테고리 Method Type Method
Stream static of(T...), of(T), empty(), ofNullable(T)
Stream static generate(Supplier), iterate(T, UnaryOperator)
Stream static concat(Stream, Stream)
Collection 객체 instance stream(), parallelStream()
Arrays static stream(*)
IntStream, LongStream static range(int startInclusive, int endExclusive), rangeClosed(int startInclusive, int endInclusive)
Resource 객체 (BufferedReader) instance lines()
Stream <---> IntStream, LongStream, DoubleStream
// Stream<String> --> IntStream
Stream<String> stream = ...;
IntStream result = stream.mapToInt(String::length);
// IntStream --> Stream<Integer>
IntStream.range(0,5).mapToObj(Integer::valueOf);

2. Stream 중개 연산자 (무상태)

Method Return
Stream.filter(Predicate) Stream
Stream.map(Function<T,R>) Stream
Stream.flatMap(Function<T,Stream>) Stream
Stream.limit(long) Stream
Stream.skip(long) Stream
Stream.peek(Consumer) Stream

2. Stream 중개 연산자 (상태)

Method Return
Stream.sorted() Stream
Stream.distinct() Stream

3. Stream 종단 연산자

Method Return
Stream.count() long
Stream.max(Comparator) Optional
Stream.min(Comparator) Optional
Stream.findFirst() Optional
Stream.findAny() Optional
Stream.allMatch(Predicate) boolean
Stream.anyMath(Predicate) boolean
Stream.noneMatch(Predicate) boolean
   
Stream.forEach(Consumer action) void
Stream.forEachOrdered(Consumer action) void
   
Stream.reduce(BinaryOperator accumulator) Optional
Stream.reduce(T identity, BinaryOperator accumulator) T
Stream.reduce(U identity, BiFunction<U, T, U> accumulator, BinaryOperator combiner) U
   
Stream.collect(Collector<T, A, R> collector) R
Stream.collect(Supplier supplier, BiConsumer<R, T> accumulator, BiConsumer<R, R> combiner) R
Collector<T, A, R>
/**
 * @param <T> the type of input elements to the reduction operation
 * @param <A> the mutable accumulation type of the reduction operation (often
 *            hidden as an implementation detail)
 * @param <R> the result type of the reduction operation
 */
public interface Collector<T, A, R> {
	Supplier<A> supplier;
        BiConsumer<A, T> accumulator;
        BinaryOperator<A> combiner;
        Function<A, R> finisher;
}   


List<String> result = stream.collect(Collectors.toList());
Set<String> result = stream.collect(Collectors.toSet());
// Collectors.toCollection(Supplier<C>) : return Collector<T, ?, C>
TreeSet<String> result = stream.collect(Collectors.toCollection(TreeSet::new));

String result = stream.collect(Collectors.joining());
String result = stream.collect(Collectors.joining(", "));
String result = stream.collect(Collectors.joining(", ", "{", "}"));

// Collectors.toMap(Function<T,K> keyMapper, Function<T,U> valueMapper, BinaryOperator<U> mergeFunction, Supplier<M> mapFactory) => return Collector<T, ?, M>   
Collector Type
Collectors.toList() Collector<<T, ?, List>>
Collecotrs.toSet() Collector<T, ?, Set>
Collectors.toCollection(Supplier) Collector<T, ?, C>
   
Collectors.joining() Collector<Charsequence, ?, String>
Collectors.joining(Charsequence delimiter) Collector<Charsequence, ?, String>
Collectors.joining(Charsequence delimiter, Charsequence prefix, Charsequence suffix) Collector<Charsequence, ?, String>
   
Collectors.toMap(Function<T, K> keyMapper, Function<T, U> valueMapper) Collector<T, ?, Map<K, U>>
Collectors.toMap(Function<T, K> keyMapper, Function<T, U> valueMapper, BinaryOperator mergeFunction) Collector<T, ?, Map<K, U>>
Collectors.toMap(Function<T, K> keyMapper, Function<T, U> valueMapper, BinaryOperator mergeFunction, Supplier mapFactory) Collector<T, ?, M>
   
Collectors.partitioningBy(Predicate predicate) Collector<T, ?, Map<Boolean, List>>
Collectors.partitioningBy(Predicate predicate, Collector<T, A, D> downstream) Collector<T, ?, Map<Boolean, D>>
Collectors.groupingBy(Function<T, K> classifier) Collector<T, ?, Map<K, List>>
Collectors.groupingBy(Function<T, K> classifier, Collector<T, A, D> downstream) Collector<T, ?, Map<K, D>>
Collectors.groupingBy(Function<T, K> classifier, Supplier mapFactory, Collector<T, A, D> downstream) Collector<T, ?, M>


Optional<T>

http://www.tcpschool.com/java/java_stream_optional

Detail

Method Return
Optional.of(T) Optional
Optional.empty() Optional
Optional.ofNullable(T) Optional
   
Optional.get() T
Optional.isPresent boolean
Optional.isEmpty boolean
Optional.ifPresent(Consumer) void
Optional.ifPresentOrElse(Consumer, Runnable) void
   
Optional.map(Function<T,R>) Optional
Optional.flatMap(Function<T, Optional>) Optional
Optional.or(Supplier<Optional>) Optional
Optional.orElse(T) R
Optional.orElseGet(Supplier) T
Optional.orElseThrow() T
Optional.orElseThrow(Supplier) T throws X


Spliterator

https://jistol.github.io/java/2019/11/17/spliterator/


@SuppressWarnings("...")

Detail

@SuppressWarnings("all") : 모든 경고를 억제
@SuppressWarnings("cast") : 캐스트 연산자 관련 경고 억제
@SuppressWarnings("dep-ann") : 사용하지 말아야 할 주석 관련 경고 억제
@SuppressWarnings("deprecation") : 사용하지 말아야 할 메소드 관련 경고 억제
@SuppressWarnings("fallthrough") : switch문에서의 break 누락 관련 경고 억제
@SuppressWarnings("finally") : 반환하지 않는 finally 블럭 관련 경고 억제
@SuppressWarnings("null") : null 분석 관련 경고 억제
@SuppressWarnings("rawtypes") : 제네릭을 사용하는 클래스 매개 변수가 불특정일 때의 경고 억제
@SuppressWarnings("unchecked") : 검증되지 않은 연산자 관련 경고 억제
@SuppressWarnings("unused") : 사용하지 않는 코드 관련 경고 억제


Java Double Brace Initialization

Detail

Set<String> countries = new HashSet<String>() {
	{
		 add("India");
		 add("USSR");
		 add("USA");
	}
};
 
assertTrue(countries.contains("India"));


Hibernate Setting (JPA)

Detail

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
             version="2.2">
    <persistence-unit name="test">
        <properties>
			<!-- 필수 속성 -->
            <property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/>
            <property name="javax.persistence.jdbc.user" value="sa"/>
            <property name="javax.persistence.jdbc.password" value=""/>
            <property name="javax.persistence.jdbc.url" value="jdbc:h2:tcp://localhost/~/Workspace/h2-test/test"/>
            <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>

			<!-- 옵션 -->
            <property name="hibernate.show_sql" value="true"/>
            <property name="hibernate.format_sql" value="true"/>
            <property name="hibernate.use_sql_comments" value="true"/>
            <property name="hibernate.jdbc.batch_size" value="10"/>
<!--            <property name="hibernate.hbm2ddl.auto" value="create"/>-->
        </properties>
    </persistence-unit>
</persistence>


ConcurentHashMap

Details

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.LongAdder;

public class ConcurrentHashMapTest {
    public static void main(String[] args) {
        int loopSize = 30;
        CountDownLatch countDownLatch = new CountDownLatch(loopSize);
        ExecutorService tp = Executors.newFixedThreadPool(10);

//        Map<String, LongAdder> testMap = new HashMap<>();
        Map<String, LongAdder> testMap = new ConcurrentHashMap<>();

        for(int i = 0; i < loopSize; i++) {
            int selector = (i % 3);
            String type = (selector == 0) ? "HR" : (selector == 1) ? "SALES" : "IT";
            tp.submit(new Runner(type , countDownLatch, testMap));
        }

        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println(testMap.toString());
        tp.shutdown();
    }

    static class Runner implements Runnable {
        private final String runnerNo;
        private final CountDownLatch countDownLatch;
        private Map<String, LongAdder> testMap;
        Runner(String runnerNo, CountDownLatch countDownLatch, Map<String, LongAdder> testMap){
            this.runnerNo = runnerNo;
            this.countDownLatch = countDownLatch;
            this.testMap = testMap;
        }
        @Override
        public void run() {
            try {
                testMap.computeIfAbsent(runnerNo, (value) -> new LongAdder()).increment();
            } catch (Exception e){
                e.printStackTrace();
            } finally {
                countDownLatch.countDown();
            }

        }
    }
}


RMI (Remote Method Invocation) (cf. RPC)

https://0yumin.tistory.com/16
https://github.com/rolroralra/java-rmi


JMX (Java Management Extensible)

https://github.com/rolroralra/helloJMX


Serializable

https://blog.naver.com/kkson50/220564273220

https://madplay.github.io/post/why-java-serialization-is-bad


PipeInputStream, PipeOutputStream

http://wiki.gurubee.net/display/SWDEV/PipedInputStream%2C+PipedOutputStream


ExecutorService, Future, Callable

Details

  • ExecutorService
  • SingleThreadExecutor
  • ScheduledThreadPoolExecutor
  • Future
  • CompletableFuture
  • Callable

https://codechacha.com/ko/java-executors/

https://codechacha.com/ko/java-scheduled-thread-pool-executor/

https://codechacha.com/ko/java-future/

https://codechacha.com/ko/java-completable-future/


Synchronized

https://codechacha.com/ko/java-synchronized-keyword/


@Valid

https://bamdule.tistory.com/35

Details

Annotation Description
@NotNull Null 불가
@Null Null만 입력 가능
@NotEmpty Null, 빈 문자열 불가
@NotBlank Null, 빈 문자열, 스페이스만 있는 문자열 불가
@Size(min=,max=) 문자열, 배열 등의 크기가 만족하는가?
@Pattern(regex=) Regular Expression을 만족하는가?
@Max(숫자) 지정 값 이하인가?
@Min(숫자) 지정 값 이상인가?
@Positive 양수만 가능
@PositiveOrZero 양수와 0만 가능
@Negative 음수만 가능
@NegativeOrZero 음수와 0만 가능
@Digits(integer=,fraction=) 대상 수가 지정된 정수와 소수 자리 수 보다 작은가?
@DecimalMax(value=) 지정된 값(실수) 이하인가?
@DecimalMin(value=) 지정된 값(실수) 이상인가?
@Email 이메일 형식만 가능
@Future 현재보다 미래인가?
@Past 현재보다 과거인가?
@AssertFalse false인가?
@AssertTrue true인가?


How to install certificate in java keystore

https://github.com/rolroralra/InstallCert

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment