서비스에 어노테이션으로 aop를 조정할 수 있다. 만약 서비스에서 로그인 관련 체크를 한다면 어노테이션을 선언하고 메서드에 어노테이션을 선언하는 것 만으로 aop 를 적용할 수 있다.

1. 인터페이스 선언 

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SecurityCheck {
}

타겟을 메서드에 준다

2. 체크할 포인트를 선언 

@Aspect
@Component
public class SecurityChecker {

  private static final Logger logger = LoggerFactory.getLogger(SecurityChecker.class);

  @Pointcut("@annotation(SecurityCheck)")
  public void checkMethodSecurity() {}

  @Around("checkMethodSecurity()")
  public Object checkSecurity (ProceedingJoinPoint joinPoint) throws Throwable {
    logger.debug("Checking method security...");
    // TODO Implement security check logics here
    Object result = joinPoint.proceed();
    return result;
  }
}

TODO 부분에 실제로 체크해야할 내용을 삽입한다.

3. 서비스 메서드에 적용 

  @SecurityCheck
  @Transactional(noRollbackFor = { UnsupportedOperationException.class })
  public Message save(String text)

Ubuntu 18.04 LTS 버전을 기준으로 한다 

1. 시스템에서 쓸 수 있는 네트워크를 확인한다. (wlan0 무선랜을 확인)

$ls /sys/class/net

eth0  lo  wlan0

2. 설정을 오픈한다 

sudo vi /etc/netplan/50-cloud-init.yaml

처음 파일을 오픈하면 이런 모습임 

network:
    ethernets:
        eth0:
            dhcp4: true
            optional: true
    version: 2

3. 파일을 편집한다. eth0 을 wlan0으로 바꾸당

network:
     wifis:
       wlan0:
         dhcp4: true
         access-points:
           "olleh_WiFi_****":
             password: "와이파이비밀번호"
     version: 2

만약 고정아이피로 하고 싶다면 아래와 같이 입력하면 된다. (dhcp4: no) 를 꼭 해주자

network:
     wifis:
       wlan0:
         dhcp4: no
         addresses: [192.168.1.16/24]
         gateway4: 192.168.1.255
         nameservers:
           addresses: [168.126.63.1,168.126.63.2]
         access-points:
           "olleh_WiFi_****":
             password: "와이파이비밀번호"
     version: 2

4. 편집후 변경사항 반영

sudo netplan apply

아이피 주소를 확인한다. 

ifconfig

웹 개발을 하다보면 리스트에서 항목 중 자식 리스트를 갖는 것을 표현하고 싶을 때 유용하게 쓸 수 있다. 

 

Course League
1코스 1부
1코스 2부
2코스 1부
2코스 2부

데이터 베이스에서 4행이 리턴된다.  1코스 = {1부, 2부} , 2코스 = {1부, 2부}

Course League
1코스 [{부=1부, 코스=1코스}, {부=2부, 코스=1코스}]
2코스 [{부=1부, 코스=2코스}, {부=2부, 코스=2코스}]

화면에서는 위와 같이 2행으로 보여주려면 어떻게 해야 할까? 

Java Stream GroupBy을 이용하여 변경할 수 있다.

 

기본 데이터 

List<Map<String, String>> list = new ArrayList<>();

Map<String, String> course1_1 = new HashMap<>();
course1_1.put("코스", "1코스");
course1_1.put("부", "1부");
Map<String, String> course2_2 = new HashMap<>();
course2_2.put("코스", "2코스");
course2_2.put("부", "2부");

Map<String, String> course2_1 = new HashMap<>();
course2_1.put("코스", "2코스");
course2_1.put("부", "1부");

Map<String, String> course1_2 = new HashMap<>();
course1_2.put("코스", "1코스");
course1_2.put("부", "2부");

list.add(course1_1);
list.add(course1_2);
list.add(course2_1);
list.add(course2_2);

Stream 에 group by  를 활용

List<Map> newList = list.stream()
  .collect(Collectors.groupingBy((map) -> map.get("코스")))
  .entrySet().stream()
  .sorted((a, b) -> b.getKey().compareTo(a.getKey()))
  .map(entry -> {
    Map map = new HashMap();
    map.put("course", entry.getKey());
    map.put("league", entry.getValue());
    return map;
  })
  .collect(Collectors.toList());

