구분자 사용해서 뽑아오기
\구분자
`(single qutoation)로 감싸주면 됨 `{print $열번호}`

cat test.txt | awk -F \| '{print $4","$5","$6","$17","$18}' > busan.csv

원본 :

26110|2608|2611010100|부산광역시|중구|영주동|261103006001|초량상로|0|1|4||48910|근린생활시설|0|영주제1동|1139873.245417|1680775.057503

결과

$ cat busan.csv
부산광역시,중구,영주동,1139873.245417,1680775.057503

'BackEnd > Linux' 카테고리의 다른 글

Yum Repository 만들기 (2)  (0) 2019.12.24
Yum Repository 만들기 (1)  (0) 2019.12.23
[Linux]NoLogin  (0) 2019.10.08
Swap 메모리 늘리기  (0) 2019.09.17
cache 삭제하기  (0) 2019.08.27

스파크 SQL 을 파일로 보내기
coalesce(1) 을 해주는 이유는 RDD 로 분산되어있는 파티션을 하나로 모아주기 위해서

 session.sql("select * from temp").coalesce(1).write().format("com.databriccks.spark.csv").option("header","true").csv("./data/morris.csv");

인프런 백기선님의 SpringMVC 강의를 보고 정리한 내용입니다.
DispatcherServlet

이전의 글에서 SpringWebMVC에서는 FrontController로 DispatcherServlet 이라는 것구현해놓았다고 했다.

mvc context hierarchy

ServletWebApplicationContext 에서 Controller 설정만 가지고 와서 특정 url에 따른 처리를 해주고

Root WebApplicationContext 에는 Service, Repository 는 모든곳에서 사용할 수 있게 구분을 할 수 있게 하는 구조로 되어있다.

DispatcherServlet 사용하기

위와 같이 Controller는 ServletWebApplicationContext에 등록하고, Service,Repository의 설정은 Root WebApplication에 등록을 해주기

web.xml

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
  <display-name>Archetype Created Web Application</display-name>

  <context-param>
    <param-name>contextClass</param-name>
    <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
  </context-param>

  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>me.morris.AppConfig</param-value>
  </context-param>

  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>

  <servlet>
    <servlet-name>app</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextClass</param-name>
      <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
    </init-param>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>me.morris.WebConfig</param-value>
    </init-param>
  </servlet>

  <servlet-mapping>
    <servlet-name>app</servlet-name>
    <url-pattern>/app/*</url-pattern>
  </servlet-mapping>

</web-app>

AppConfig.java : Controller를 제외한 ApplicationContext

WebConfig.java : Controller를 포함한 ApplicationContext

AppConfig.java

package me.morris;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Controller;

@Configuration
@ComponentScan(excludeFilters = @ComponentScan.Filter(Controller.class))
public class AppConfig {

}

WebConfig.java

package me.morris;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Controller;

@Configuration
@ComponentScan(useDefaultFilters = false, includeFilters = @ComponentScan.Filter(Controller.class))
public class WebConfig {

}

HelloController.java

package me.morris;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {
    @Autowired
    HelloService helloService;
    @GetMapping("/hello")
    public String hello(){
        return "Hello, "+ helloService.getName();
    }
}

HelloService.java

package me.morris;

import org.springframework.stereotype.Service;

@Service
public class HelloService {
    public String getName(){
        return "morrisKim";
    }
}

이렇게 RootWebApplicationContext와 Servlet WebapplicattionContext에 나눠서 설정을 할 수 있다.


간단하게 하면 Root WebApplicationContext에 Controller와 Service, Repository 등을 전부 등록하여 사용이 가능하다.

web.xml

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>

  <servlet>
    <servlet-name>app</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextClass</param-name>
      <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
    </init-param>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>me.morris.WebConfig</param-value>
    </init-param>
  </servlet>

  <servlet-mapping>
    <servlet-name>app</servlet-name>
    <url-pattern>/app/*</url-pattern>
  </servlet-mapping>

</web-app>

WebConfig.java : ComponentScan을 전체로 등록함

package me.morris;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Controller;

@Configuration
@ComponentScan
public class WebConfig {

}

IOC Container 연동

인프런 Spring WEB MVC 강의를 듣고 정리 한 내용입니다.

SpringIOC 를 Servlet에 연동을 하려고한다.

maven 의 pom.xml 의존성을 추가함

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-webmvc</artifactId>
  <version>5.1.3.RELEASE</version>
</dependency>

web.xml 변경

  • 이전 서블릿에서 사용했던 servlet listener (ServletContextListener 구현체) 대신에 Spring에서 지원하는 ContextLoaderListener로 변경 해줌

변경 전

<listener>
  <listener-class>me.morris.MyListener</listener-class>
</listener>

spring에서 지원하는 org.springframework.web.context.ContextLoaderListener

: 스프링 IOC 컨테이너 applicationcontext 를 servlet의 생명주기에 맞춰서 servletcontext에 등록해주고 , 종료할때 applicationcontext를 제거하는 역할을 함

변경 후

<listener>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

applicationcontext의 위치, 파일 을 파라미터로 지정해줘야함

contextClass 등록

ContextLoader를 통해 ApplicationContext를 등록 해줘야한다.

web.xml

contextClass : applicationContext를 어떤 방법으로 등록을 할것인가?(Java Configure, Xml Configure ...)

<context-param>
  <param-name>contextClass</param-name>
  <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</context-param>

<context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>me.morris.AppConfig</param-value>
</context-param>

me.morris.AppConfig.java

package me.morris;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan
public class AppConfig {

}

HelloService.java 서비스 빈으로 등록

package me.morris;

import org.springframework.stereotype.Service;

@Service
public class HelloService {
    public String getName(){
        return "morrisKim";
    }
}

web.xml에 아래와 같이 오류가 난다고 한다면??아래의 순서대로 태그를 나열하면 해결된다.

The content of element type "web-app" must match "(icon?,display-name?,description?,distributable?,context-param*,filter*,filter-mapping*,listener*,servlet*,servlet-mapping*,session-config?,mime-mapping*,welcome-file-list?,error-page*,taglib*,resource-env-ref*,resource-ref*,security-constraint*,login-config?,security-role*,env-entry*,ejb-ref*,ejb-local-ref*)".

Web ApplicationContext 불러오기

아래를 보면 ContextLoaderListener.class가 initwebApplicationContext를 통하여 context를 지정해준다.

99 servletContext.setAttribute(applicationContextName, context);

servletContext에 등록이 되는 것을 알 수 있다.

그 이후에는 이전에 만들었던 HelloServlet.java 클래스로 이동해서 doGet메서드에 서 ApplicationContext를 불러 와보자.

servletContext에 WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE 라는 이름으로 ApplicationContext가 등록이 되어있으므로, 아래와 같이 불러와서 BeanFactory에서 HelloService.class 를 불러와서 사용이 가능하다.

HelloServlet.java

...
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

  ApplicationContext context = (ApplicationContext) getServletContext().getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
  HelloService helloService = context.getBean(HelloService.class);

  System.out.println("doGet");
  resp.getWriter().println("" +
                           "<html>\n" +
                           "<body>\n" +
                           "<h2>Hello Servlet!" +helloService.getName()+"</h2>\n" +
                           "</body>\n" +
                           "</html>\n");
}
...

이로써 IOC 컨테이너를 Servlet에서 사용 할 수 있는 방법을 알 아 볼 수 있었다.

url 하나당 서블릿 하나씩 만들어 나간다면, 설정이 계속 추가가 되며, 여러 서블릿에서 공통적으로 쓰는 것들을 어떻게 해결을 할수 있을까?

그래서 나온것이 FrontController

FrontController의 역할을 하는 하나의 Servlet을 설정해주고 url을 구분하는 방법을 나타냄

SpringWebMVC에서는FrontController로 DispatcherServlet 이라는 것구현해놓았다.

Servlet 애플리케이션 개발

웹 MVC 시작하기

처음 프로젝트 시작을 maven-archetype-webapp 으로 시작

Pom.xml에 servlet-api 디펜던시 추가

<dependency>
    <groupId>javax.servlet</groupId>
  <artifactId>javax.servlet-api</artifactId>
  <version>4.0.1</version>
  <scope>provided</scope>
</dependency>

provided 는 개발할때만 사용되고, 빌드 될때는 빠진다. 이유는 tomcat 에서 구현이 될것이다.

Servlet 생성

web.xml 파일

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>

  <servlet>
    <servlet-name>hello</servlet-name>
    <servlet-class>me.morris.HelloServlet</servlet-class>
  </servlet>


  <servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello</url-pattern>
  </servlet-mapping>

</web-app>

me.morris 패키지 HelloServlet.java

package me.morris;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class HelloServlet extends HttpServlet {

    @Override
    public void init() throws ServletException {
        System.out.println("init");
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("doGet");
        resp.getWriter().println("" +
                "<html>\n" +
                "<body>\n" +
                "<h2>Hello Servlet!</h2>\n" +
                "</body>\n" +
                "</html>\n");

    }

    @Override
    public void destroy() {
        System.out.println("Destroy");
    }
}

톰캣을 사용하여 실행 하면 처리가 됨

Init 메소드는 처음에 요청시에만 출력

Destroy는 tomcat servlet콘테이너가 종료 될때 실행

Servlet Listener와 Filter

Servlet Listener :

  • 웹 어플리케이션에서 발생하는 주요 이벤트를 감지하고, 각 이벤트에 특별한 작업이 필요한 경우에 사용 할 수 있다.
    • 서블릿 컨택스트 수준의 이벤트
      • 컨텍스트 라이프사이클 이벤트
      • 컨텍스트 애트리뷰트 변경 이벤트
    • 세션 수준의 이벤트
      • 세션 라이프 사이클 이벤트
      • 세션 애트리뷰트 변경 이벤트

Servlet Container가 시작될때, DatabaseConnection을 미리 만들어놓고, 다양한 servlet에서 생성할 수 있다.

Servlet attribute에 DatabaseConnection을 미리 만들어 놓을 수 있다.

구현

아래는 Servlet Context의 라이프사이클 변경에 대한 이벤트 를 감지 한것

MyListener.java 추가 하기

public class MyListener implements ServletContextListener {
    //Servlet Container의 라이프 사이클의 이벤트를 감지
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("contextInitialized ");
        sce.getServletContext().setAttribute("name","morriskim");
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        System.out.println("contextDestroyed");
    }
}

web.xml 에 listener 태그 추가

<listener>
  <listener-class>me.morris.MyListener</listener-class>
</listener>

결과 :

[2020-03-01 06:39:52,389] Artifact SpringWebMVC:war exploded: Artifact is being deployed, please wait...
contextInitialized <-- 여기 추가된것을 알수 있다.
[2020-03-01 06:39:52,781] Artifact SpringWebMVC:war exploded: Artifact is deployed successfully
[2020-03-01 06:39:52,782] Artifact SpringWebMVC:war exploded: Deploy took 393 milliseconds
01-Mar-2020 18:40:02.244 정보 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory [/Users/daeyunkim/Documents/03.util/apache-tomcat-8.5.42/webapps/manager]
01-Mar-2020 18:40:02.281 정보 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory [/Users/daeyunkim/Documents/03.util/apache-tomcat-8.5.42/webapps/manager] has finished in [37] ms
init
doGet

Servlet Filter :

  • 들어온 요청을 서블릿으로 보내고, 또 서블릿이 작성한 응답을 클라이언트로 보내기 전에 특별한 처리가 필요한 경우에 사용 할 수 있다.
  • 체인 형태의 구조

어떠한 요청이 들어왔을때, 요청, 응답에 있어서 전에 처리를 하고 싶은 경우, 여러개의 서블릿에 추가적으로 할 수 있다.

구현

MyFilter.java 추가

  • 주의 해야할점 : javax.servlet의 Filter를 implements 해야됨
    doFilter의 파라미터 들의 값을 보면 ServletRequest request, ServletResponse response, FilterChain chain 을 들어간것을 볼수 있다.
    여기에서는 Filterchain이 request,response를 연결 해줘야한다.

    package me.morris;

    import javax.servlet.*;
    import java.io.IOException;

    public class MyFilter implements Filter {

      @Override
      public void init(FilterConfig filterConfig) throws ServletException {
          System.out.println("Filter init");
      }
    
      @Override
      public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
          System.out.println("Filter ");
          chain.doFilter(request,response);
      }
    
      @Override
      public void destroy() {
          System.out.println("Filter destroy");
      }

    }

web.xml 에 Filter 설정 추가

,

의 안의 속성에는 servlet-name과 url-pattern이 있는데,

하나의 주소 이외에 다양한 곳에 필터를 사용할때 url-pattern을 사용한다.

  <filter>
    <filter-name>myfilter</filter-name>
    <filter-class>me.morris.MyFilter</filter-class>
  </filter>

  <filter-mapping>
    <filter-name>myfilter</filter-name>
    <servlet-name>hello</servlet-name>
  </filter-mapping>

Filter를 추가한 실행 동작 순서

[2020-03-01 06:49:03,499] Artifact SpringWebMVC:war exploded: Artifact is being deployed, please wait...
contextInitialized 
Filter init
[2020-03-01 06:49:03,887] Artifact SpringWebMVC:war exploded: Artifact is deployed successfully
[2020-03-01 06:49:03,887] Artifact SpringWebMVC:war exploded: Deploy took 388 milliseconds
init
Filter 
doGet
01-Mar-2020 18:
  1. contextInitialized : 서블릿 리스너에서 contextInitinalize가 실행
  2. Filter init : Filter 를 구현한 클래스에서 init 메서드 실행
  3. FilterMapping된 Servlet 클래스 호출
  4. init : Servlet클래스 init 메서드 실행
  5. Filter : Filter 클래스에서의 doFilter 메서드 실행
  6. doGet : Servlet 메서드의 doGet 메서드 실행

으로 적용된다.

Servlet Container ->(request)-> Filter -> Servlet ->(response)-> Servlet Container

해결하고 싶은 것

아래와 같은 내용을 Spring @RequestBody 에 값을 전달하고싶다.

{
    "zooName":"MorrisZoo",
    "animals":[
        {"type":"cat", "name":"yammi", "likesCream":true,"lives":0},
        {"type":"dog", "name":"Fancy","barkVolume":4}
    ]
}

animals는 Animal 타입을 상속 받은 dog, cat 의 객체로 받아와야한다.

구현하기
Jackson Polymorphic Type Handling Annotations 을 참고
Jackson 라이브러리는 다음에 한번에 정리를 하겠습니다.

AnimalController.java

@RestController
public class AnimalController {

    @PostMapping(value="/zooinfo")
    public void jsonTypeCheck(@RequestBody Zoo zoo){
        String zooName = zoo.zooName;
        System.out.println("동물원 이름 : "+zooName);
        zoo.animals.forEach((value)->value.println());
    }
}

Zoo.java : @RequestBody에 받아올 zoo 객체

package com.jackson.jacksontutorial;

import java.util.List;

public class Zoo {
    public String zooName;
    public List<Animal> animals;
}

Animal.java` : Dog, Cat의 상위 클래스

package com.jackson.jacksontutorial;

import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;

@JsonTypeInfo(
        use = JsonTypeInfo.Id.NAME,
        include = JsonTypeInfo.As.PROPERTY,
        property = "type")
@JsonSubTypes({
        @JsonSubTypes.Type(value = Dog.class, name = "dog"),
        @JsonSubTypes.Type(value = Cat.class, name = "cat")
})
public abstract class Animal {
    public String name;

    public void println( ){
        System.out.println("Animal Type : "+name);
    };

}

Cat.java

package com.jackson.jacksontutorial;

import com.fasterxml.jackson.annotation.JsonRootName;
import com.fasterxml.jackson.annotation.JsonTypeName;


//@JsonTypeName("cat")
@JsonRootName("cat")
public class Cat extends Animal {
    boolean likesCream;
    public int lives;

    @Override
    public String toString() {
        return "Cat{" +
                "likesCream=" + likesCream +
                ", lives=" + lives +
                '}';
    }

    @Override
    public void println() {
        String AnimalType = super.name;
        System.out.println("name : "+name+","+this.toString());
    }
}

Dog.java

package com.jackson.jacksontutorial;

import com.fasterxml.jackson.annotation.JsonRootName;
import com.fasterxml.jackson.annotation.JsonTypeName;