결과는 

courseAndData = {league=[{부=1부, 코스=2코스}, {부=2부, 코스=2코스}], course=2코스}
courseAndData = {league=[{부=1부, 코스=1코스}, {부=2부, 코스=1코스}], course=1코스}
computeIfAbsent​(K key, Function<? super K,​? extends V> mappingFunction)
putIfAbsent​(K key, V value)
computeIfPresent​(K key, BiFunction<? super K,​? super V,​? extends V> remappingFunction)
compute​(K key, BiFunction<? super K,​? super V,​? extends V> remappingFunction)

computeIfAbsent 와 putIfAbsent 

자바에서 맵에서 특정 키(Key)들에 항목(Value)을 넣어주고 싶은 경우가 있다. 

 

Key Value
1 KOREA
2 USA
4 JAPAN
? ?

추가되는 키가 없을 경우 함수를 호출해서 항목을 넣어줄 수 있다.

 

만약 키 값이 4 = CHINA , 5 = CANADA 를 리턴하는 함수 선언

private String getCountry(String key){
	System.out.println("@@@@@ : " + key);
	return key.equals("4") ? "CHINA" : "CANADA";
}

맵에는 1,2,3 에 대한 값만 있고, 키 리스트는 1,2,3,4,5 일 경우 

computeIfAbsent를 이용하여 4,5에 값을 넣을 수 있다.

List<String> keyList = new ArrayList<>();
keyList.add("1");
keyList.add("2");
keyList.add("3");
keyList.add("4");
keyList.add("5");

Map<String, String> map = new HashMap<>();
map.put("1", "KOREA");
map.put("2", "USA");
map.put("3", "JAPAN");

for(String s : keyList){
	map.computeIfAbsent( s, (key) -> getCountry(key) );
}

System.out.println("map = " + map);

결과는 putIfAbsent 도 동일한 결과를 보여준다

map = {1=KOREA, 2=USA, 3=JAPAN, 4=CHINA, 5=CANADA}

computeIfAbsent 와 putIfAbsent 차이

putIfAbsent는 키(Key)가 있음에도 함수를 호출함 (*단 항목을 변경하지 않음)

 

computeIfAbsent 의 결과 출력

@@@@@ : 4
@@@@@ : 5
map = {1=KOREA, 2=USA, 3=JAPAN, 4=CHINA, 5=CANADA}

putIfAbsent 의 결과 출력

@@@@@ : 1
@@@@@ : 2
@@@@@ : 3
@@@@@ : 4
@@@@@ : 5
map = {1=KOREA, 2=USA, 3=JAPAN, 4=CHINA, 5=CANADA}

computeIfPresent 와 compute

단어의 빈도 수를 체크하는 프로그램을 만들 때

어떤 단어가 몇 번 나왔는지 체크할때 유용하게 사용할 수있다.

 

text에 단어가 몇 번 나왔는지 맵에 저장, 일단 초기값은 0 이다.

String text = "KOREA KOREA USA USA USA CANADA JAPAN ";

Map<String, Integer> wordMap = new HashMap<>();

wordMap.put("KOREA", 0);
wordMap.put("USA", 0);
wordMap.put("CHINA", 0);
wordMap.put("JAPAN", 0);

 

computeIfPresent 을 이용하여 빈도 수를 계산한다.

for(String word : text.split(" ")){
	wordMap.computeIfPresent(word, (String key, Integer value) ->  ++value);
}

System.out.println("wordMap = " + wordMap);

 

결과는... 

wordMap = {USA=3, CHINA=0, JAPAN=1, KOREA=2}

computeIfPresent 와 compute 차이

위에 결과를 compute로 바꾸면 에러(NullPointerException)가 발생한다. 

CANADA가 없기 때문이다. CANADA가 없다면 결과는 동일하다. 

 

그리고 ... getOrDefault

값이 없을 때 널을 피하기 위하여 디폴트를 지정할 수 있다. 

Map<String, String> map = new HashMap<>();
map.put("1", "KOREA");
map.put("2", "USA");