//@JsonTypeName("dog")
@JsonRootName("dog")
public class Dog extends Animal {
    public double barkVolume;

    @Override
    public String toString() {
        return "Dog{" +
                "barkVolume=" + barkVolume +
                '}';
    }
    @Override
    public void println() {
        String name = super.name;
        System.out.println("name : "+name+","+this.toString());
    }
}

결과

요청

post- @RequestBody

{
    "zooName":"MorrisZoo",
    "animals":[
        {"type":"cat", "name":"yammi", "likesCream":true,"lives":0},
        {"type":"dog", "name":"Fancy","barkVolume":4}
    ]
}

SpringApplication

2020-02-28 16:51:14.376  INFO 17268 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 5 ms
동물원 이름 : MorrisZoo
name : yammi,Cat{likesCream=false, lives=0}
name : Fancy,Dog{barkVolume=4.0}

ClassPath Scanning

특정 classpath 이하에 있는 관리할 컴포넌트(@Component)들을 등록을 하기 위해 스캔함

@Component : Annotation Type으로 런타임에 동작함. classpath scanning을 통해 자동적으로 검색됨.

@Repository, @Service, @Controller

@ComponentScan(basePackages = "kr.co.fastcampus.cli") 을 해주면 xml에 별도로 설정을 안해줘도 알아서 추가가 됨.

예시

@Configuration
@ComponentScan(basePackages = "kr.co.fastcampus.cli")
public class AppConfig {
    @Bean
    public A a1(){
        return new A();
    }
    @Bean
      @Scope("singleton")
    public B b1(){
        return new B();
    }
}

@Component
class A {}

@Component
class B{}

아래와 같이 AnnotationConfigApplicationContext()를 사용해서 사용이 가능하다.

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

AnnotationConfigApplicationContext API 를 살펴보면 아래와 같이 파라미터를 넣어주면 사용이 가능하다.

Constructor and Description
AnnotationConfigApplicationContext()Create a new AnnotationConfigApplicationContext that needs to be populated through register(java.lang.Class...) calls and then manually refreshed.
AnnotationConfigApplicationContext(Class... componentClasses)Create a new AnnotationConfigApplicationContext, deriving bean definitions from the given component classes and automatically refreshing the context.
AnnotationConfigApplicationContext(DefaultListableBeanFactory beanFactory)Create a new AnnotationConfigApplicationContext with the given DefaultListableBeanFactory.
AnnotationConfigApplicationContext(String... basePackages)Create a new AnnotationConfigApplicationContext, scanning for components in the given packages, registering bean definitions for those components, and automatically refreshing the context.

Filter

ComponentScan에서 특정 클래스를 빼고 싶을 때, (pattern, class, 등 의 다양함 )