System.out.println("map = " + map.getOrDefault("3", "FRANCE"));
System.out.println("map = " + map.get("3"));

결과는...

map = FRANCE
map = null
  1. HttpServletRequest.getUserPrincipal() 으로 현재 사용자 정보를 가져올 수 있다.  
  2. SecurityContextHolder로 SecurityContextHolder.getContext().getAuthentication() 
  3. 스프링 시큐리트의 @AuthenticationPrincipal이 적용된 어노테이션을 생성할 있다. 그리고 스프링에 UserDetails 구현체를 API 핸들러 메소드에 주입하여 요청

3번의 예제

@Target({ElementType.PARAMETER, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@AuthenticationPrincipal
public @interface CurrentUser {
}

Controller 에서 변환하여 사용

public ResponseEntity<ApiResult> createBoard(
            @RequestBody CreateBoardPayload payload,
            @CurrentUser SimpleUser currentUser) {
...
spring:
  datasource:
    url: jdbc:h2:tcp://localhost/~/task_agile_test
    username: sa
    password:
    driver-class-name: org.h2.Driver

  jpa:
    database-platform: org.hibernate.dialect.H2Dialect
    open-in-view: false
    hibernate:
      ddl-auto: create-drop
    properties:
      hibernate:
        show_sql: true
        format_sql: true
        
logging:
  level:
    org.hibernate.type.descriptor.sql: trace
  • spring.datasource : DB 연결정보 
  • spring.jpa.database-platform : 데이터 플래폼을 지정, 참고 
  • spring.jpa.open-in-view : osiv 웹요청이 완료될때까지 영속성을 가짐 (성능상 안 좋음)
  • spring.jpa.hibernate.ddl-auto :
    • none : No action is performed. The schema will not be generated.
    • create : create the schema, the data previously present (if there) in the schema is lost
    • create-drop : (default) create the schema with destroying the data previously present(if there). It also drop the database schema when the SessionFactory is closed.
    • update : update the schema with the given values.
    • validate : validate the schema. It makes no change in the DB.
  • spring.jpa.properties.hibernate.format_sql : 실행쿼리를 가독성있게 표현
  • spring.jpa.properties.hibernate.show-sql : 콘솔에 jpa 실행쿼리
  • logging.level.org.hibernate.type.descriptor.sql : ? 부문을 로그로 출력해줌

https://github.com/FortAwesome/vue-fontawesome

 

FortAwesome/vue-fontawesome

Font Awesome 5 Vue component. Contribute to FortAwesome/vue-fontawesome development by creating an account on GitHub.

github.com

위 링크를 참조하였음

 

NPM 으로 설치

$ npm i --save @fortawesome/fontawesome-svg-core
$ npm i --save @fortawesome/free-solid-svg-icons
$ npm i --save @fortawesome/vue-fontawesome

vue /src/main.js 에서 설정

import { library as faLibrary } from '@fortawesome/fontawesome-svg-core'
import { faHome, faSearch, faPlus } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'

// Set up FontAwesome
faLibrary.add(faHome, faSearch, faPlus)
Vue.component('font-awesome-icon', FontAwesomeIcon)

화면에서 사용

<font-awesome-icon icon="plus" />
  • 자바 설치하기 
  • 타임존 변경
  • 호스트 이름 변경

자바설치하기

sudo yum install -y java-1.8.0-openjdk-devel.x86_64

java 11 의 경우 

sudo amazon-linux-extras install java-openjdk11

 

설치가  완료되면 인스턴스의 자바 버전을 변경

sudo /usr/sbin/alternatives --config java

타임존 변경

sudo rm /etc/localtime sudo 
ln -s /usr/share/zoneinfo/Asia/Seoul /etc/localtime

date 로 변경을 확인

Hostname 변경

sudo vim /etc/sysconfig/network

HOSTNAME=원하는 이름

 

* amazon ami 2 는 다르다

sudo hostnamectl set-hostname webserver.mydomain.com

 

호스트 파일도 변경해준다

sudo vim /etc/hosts

127.0.0.1    원하는 이름

 

이후 reboot 하고 적용을 확인한다

+ Recent posts