아래처럼 filter를 사용해서 execludeFilters를 사용하여 가능하다.

@Slf4j
@ComponentScan(basePackageClasses = Main.class , excludeFilters = @ComponentScan.Filter (type= FilterType.REGEX,pattern="kr.co.fastcampus.cli.B"))
public class Main {
    static Logger logger = LoggerFactory.getLogger(Main.class);

    public static void main(String []args) {

        //Java Anotation을 사용한 주입
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Main.class);
        B b = context.getBean(B.class);
        log.info("b : "+b);
        context.close();
    }
}

ComponentScan 성능 향상

ComponentScan은 Java Generic을 사용하여 JVM에서 어노테이션이 붙어있는지 아닌지 결정하여 판단을 하게 되는데, 만약 어노테이션이 너무 많이 사용되게 되면 ComponentScan이 오래 걸릴 수 있다.

그래서 indexer를 만들어 놓음

pom.xml에 추가

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context-indexer</artifactId>
        <version>5.2.3.RELEASE</version>
        <optional>true</optional>
    </dependency>
</dependencies>

빌드를 하게 되면 META-INF/spring.components 가 만들어짐.

java.io.InvalidClassException: org.apache.spark.rdd.RDD

java.io.InvalidClassException: org.apache.spark.rdd.RDD; local class incompatible: stream classdesc serialVersionUID 에러

19:58:43.380 [dag-scheduler-event-loop] INFO  o.a.spark.scheduler.DAGScheduler - ShuffleMapStage 0 (count at TaskProcessService.java:152) failed in 0.880 s due to Job aborted due to stage failure: Task 0 in stage 0.0 failed 4 times, most recent failure: Lost task 0.3 in stage 0.0 (TID 3, 192.168.44.80, executor 1): java.io.InvalidClassException: org.apache.spark.rdd.RDD; local class incompatible: stream classdesc serialVersionUID = -3328732449542231715, local class serialVersionUID = 4416556597546473068
        at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:616)
        at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1843)
        at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1713)
        at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1843)
        at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1713)
        at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2000)
        at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1535)
        at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2245)
        at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2169)
        at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2027)
        at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1535)
        at java.io.ObjectInputStream.readObject(ObjectInputStream.java:422)

spark 를 사용하는 어딘가에서 spark version이 여러개라서 오류가 나는것

저 같은 경우에는 springboot에서 spark의 버전을 2.4.0 으로 설정이 되어있고, 서버의 spark 모듈은 2.4.5라서 발생했었음

'BackEnd > Spark' 카테고리의 다른 글

[Spark] RDD Persistence 와 Caching  (0) 2020.03.05
스파크 SQL 사용하여 파일로 보내기  (0) 2020.03.02
Spark History Server 실행 오류 시  (0) 2020.02.10
SparkSession  (0) 2020.02.06
RDD 영속화(캐싱)  (0) 2019.09.02

MYSQL 8.0 이후 접속시

8.0 이상의 Dbeaver로 접속을 하려고 하는데,

이전에는 주소값, 데이터베이스, 드라이버이름, 유저아이디, 패스워드 등만 가지고 있으면 접속이 가능했었다. 하지만 8.0 이후의 버전으로 접속을 시도 했을때

아래와 같은 에러가 발생했다.

public key retrieval is not allowed

8.0 이후 부터는

allowPublicKeyRetrieval=true 의 설정을 추가 해줘야한다.

jdbc 주소 는 아래와 같이

jdbc:mysql://localhost:3306/database?allowPublicKeyRetrieval=true

Dbeaver 에서는 드라이버 설정

> driver properties

'BackEnd > SQL' 카테고리의 다른 글

분산 마리아 디비 , galera cluster  (0) 2017.12.18

Bean Scope

빈의 범위

객체를 만들때 컨테이너가 객체를 한번만 호출하는지, 객체를 호출받을때마다 생성하는지를 정의

singleton, prototype을 주로 많이 쓰임

Singleton : 객체를 한번만 생성 (동일성을 보장)

<bean id="A" class="kr.co.fastcampus.cli.A" scope="singleton"></bean>

prototype : 객체를 계속 새로 만듬

<bean id="A" class="kr.co.fastcampus.cli.A" scope="prototype"></bean>

Scope Description
singleton (Default) Scopes a single bean definition to a single object instance for each Spring IoC container.
prototype Scopes a single bean definition to any number of object instances.
request Scopes a single bean definition to the lifecycle of a single HTTP request. That is, each HTTP request has its own instance of a bean created off the back of a single bean definition. Only valid in the context of a web-aware Spring ApplicationContext.
session Scopes a single bean definition to the lifecycle of an HTTP Session. Only valid in the context of a web-aware Spring ApplicationContext.
application Scopes a single bean definition to the lifecycle of a ServletContext. Only valid in the context of a web-aware Spring ApplicationContext.
websocket Scopes a single bean definition to the lifecycle of a WebSocket. Only valid in the context of a web-aware Spring ApplicationContext.

동일성과 동등성

동일성 : 객체 주소가 같다.

동등성 : 객체의 값이 같다.

동일성

@Test
public void testIdentity(){
  //동일성 (identity) : 객체 주소 가 같다. (object1==object2==object3) 는 동일한 주소 값을 가질 수 있다.
  //동등성 (eqauls) : 객체의 값이 같다. (object1.equals(object2) ==true )

  A a1 = new A();
  A a2 = new A();
  Assert.assertFalse(a1==a2); //a1과 a2의 주소값이 같은지 ? 다르다

  A a3 = a1;
  Assert.assertTrue(a3==a1);

}
class A{

}

동등성

Object 의 equals 는 아래와 같이 동일성 체크를 한다.

public boolean equals(Object obj) {
            return (this == obj);
}



@Test
public void testEquals(){

  A a1 = new A(10,"Hello world");
  A a2 = new A(10,"Hello world");
  A a3 = new A(5,"Hello world");


  Assert.assertTrue(a1.equals(a2));
  Assert.assertFalse(a1.equals(a3));

}

코드

class A{
    private int a1 ;
    private String a2;

    public A(int a1, String a2) {
        this.a1 = a1;
        this.a2 = a2;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof A)) return false;
        A a = (A) o;
        return a1 == a.a1 &&
                Objects.equals(a2, a.a2);
    }

    @Override
    public int hashCode() {
        return Objects.hash(a1,a2);
    }
}

lombok을 응용하여 사용하면 아래와 같이 쉽게 만들 수 있다.

@EqualsAndHashCode
@AllArgsConstructor
class A{
    private int a1 ;
    private String a2;
}

TestCode

https://junit.org/junit5/docs/current/user-guide/#running-tests

https://junit.org/junit5/docs/current/user-guide/#running-tests-build-maven

https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#beans-factory-scopes

+ Recent posts