반응형
ENGINEERING

Microservices with Spring

Introduction

NOTE: Revised June 2018

A simple example of setting up a microservices system using Spring, Spring Boot and Spring Cloud.

Microservices allow large systems to be built up from a number of collaborating components. It does at the process level what Spring has always done at the component level: loosely coupled processes instead of loosely coupled components.

Shopping Application

For example imagine an online shop with separate microservices for user-accounts, product-catalog order-processing and shopping carts:

Inevitably there are a number of moving parts that you have to setup and configure to build such a system. How to get them working together is not obvious - you need to have good familiarity with Spring Boot since Spring Cloud leverages it heavily, several Netflix or other OSS projects are required and, of course, there is some Spring configuration “magic”!

Demo Application

In this article I aim to clarify how things work by building the simplest possible system step-by-step. Therefore, I will only implement a small part of the big system - the user account service.

The Web-Application will make requests to the Account-Servicemicroservice using a RESTful API. We will also need to add a discovery service – so the other processes can find each other.

The code for this application is here: https://github.com/paulc4/microservices-demo.

The description of how it works is deliberately detailed. Impatient readers may prefer to simply look at the code. Note that it contains three microservices in a single project.

Follow-Up 1: Other Resources

This article only discusses a minimal system. For more information, you might like to read Josh Long’s blog article Microservice Registration and Discovery with Spring Cloud and Netflix’s Eureka which shows running a complete microservice system on Cloud Foundry.

The Spring Cloud projects are here.

Follow Up 2: SpringOne Platform 2018

Book your place at SpringOne2 Platform in Washington DC, USA this September - simply the best opportunity to find out first hand all that’s going on and to provide direct feedback. The name has changed, from Spring One, to reflect the growth of Spring in platform services (such as the Spring Cloud projects).

Updates (June 2018)

A number of changes since I originally wrote this blog:

  1. discussion of using multiple instances of the same service on the same host.. Demo application updated to match.
  2. discussion of @LoadBalanced - how this works has changed since the Brixton release-train (Spring Cloud 1.1.0.RELEASE).
  3. Refactored configuration of Accounts microservice into its own class AccountsConfiguration.
  4. Upgraded to Spring Boot 2, so a few Boot classes have changed package.
  5. Upgraded demo application to Spring Cloud Finchley release-train (including various fixes from the comments at the end - thanks for the feedback).
  6. The Eureka server dependency has changed to spring-cloud-starter-netflix-eureka-server.

Previous version, using Spring Boot 1.5.10 and Spring Cloud Edgeware SR3, is available as git tag v1.2.0.

 

OK, let’s get started …

Service Registration

When you have multiple processes working together they need to find each other. If you have ever used Java’s RMI mechanism you may recall that it relied on a central registry so that RMI processes could find each other. Microservices has the same requirement.

The developers at Netflix had this problem when building their systems and created a registration server called Eureka (“I have found it” in Greek). Fortunately for us, they made their discovery server open-source and Spring has incorporated into Spring Cloud, making it even easier to run up a Eureka server. Here is the complete discovery-server application:

@SpringBootApplication
@EnableEurekaServer
public class ServiceRegistrationServer {

  public static void main(String[] args) {
    // Tell Boot to look for registration-server.yml
    System.setProperty("spring.config.name", "registration-server");
    SpringApplication.run(ServiceRegistrationServer.class, args);
  }
}

It really is that simple!

Spring Cloud is built on Spring Boot and utilizes parent and starter POMs. The important parts of the POM are:

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.1.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <!-- Setup Spring Boot -->
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <!-- Setup Spring MVC & REST, use Embedded Tomcat -->
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <!-- Spring Cloud starter -->
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter</artifactId>
        </dependency>

        <dependency>
            <!-- Eureka for service registration -->
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka-server</artifactId>
        </dependency>
    </dependencies>

   <!-- Spring Cloud dependencies -->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Finchley.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

This POM has changed since I originally wrote the article to use Spring Boot as its parent not Spring Cloud. Spring Cloud dependencies are provided via the dependency management section.

An sample gradle build file is also included in the github code.

Note: Finchley.RELEASE is the current "release train" - a set of co-ordinated releases -- see note on Spring Cloud home page.

By default Spring Boot applications look for an application.properties or application.ymlfile for configuration. By setting the spring.config.name property we can tell Spring Boot to look for a different file - useful if you have multiple Spring Boot applications in the same project - as I will do shortly.

This application looks for registration-server.properties or registration-server.yml. Here is the relevant configuration from registration-server.yml:

# Configure this Discovery Server
eureka:
  instance:
    hostname: localhost
  client:  # Not a client, don't register with yourself (unless running
           # multiple discovery servers for redundancy)
    registerWithEureka: false
    fetchRegistry: false

server:
  port: 1111   # HTTP (Tomcat) port

By default Eureka runs on port 8761, but here we will use port 1111 instead. Also by including the registration code in my process I might be a server or a client. The configuration specifies that I am not a client and stops the server process trying to register with itself.

Using Consul

Spring Cloud also supports Consul as an alternative to Eureka. You start the Consul Agent (its registration server) using a script and then clients use it to find their microservices. For details, see this blog article or project home page.

Try running the RegistrationServer now (see below for help on running the application). You can open the Eureka dashboard here: http://localhost:1111 and the section showing Applications will be empty.

From now on we will refer to the discovery-serversince it could be Eureka or Consul (see side panel).

Creating a Microservice: Account-Service

A microservice is a stand-alone process that handles a well-defined requirement.

Beans vs Processes

When configuring applications with Spring we emphasize Loose Coupling and Tight Cohesion, These are not new concepts (Larry Constantine is credited with first defining these in the late 1960s - reference) but now we are applying them, not to interacting components (Spring Beans), but to interacting processes.

In this example, I have a simple Account management microservice that uses Spring Data to implement a JPA AccountRepository and Spring REST to provide a RESTful interface to account information. In most respects this is a straightforward Spring Boot application.

What makes it special is that it registers itself with the discovery-server at start-up. Here is the Spring Boot startup class:

@EnableAutoConfiguration
@EnableDiscoveryClient
@Import(AccountsWebApplication.class)
public class AccountsServer {

    @Autowired
    AccountRepository accountRepository;

    public static void main(String[] args) {
        // Will configure using accounts-server.yml
        System.setProperty("spring.config.name", "accounts-server");

        SpringApplication.run(AccountsServer.class, args);
    }
}

The annotations do the work:

  1. @EnableAutoConfiguration - defines this as a Spring Boot application.
  2. @EnableDiscoveryClient - this enables service registration and discovery. In this case, this process registers itself with the discovery-server service using its application name (see below).
  3. @Import(AccountsWebApplication.class) - this Java Configuration class sets up everything else (see below for more details).

What makes this a microservice is the registration with the discovery-server via @EnableDiscoveryClient and its YML configuration completes the setup:

# Spring properties
spring:
  application:
     name: accounts-service

# Discovery Server Access
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:1111/eureka/

# HTTP Server
server:
  port: 2222   # HTTP (Tomcat) port

Note that this file

  1. Sets the application name as accounts-service. This service registers under this name and can also be accessed by this name - see below.
  2. Specifies a custom port to listen on (2222). All my processes are using Tomcat, they can’t all listen on port 8080.
  3. The URL of the Eureka Service process - from the previous section.
Eureka Dashboard

Run the AccountsServiceapplication now and let it finish initializing. Refresh the dashboard http://localhost:1111 and you should see the ACCOUNTS-SERVICE listed under Applications. Registration takes up to 30 seconds (by default) so be patient - check the log output from RegistrationService

Warning: Do not try to display XML output using the internal web-viewer of Eclipse/STS because it cannot do so. Use your favorite web browser instead.

For more detail, go here: http://localhost:1111/eureka/apps/ and you should see something like this:

<applications>
    <versions__delta>1</versions__delta>
    <apps__hashcode>UP_1_</apps__hashcode>
    <application>
        <name>ACCOUNTS-SERVICE</name>
        <instance>
            <hostName>autgchapmp1m1.corp.emc.com</hostName>
            <app>ACCOUNTS-SERVICE</app>
            <ipAddr>172.16.84.1</ipAddr><status>UP</status>
            <overriddenstatus>UNKNOWN</overriddenstatus>
            <port enabled="true">3344</port>
            <securePort enabled="false">443</securePort>
            ...
        </instance>
    </application>
</applications>

Alternatively go to http://localhost:1111/eureka/apps/ACCOUNTS-SERVICE and see just the details for AccountsService - if it’s not registered you will get a 404.

Configuration Options

Registration Time: Registration takes up to 30s because that is the default client refresh time. You can change this by setting the eureka.instance.leaseRenewalIntervalInSecondsproperty to a smaller number (in the demo application I have set it to 5). This is not recommended in production. See also.

eureka:
  instance:
    leaseRenewalIntervalInSeconds: 5         # DO NOT DO THIS IN PRODUCTION

Registration Id: A process (microservice) registers with the discovery-service using a unique id. If another process registers with the same id, it is treated as a restart (for example some sort of failover or recovery) and the first process registration is discarded. This gives us the fault-tolerant system we desire.

To run multiple instances of the same process (for load-balancing and resilience) they need to register with a unique id. When I first wrote this blog, that was automatic and since the Brixtonrelease-train, it is again.

Under the Angel release train, the instance-id, used by a client to register with a discovery server, was derived from the client’s service name (the same as the Spring application name) and also the client’s host name. The same processes running on the same host would therefore have the same id, so only one could ever register.

Fortunately you could set the id property manually via the client’s Eureka metadata map, like this:

eureka:
  instance:
    metadataMap:
      instanceId: ${spring.application.name}:${spring.application.instance_id:${server.port}}

Since the Brixton release train, this is now the default. So what does it do?

We are setting the instanceId to application-name:instance_id, but if instance_id is not defined, we will use application-name::server-port instead. Note that the spring.application.instance_id is only set when using Cloud Foundry but it conveniently provides a unique id number for each instance of the same application. We can do something similar when running elsewhere by using the server-port (since different instances on the same machine must listen on different ports. Another example you will often see is ${spring.application.name}:${spring.application.instance_id:${random.value}} but I personally find using the port number makes each instance easy to identify - the random values are just long strings that don’t mean anything.

Note: The syntax ${x:${y}} is Spring property shorthand for ${x} != null ? ${x} : ${y}.

Since the Brixton release there is also a dedicated property for this:

eureka:
  instance:
    instanceId: ${spring.application.name}:${spring.application.instance_id:${random.value}}

Accessing the Microservice: Web-Service

To consume a RESTful service, Spring provides the RestTemplate class. This allows you to send HTTP requests to a RESTful server and fetch data in a number of formats - such as JSON and XML.

Note: The Accounts microservice provides a RESTful interface over HTTP, but any suitable protocol could be used. Messaging using AMQP or JMS is an obvious alternative (in which case the Discovery Server is no longer needed - instead processes need to know the names of the queues to talk to, consider using the Spring Cloud Configuration Server for this).

Which formats can be used depends on the presence of marshaling classes on the classpath - for example JAXB is always detected since it is a standard part of Java. JSON is supported if Jackson jars are present in the classpath.

A microservice (discovery) client can use a RestTemplate and Spring will automatically configure it to be microservice aware (more of this in a moment).

Encapsulating Microservice Access

Here is part of the WebAccountService for my client application:

@Service
public class WebAccountsService {

    @Autowired        // NO LONGER auto-created by Spring Cloud (see below)
    @LoadBalanced     // Explicitly request the load-balanced template
                      // with Ribbon built-in
    protected RestTemplate restTemplate; 

    protected String serviceUrl;

    public WebAccountsService(String serviceUrl) {
        this.serviceUrl = serviceUrl.startsWith("http") ?
               serviceUrl : "http://" + serviceUrl;
    }

    public Account getByNumber(String accountNumber) {
        Account account = restTemplate.getForObject(serviceUrl
                + "/accounts/{number}", Account.class, accountNumber);

        if (account == null)
            throw new AccountNotFoundException(accountNumber);
        else
            return account;
    }
    ...
}

Note that my WebAccountService is just a wrapper for the RestTemplate fetching data from the microservice. The interesting parts are the serviceUrl and the RestTemplate.

Accessing the Microservice

As shown below, the serviceUrl is provided by the main program to the WebAccountController (which in turn passes it to the WebAccountService):

@SpringBootApplication
@EnableDiscoveryClient
@ComponentScan(useDefaultFilters=false)  // Disable component scanner
public class WebServer {

    // Case insensitive: could also use: http://accounts-service
    public static final String ACCOUNTS_SERVICE_URL
                                        = "http://ACCOUNTS-SERVICE";

    public static void main(String[] args) {
        // Will configure using web-server.yml
        System.setProperty("spring.config.name", "web-server");
        SpringApplication.run(WebServer.class, args);
    }

    @LoadBalanced    // Make sure to create the load-balanced template
    @Bean
    RestTemplate restTemplate() {
        return new RestTemplate();
    }

    /**
     * Account service calls microservice internally using provided URL.
     */
    @Bean
    public WebAccountsService accountsService() {
        return new WebAccountsService(ACCOUNTS_SERVICE_URL);
    }

    @Bean
    public WebAccountsController accountsController() {
         return new WebAccountsController
                       (accountsService());  // plug in account-service
    }
}

A few points to note:

  1. The WebController is a typical Spring MVC view-based controller returning HTML. The application uses Thymeleaf as the view-technology (for generating dynamic HTML)
  2. WebServer is also a @EnableDiscoveryClient but in this case as well as registering itself with the discovery-server (which is not necessary since it offers no services of its own) it uses Eureka to locate the account service.
  3. The default component-scanner setup inherited from Spring Boot looks for @Componentclasses and, in this case, finds my WebAccountController and tries to create it. However, I want to create it myself, so I disable the scanner like this @ComponentScan(useDefaultFilters=false).
  4. The service-url I am passing to the WebAccountController is the name the service used to register itself with the discovery-server - by default this is the same as the spring.application.name for the process which is account-service - see account-service.yml above. The use of upper-case is not required but it does help emphasize that ACCOUNTS-SERVICE is a logical host (that will be obtained via discovery) not an actual host.

Load Balanced RestTemplate

The RestTemplate bean will be intercepted and auto-configured by Spring Cloud (due to the @LoadBalanced annotation) to use a custom HttpRequestClient that uses Netflix Ribbon to do the microservice lookup. Ribbon is also a load-balancer so if you have multiple instances of a service available, it picks one for you. (Neither Eureka nor Consul on their own perform load-balancing so we use Ribbon to do it instead).

Note: From the Brixton Release Train (Spring Cloud 1.1.0.RELEASE), the RestTemplate is no longer created automatically. Originally it was created for you, which caused confusion and potential conflicts (sometimes Spring can be too helpful!).

Note that this instance is qualified using @LoadBalanced. (The annotation is itself annotated with @Qualifier - see here for details). Thus if you have more than one RestTemplate bean, you can make sure to inject the right one, like this:

    @Autowired
    @LoadBalanced     // Make sure to inject the load-balanced template
    protected RestTemplate restTemplate;

If you look in the RibbonClientHttpRequestFactory you will see this code:

    String serviceId = originalUri.getHost();
    ServiceInstance instance =
             loadBalancer.choose(serviceId);  // loadBalancer uses Ribbon
    ... if instance non-null (service exists) ...
    URI uri = loadBalancer.reconstructURI(instance, originalUri);

The loadBalancer takes the logical service-name (as registered with the discovery-server) and converts it to the actual hostname of the chosen microservice.

RestTemplate instance is thread-safe and can be used to access any number of services in different parts of your application (for example, I might have a CustomerService wrapping the same RestTemplate instance accessing a customer data microservice).

Configuration

Below the relevant configuration from web-server.yml. It is used to:

  1. Set the application name
  2. Define the URL for accessing the discovery server
  3. Set the Tomcat port to 3333
# Spring Properties
spring:
  application:
     name: web-service

# Discovery Server Access
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:1111/eureka/

# HTTP Server
server:
  port: 3333   # HTTP (Tomcat) port

How to Run the Demo

A small demo of this system is at http://github.com/paulc4/microservices-demo. Clone it and either load into your favorite IDE or use maven directly. Suggestions on how to run the demo are included in the README on the project homepage.


Extra Notes

Some notes about Spring Boot usage by these applications. If you are not familiar with Spring Boot, this explains some of the “magic”!

View Templating Engines

The Eureka dashboard (inside RegistrationServer) is implemented using FreeMarker templates but the other two applications use Thymeleaf. To make sure each uses the right view engine, there is extra configuration in each YML file.

This is at the end of registration-server.yml to disable Thymeleaf.

...
# Discovery Server Dashboard uses FreeMarker.  Don't want Thymeleaf templates
spring:
  thymeleaf:
    enabled: false     # Disable Thymeleaf spring:

Since both AccountService and WebService use thymeleaf, we also need to point each at their own templates. Here is part of account-server.yml:

# Spring properties
spring:
  application:
     name: accounts-service  # Service registers under this name
  freemarker:
    enabled: false      # Ignore Eureka dashboard FreeMarker templates
  thymeleaf:
    cache: false        # Allow Thymeleaf templates to be reloaded at runtime
    prefix: classpath:/accounts-server/templates/
                        # Template location for this application only
...

web-server.yml is similar but its templates are defined by

   prefix: classpath:/web-server/templates/

Note the / on the end of each spring.thymeleaf.prefix classpath - this is crucial.

Command-Line Execution

The jar is compiled to automatically run io.pivotal.microservices.services.Main when invoked from the command-line - see Main.java.

The Spring Boot option to set the start-class can be seen in the POM:

    <properties>
        <!-- Stand-alone RESTFul application for testing only -->
        <start-class>io.pivotal.microservices.services.Main</start-class>
    </properties>

AccountsConfiguration class

@SpringBootApplication
@EntityScan("io.pivotal.microservices.accounts")
@EnableJpaRepositories("io.pivotal.microservices.accounts")
@PropertySource("classpath:db-config.properties")
public class AccountsWebApplication {
...
}

This is the main configuration class for AccountService which is a classic Spring Boot application using Spring Data. The annotations do most of the work:

  1. @SpringBootApplication - defines this as a Spring Boot application. This convenient annotation combines @EnableAutoConfiguration@Configuration and @ComponentScan(which, by default, causes Spring to search the package containing this class, and its sub-packages, for components - potential Spring Beans: AccountController and AccountRepository) .
  2. @EntityScan("io.pivotal.microservices.accounts") - because I am using JPA, I need to specify where the @Entity classes are. Normally this is an option you specify in JPA’s persistence.xml or when creating a LocalContainerEntityManagerFactoryBean. Spring Boot will create this factory-bean for me because the spring-boot-starter-data-jpadependency is on the class path. So an alternative way of specifying where to find the @Entity classes is by using@EntityScan. This will find Account.
  3. @EnableJpaRepositories("io.pivotal.microservices.accounts")- look for classes extending Spring Data’s Repository marker interface and automatically implement them using JPA - see Spring Data JPA.
  4. @PropertySource("classpath:db-config.properties") - properties to configure my DataSource – see db-config.properties.

Configuring Properties

As mentioned above, Spring Boot applications look for either application.properties or application.yml to configure themselves. Since all three servers used in this application are in the same project, they would automatically use the same configuration.

To avoid that, each specifies an alternative file by setting the spring.config.name property.

For example here is part of WebServer.java.

public static void main(String[] args) {
  // Tell server to look for web-server.properties or web-server.yml
  System.setProperty("spring.config.name", "web-server");
  SpringApplication.run(WebServer.class, args);
}

At runtime, the application will find and use web-server.yml in src/main/resources.

Logging

Spring Boot sets up INFO level logging for Spring by default. Since we need to examine the logs for evidence of our microservices working, I have raised the level to WARN to reduce the amount of logging.

To do this, the logging level would need to be specified in each of the xxxx-server.ymlconfiguration files. This is usually the best place to define them as logging properties cannotbe specified in property files (logging has already been initialized before @PropertySource directives are processed). There is a note on this in the Spring Boot manual, but it’s easy to miss.

Rather than duplicate the logging configuration in each YAML file, I instead opted to put it in the logback configuration file, since Spring Boot uses logback - see src/main/resources/logback.xml. All three services will share the same logback.xml.


출처: https://spring.io/blog/2015/07/14/microservices-with-spring


'JAVA > Java' 카테고리의 다른 글

Intellij 셋팅 파일  (0) 2019.07.09
REST 개념  (0) 2019.03.21
메서드, 클래스 명명규칙 어떡하면 좋을까?  (0) 2017.07.04
이클립스 실행 인자 입력 받기  (0) 2016.11.02
자바7에서 마음에 드는 다섯 가지  (0) 2016.10.17
반응형

많은 개발자들이 개발 중에 종종 고민하는 "이 메서드명은 뭘로 해야 좋을까?"란 문제는 흡사 직장인들이 "오늘 점심 뭘 먹을까?"와 거의 비슷한…, 또 본의 아니게 심각한 트라우마에 빠질 수도 있는 고민 중 하나이다. 사실 어떻게 보면 별것도 아닌 고민일 수 있는데 한국인인지라 영어도 잘 모르는 상황에서 컴퓨터랑 영어로 대화를 하려니 발생하는 헤프닝일 수도 있겠다.


아마 대부분의 개발자들이 처음에는 구현해야할 기능의 성격이 어느 정도 명확하니까 비교적 단순한 영단어로 get, put, remove…같은 식으로 지어나가곤 한다. 그리고 그렇게 도메인 계층이나 DAO계층을 어느 정도 마무리 짓고 본격적으로 서비스 계층, 서포트 계층으로 올라가려다보면 어느덧 명명규칙의 트랩에 빠지게 되고 사전에 야기했던 본의 아닌 트라우마에 빠지기 시작한다.

예를 들어 메서드를 하나 만드는데 내용이 '클라이언트가 전달 파라미터를 가지고 User 테이블의 인덱스를 검사한 뒤, 그 결과값 바탕으로 다시 Friends 테이블에 검색해서 나온 결과값을 가공하여 뷰가 해석할 수 있는 클래스로 변환한 값을 리턴'한다고 하자. 도대체 이런 해괴망칙한 과정을 거치는 메서드 명은 당신은 뭐라고 지을 것인가?

더욱이 이런 메서드를 한 두개 만드는 것도 아니고 보통 하루에 30~40개 정도의 (어느 정도 의미있는) 메서드를 찍어내고 7~10개 정도의 클래스를 만들어내는 게 프로그래머들이다. 매번 게임 아이디 만드는 것도 아니고 쓸데없는 메서드명 창작에 심혈을 기울이고 싶은 사람은 아무도 없을 것이다.

에다가 심각한 것은 문제가 이게 끝이 아니라는 것이다. 메서드명 짓기도 짜증이 나는데 클래스명 창작은 더욱 난해하고 심오해서 세상에서 가장 어려운 단어 찾기의 게임 속으로 빠져든다. 왜냐하면 보통 클래스명은 많은 의미를 함축하고 있으면서도 명확한 목적을 표현해야 하므로 여러가지 정황을 고려해 지어지는 것이 일반적이다. 예를 들어 AnnotationConfigApplicationContext.class의 이름은 @Configuration 어노테이션으로 설정된 클래스를 ApplicationContext 형태로 가공해주는 클래스인데 스프링 제작자가 이름 짓기 귀찮아 ApplicationContextImpl과 같이 단순히 인터페이스를 구현했다고 가정해보자. 이런 상황에서 작성자는 자신이 만든 클래스의 기능을 속속들이 알고 있지만 사용자는 대개 메서드명만 보고 단순 예측한 상태에서 기능을 사용하기 때문에 자칫 혼란을 가져오는 문제를 발생 시키기도 한다.

그러므로 메서드명과 클래스명에서 발생되는 문제는 개발자 본인에게는 별 것 아닌 문제처럼 치부될 수도 있지만 직접 사용하는 사용자에게는 매우 중요한 역할을 수행하게 되므로 사전에 충분히 작성이 필요한 메서드들을 예측하여 약속된 문법과 단어들을 조합하여 메서드와 클래스를 작성하는 규칙이 필요하다.

그리고 만약에 그럴 사람은 드물겠지만 프로그래밍의 메서드와 클래스명을 짓기 위해 조금이나마 영어공부를 하고 싶다면 on, by, after, before, of…와 같은 단순전치사나 전치사구는 여러모로 프로그래밍 명명규칙에 활용하기 좋은 영단어이므로 콩글리쉬로만 알지 말고 내포하고 있는 다양한 의미를 습득하는 것이 좋다.

앞으로 여기서 나열하는 단어들과 의미는 스프링 프레임워크에서 사용되고 있는 메서드와 클래스 이름의 규칙들이며 가급적 특정한 의미만을 내포하지 않고 규칙적으로 사용되는 단어들을 선별하고자 노력하였다. 그리고 단순히 영어단어의 뜻만이 아니라 프로그래밍 적으로 사용되는 뜻까지 포함할 수 있도록 하였으니 정독만 했다면 독자의 개발과정에 어느 정도 도움이 되리라 본다.



패키지명

패키지명은 하나의 단어만 사용할 것이 권장되며 만약 단어의 길이가 10자를 넘어 가독성에 무리가 간다 판단될 경우에 단어의 앞 3글자만 따서 지을 수도 있다. 항상 하위 패키지는 상위 패키지와 깊은 연관을 맺어야하며 만약 서로 다른 성격의 패키지가 부모 자식 패키지로 설정될 경우 혼동이 올 수가 있다.

사용되는 대표적인 패키지명들

domain (영역, 범위, 소유지) - 단위로 표현할 수 있고 원자성을 띄는 자바빈 클래스, Enum 클래스 등이 위치한다. 다른 곳에서 VO라고 하는 것을 본적이 있는데 필자는 domain이란 이름이 더 마음에 든다.

dao (Data Access Object) - 데이터액세스 계층과 관련된 클래스와 인터페이스들이 자리한다. DB과 관련된 작업을 한다면 사용할 수 있는 패키지명이다.

service (근무, 봉사, 편익, 이용…) - 역시 웹에서 사용되는 계층 중 하나이며 대개 dao를 조합하고 트랜잭션의 경계가 설정되는 구간이기도 하다.

core (속, 중심부, 핵심) - 어플리케이션의 핵심적인 역할을 수행하는 클래스와 인터페이스들이 자리하는 구간이다.

task (일, 과업, 과제…) - 단어와는 가장 딴판으로 사용되는 용어 중 하나이다. 자바에서 스레드와 관련된, java.lang.Runnable 클래스의 활동을 지원하는 클래스들이 위치한다.

access (접근, 진입로, 증가…) - DB 뿐만이 아니라 다른 리소스의 자원을 불러들이고 이를 자바에서 사용가능한 상태로 가공해주는 클래스들이 위치한다.

support (지지, 지원…) - 가장 잘 이해하고 사용해야 할 패키지명이며 어느 어플리케이션이든 기본적으로 하나씩은 포함되곤 한다. 스프링 프레임워크에서는 대개 구현체를 지원하는 팩토리빈 클래스라던가 객체를 다른 클래스에서 요구하는 형태로 가공해주는 역할의 클래스들이나 부모 패키지의 인터페이스들이 구현된 클래스들이 위치해 있었다.

※ 혹시 이 패키지에 대한 다른 견해가 있으면 꼭 댓글로 말해주길 바란다.

config (구성, 설정) - 다른 언어 또는 외부 자원을 자바의 형태로 파싱해주고 그 설정을 Builder와 같은 설정 구현체에 저장해주는 역할을 담당한다.

validation (확인) - 부모 패키지의 객체들을 검증하는 검사자 클래스들이 위치한다.

util (유용한, 쓸모 있는…) - 부모 패키지의 객채들에 대해 기본적인 CRUD(Create · Remove · Update · Delete)작업을 해주거나 컬렉션 프레임워크과 비슷한, 혹은 좀 더 복잡한 작업을 도와주는 도구 클래스들이 위치한다.


인터페이스

인터페이스는 굉장히 추상적이면서도 핵심의 의표를 찔러야 하는 명명규칙이 필요하다. 그러므로 가장 직관적이고 누구나 이해할 수 있는 단어로 선별해 내는 것이 중요하며 전치사나 동사를 사용하지 않는 것이 좋다.

대개 1~2 단어만 조합되므로 명명규칙이 필요 없을 것 같지만 설계가 좀 더 다양화되고 구체적이게 될수록 인터페이스 간의 관계 또한 복잡해지므로 다음의 스프링 클래스의 이름을 보면서 개발자들이 사용하고 있는 명명규칙을 조금이나마 이해하면 도움이 될 듯 하다.

예) ApplicationContext

// ApplicationContext는 사실 총 6개의 각기 다른 성격의 인터페이스들을 상속받고 있으며 스프링에서 중요한 역할을 담당하는 컨텍스트의 가장 원시적인 모델이기도 하다.

ApplicationContext -▷ EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher, ResourcePatternResolver

ConfigurableApplicationContext -▷ ApplicationContext (and LifeCycle)
AbstractApplicationContext -▷ ConfigurableApplicationContext
GenericApplicationContext -▶ AbstractApplicationContext
GenericXmlApplicatonContext -▶ GenericApplicationContext
AnnotationConfigApplicationContext -▶ GenericApplicationContext

위의 인터페이스와 클래스 간의 이름들을 보면 알 수 있는 뻔한 사실이긴 하지만 ApplicationContext 인터페이스를 상속 또는 구현하고 있는 모든 객체가 동일하게 ApplicationContext란 원시 인터페이스의 이름을 유지하고 있다는 것이다. 물론 ApplicationContext 인터페이스 자체는 본인의 이름과 전혀 관계없는 인터페이스들을 구현하고 있긴 하지만 그것도 이유가 다 있다.

왜냐하면 ApplicationContext란 인터페이스에는 2가지의 개념이 적용되고 있는데 바로 인터페이스 간의 포함과 상속개념이 그것이다. 과거에 초보시절에 자바를 배우던 기억을 어렴풋이 더듬어보면 클래스끼리는 클래스 내부에 다른 클래스를 포함시키면 포함관계고 상속 받으면 상속 관계라고 배웠고 인터페이스는 상속은 가능해도 클래스처럼 포함관계를 가질 수 없다고 배웠다.

물론 인터페이스끼리 포함관계가 성립될 수 없다는 것이 맞는 말이긴 하나, 중요한 것은 원칙에 의해 프레임워크를 만들다 보면 때로는 인터페이스 간에도 포함이라는 관계가 필요하다는 것이다. (사실 필자는 그런 경지에 까지 올라가야할 어플리케이션을 만들어 본적은 없지만…) 물론 정확한 사실은 아니지만 필자가 예측하기에 스프링 개발팀은 합치기엔 너무도 다른 성격의 기능들을 각기 다른 클래스로 분리해야만 했고 분리해냄과 동시에 또 의존적 주입이 가능하도록 분리한 클래스들의 인터페이스를 구현해야만 했다. 그리고 그 분리해낸 기능이 합쳐지는 클래스 또한 의존적 주입이 가능하도록 다시 합쳐진 인터페이스를 구현해야 했기 때문에 저런 형태의 인터페이스와 클래스나 나왔던 것이다.

스프링 팀이 이런 문제를 해결하기 위해 반드시 복잡한 인터페이스 다형성 기술을 도입할 필요는 없었지만 아마 자신들의 의존적 주입방식에 대한 확고한 철학이 있었기에 이런 방식으로 문제를 해결할 수 밖에 없었을 것이다. 물론 인터페이스의 다형성 원칙이 원래는 존재하지 않았던 엄청난 기술은 아니지만 대개 인터페이스 상에서 다형성을 구현할 정도로 복잡한 코드를 짜는 프로그래머들이 많지 않기에 조금 시간을 할애해서 설명을 덧붙일 필요성은 있지 않나 싶다.


클래스

스프링을 이용한다면 Dependency Injection이 가능한 형태로 클래스를 만들도록 정말 노력해야 한다. 설마가 사람잡는다고 "이걸 확장할 필요가 있겠어?"란 생각에 인터페이스도 없이 작성한 클래스가 어쩌다보니 확장이 필요하게 되는 경우가 생길 수도 있는 것이다. 그러므로 모든 클래스는 가급적 작성 전에 원시 형태의 인터페이스를 우선 작성하는 것을 고려해야 하며 최대한 모든 조건 하에 주입관계가 이루어지도록 코드를 작성해야 한다.

그러므로 필자는 스프링을 이용하고 항시 인터페이스를 구현한 클래스를 사용한다는 조건 하에 설명하겠다.

Simple + 인터페이스명 : Simple로 시작하는 클래스명은 이 인터페이스의 가장 기본적인 구현체를 뜻한다. 간혹 인터페이스명 + Impl과 같이 사용하는 경우도 있는데 좀 더 의미를 명확하게 하기 위해 Simle이란 접두어를 사용할 것을 권장한다.

용도명 + 인터페이스명 : 기본 구현체 외에 다른 방식으로 이용된다면 용도를 접두어로 사용하는 클래스가 구현된다.

인터페이스명 + Utils : 특정 구현체를 인자로 받아 다양한 역할을 수행해주는 도움 클래스를 지칭한다.


메서드

마지막으로 메서드의 작명규칙이다. 아마 개발자들이 가장 고민하고 답답해하는 부분이 바로 메서드명이 아닐까 싶다. 사실 메서드 명에는 정말 자세히 들여다 보지 않으면 눈에 띄지 않는, 정말 깨알 같이 적용되곤 하는 규칙들이 존재한다. 뭐 get, set같은 거는 이미 오래 전부터 널리 알려진 규칙이고 아래에 작성된 규칙들 또한 프로그래머들 간에 보이지 않는 약속 축에 속한다고 보면 된다.

접두어로의 사용

get… : 어떠한 리소스를 리턴하는 메서드

set… : 프로퍼티에 해당 리소스를 내장시키는 역할의 메서드 

init… : 초기값이 필요하다면 초기값을 설정하고 내부에서 관련 validate를 실행하는 역할의 메서드

load… : 전달인자를 기준으로 어떠한 값을 불러와 내장시켜주거나 카운팅하는 역할의 메서드

is… : 불리언 메서드에서 사용되는 접두어이다. 용도는 get과 같다.

has… : contains 메서드처럼 어떠한 값을 가지고 있는지 확인해준다. 다른 점이 있다면 contains는 좀 더 범위가 넓지만 has는 특정 값으로 범위가 한정되있다.

register… : 기본적으로 set과 동작하는 방식이 같지만 set은 자바빈 규약에 얽혀있기 때문에 복잡한 연산을 포함할 수 없다. 보다 지능적인 set이 요구될 때 register과 같은 접두어를 사용한다.

create… : register…는 보통 void 형태이지만 create는 전달인자를 통해 새로운 객체를 만든 뒤에 이 객체를 리턴해준다. 등록과 생성은 엄밀히 다르므로 create를 register처럼 써서는 안될 것이다.

to… : 많이 만들어두면 참 좋은 접두어 메서드이다. 해당 객체를 다른 형태의 객체로 변환해준다.
전치사로의 사용

A-By-B : B를 기준으로 A를 하겠다는 뜻
ex) getUserByName(String name) : 이름값을 통해 유저를 불러옴

A-With-B : B와 함께 A를 하겠다는 뜻
ex) registerWithGeneratedName(BeanDefinition beanDefinition) : beanDefinition으로 다른 메서드를 통해 GeneratedName 값을 불러와 함께 저장.
접미사로의 사용

…With : 무엇과 함께 있는지, indexOf와 비슷한 성격의 접미사이다.
…s : 해당 객체가 복수의 객체를 반환하는지 단일 객체를 반환하는지 구분하는 것은 매우 중요하다. 복수형으로 표현해야 하는 메서드는 반드시 복수형으로 표현하여야 한다.

이외에도 많은 메서드 명명 규칙이 있겠지만 여기까지 하는 것으로 마무리 하겠다. 이게 전부라고 생각하지는 말고 좀 더 구체적이고 다양한 명명규칙을 가지고 있으면 개발시에 참 편리하다. 그리고 추가로 필요한 명명 규칙이 있어야만 한다면 댓글로 신랄하게 적어주길 바란다.


출처 : http://egloos.zum.com/springmvc/v/539238


반응형

이클립스 실행 인자 입력 받기

보통 위 제목으로 검색을 하면

Run -> Run Configuration

요 정도에서 해결한다.

하지만 인자를 바꿀 때 마다 항상 반복해야되고

심지어 단축키도 없다.(있을 수도 있으나 아직까지 모름)

여기서 한발짝 더 나아가

실행할 때마다 인자를 입력받게 할 수 있으니...


이렇게 설정하고 나서 apply 해주면

실행시마다 아래와 같이 인자를 입력 받는 창이 뜬다.


엄훠.. 내가 원하던게 이거야!

출처 : http://guldari.tistory.com/entry/%EC%9D%B4%ED%81%B4%EB%A6%BD%EC%8A%A4-%EC%8B%A4%ED%96%89-%EC%9D%B8%EC%9E%90-%EC%9E%85%EB%A0%A5-%EB%B0%9B%EA%B8%B0


반응형

자바7 출시가 점점 앞으로 다가오는데, 마음에 드는 자바7의 몇 가지 특징들은 다음과 같다.

  • try-with-resources
  • 멀티캐치(multicatch)
  • switch-case에 문자열 지원
  • Fork/Join
  • ECC 암호화 기능 제공

try-with-resources 이용 자원 해제 자동 처리

사실 이거 진작에 필요했던거다. 뭔가 자원을 생성하고 사용하고 해제하는 코드는 항상 다음과 같이 구조가 중복되는 코드를 작성해야 했다. finally 블록의 자원 해제 코드 정말 하는 거 없이 여러 줄 차지한다.

SomeResource resource = null;
try {
    resource = getResource();
    use(resource);
} catch(...) {
    ...
} finally {
    if (resource != null) {
        try { resource.close(); } catch(...) { /* 아무것도 안 함 */ }
    }
}


이게 코딩할 때 참 귀찮게 만드는 건지 알았는지 자바7에서 try-with-resources라는 특징이 추가되었다. 이건 문법 차원에서 추가된 건데, try에 자원 객체를 전달하면 finally 블록으로 종료 처리를 하지 않아도 try 코드 블록이 끝나면 자동으로 자원을 종료해주는 기능이다. 모습은 아래와 같다.

try (SomeResource resource = getResource()) {
    use(resource);
} catch(...) {
    ...
}


뭔가 코드 줄 수가 많이 줄어드는 것을 알 수 있다. finally 블록에 출현했던 자원 해제 코드를 작성하지 않아도 되기 때문에 코딩도 편하다. try 블록에서 사용하는 자원의 개수가 늘어나면 try-with-resources의 위력은 배가 된다. 아래는 예이다.

try (InputStream in = new FileInputStream(inFile);
     OutputStream out = new FileOutputStream(outFile)) {
    ...
} catch(IOException ex) {
    ...
}
// in과 out 모두 자동으로 종료됨



멀티캐치(multicatch)

예외 처리 블록도 참 코드를 길게 만들어주는 것 중의 하나였다. 어떤 메서드를 실행하면 예외가 AException, BException, CException이 발생하는데, 이 세 예외에 대해 AException과 BException은 동일한 코드를 실행하고 CException은 다른 코드를 실행한다고 하자. 만약 AException과 BException이 공통의 부모 예외 클래스가 없다면 다음과 같이 중복되는 코드를 작성해 주어야 했다.

try {
    throwABCmethod();
} catch(AException ex) {
    any(ex); // 코드 중복
} catch(BException ex) {
   any(ex); // 코드 중복
} catch(CException ex) {
    some(ex);
}


항상 개발 서적에서 나오는 말 중의 하나는 코드 중복을 없애라는 것이다. 그런데, 애초에 언어가 저 따구로 밖에 코드를 만들 수 없도록 했기 때문에 부득이 예외 처리 부분에서 중복된 코드가 발생했었다. 그런데, 자바7 버전에서 다음과 같이 하나의 catch 블록에서 동시에 여러 예외를 묶어서 처리할 수 있도록 했다.

try {
    throwABCmethod();
} catch(final AException | BException ex) {
    any(ex);
} catch(CException ex) {
    some(ex);
}


catch 블록에서 한번에 여러 개의 예외를 잡을 수 있다는 의미로 위 방식을 멀티캐치(multicatch)라고 하는데, 멀티캐치 덕에 주저리 주저리 길게 나열되면서 중복되는 catch 블록을 작성하지 않아도 된다.

switch-case의 문자열 지원

이것도 좀 진작에 지원해 주었으면 좋으련만, 어쨋든 switch-case에 이제 문자열을 사용할 수 있게 되었다.

String value = ...;
switch(value) {
case "city":
    ...
case "country":
    ...
}



fork/join을 이용한 작업 분할 실행

자바에서 분할-정복(divide-and-conquer) 방식으로 작업을 분해하고 실행하려면 직접 관련 코드를 만들어주어야 했다. 그런데, 필자 같은 경우는 멀티코어가 정착되면서 뭔가 작업을 분할해서 다중 쓰레드를 이용해서 병렬로 정복하고 싶은 싶은 욕구가 생긴다. 필자 외에도 많은 개발자들이 멀티코어를 활용하고 싶은 욕구가 있을텐데, 자바7에 분할-정복 방식을 위한 ForkJoinPool 클래스가 추가되었다. 이 클래스는 큰 작업을 작은 작업으로 나누고 각각의 분할된 작업을 병렬로 처리해주는 기능을 제공하기 때문에 멀티코어 환경에서 처리 시간을 단축할 수 있도록 하고 있다.

중요한 건 프레임워크이기 때문에 내가 밑바닥부터 만들 필요가 없다는 점이다. 그냥 제공하는 API에 맞게 코드를 만들어주면 땡이다.

ECC 암호화 기본 내장

이것도 진작 넣었더라면 더 좋았을 것을. 암호화 처리를 위해 ECC를 제공하지 않아 외부 라이브러리를 사용하는 곳이 많았는데, 이제 그럴 필요가 없어졌다. 드디어 자바가 ECC를 지원하기 시작했다.

기타

이 외에 NIO 강화, 네트워크 관련 기능 강화 등이 있다.


출처 : http://javacan.tistory.com/entry/my-interesting-java7-five-features

반응형

JAVA의 기본 정책으로는 AES128 암호화 방식까지만 사용이 가능하므로
AES256 방식으로 암호화를 하게 되면 아래와 같은 Exceptioin이 발생합니다.

java.security.InvalidKeyException: Illegal key size

이를 해결하기 위한 방법은

$JAVA_HOME/jre/lib/security 에 아래의 unlimited strength crypto file을 덮어 쓰기 하시면 됩니다.

local_policy.jar US_export_policy.jar

Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files 7 다운로드

참고로 미 통상법에 의해 자국내에서만 AES256 방식이 허용되었다고 하네요.

아래 내용 참고하시면 되겠습니다.
참고 URL : http://www.raritan.com/helpfiles/ccsg42/en/1926.htm

Check Your Browser for AES Encryption

CC-SG supports AES-128 and AES-256. If you do not know if your browser uses AES, check with the browser manufacturer.

You may also want to try navigating to the following web site using the browser whose encryption method you want to check: https://www.fortify.net/sslcheck.html. This web site will detect your browser’s encryption method and display a report. Raritan is not affiliated with this web site.

Note: Internet Explorer 6 does not support AES-128 or -256 encryption.

AES-256 Prerequisites and Supported Configurations

AES-256 encryption is supported on the following web browsers only:

  • Firefox 2.0.0.x and later
  • Internet Explorer 7

Note: Internet Explorer 7 supports AES-128 or -256 encryption in Windows Vista only. It does not support any AES encryption in Windows XP.

In addition to browser support, AES-256 encryption requires the installation of Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files 6.

To enable the AES-256 encryption with your browser

  1. Download JCE Unlimited Strength Jurisdiction Policy Files 6 from http://java.sun.com/javase/downloads/index.jsp.
  2. Extract the files into your Java directory under \lib\security\. For example, C:\Program Files\Java 1.6.0\lib\security\.
출처 : https://dukeom.wordpress.com/2013/01/03/aes256-%EC%95%94%ED%98%B8%ED%99%94%EC%8B%9C-java-security-invalidkeyexception-illegal-key-size-%ED%95%B4%EA%B2%B0-%EB%B0%A9%EC%95%88/


'JAVA > Java' 카테고리의 다른 글

이클립스 실행 인자 입력 받기  (0) 2016.11.02
자바7에서 마음에 드는 다섯 가지  (0) 2016.10.17
이클립스 SVN 설정  (0) 2016.06.30
이클립스 메모리 늘리기  (0) 2016.06.23
이클립스 디컴파일러(JAD) 설정하기  (0) 2016.06.10
반응형


이클립스(Eclipse IDE)를 쓰다가 어느 날, 왼쪽의 Package Explorer 창에서 각 프로젝트 옆에 표시되는 SVN 관련 정보 (revision 번호, SVN repository 주소 등)가 사라져 있는 것을 발견했다.

설정을 바꾸지 않는데도 이렇게 갑자기 보이지 않게 되는 것이 이상하지만, 어쨌든 이클립스를 새로 설치할 필요 없이 설정을 변경해서 다시 복구할 수 있다.



(1) 메뉴에서 Window > Preferences 선택


(2) General > Appearance > Label Decorations 선택

오른편에서 "SVN" 항목이 선택되어 있지 않다면, 체크해서 선택한다.





추가로, SVN 관련 표시에 대한 설정(글자색, 아이콘 등)을 변경하고자 한다면, 

Team > SVN > Label Decorations 에 가면 된다.



출처 : http://skylit.tistory.com/123


반응형

이클립스/Eclipse 메모리 Heap 영역 늘리기

이클립스를 사용하면서 시스템 과부하나 메모리 부족 현상을 느낀 경험이 많이 있으실 겁니다.

이는 JVM이 메모리 영역을 사용하기 때문에 나타나는 현상인데요, JVM 은 메모리 관리를 
Heap과 PermGen 영역으로 나누어 

관리하기 
때문인데요. JVM의 일반적인 실행 영역은 Heap 영역이라고 합니다. PermGen 영역은 클래스 메타 데이터를 관리해 

주는 영역이구요.


그렇게 때문에 JVM의 Heap영역과 PermGen 영역을 늘려주면 보다 전보다 원할한 작업을 진행 할 수 있습니다.

Heap영역과 PermGen영역을 늘리는 작업을 시작해 보겠습니다.




1. Eclipse가 설치된 폴더에 eclipse.ini 라는 파일을 열어 보셔야 합니다
.
 ( 참고로 이클립스는 인디고 버전 입니다. )

 
위에 그림에서 보면 vmargs 밑에 Xms1024m , Xmx1024m 이라고 보이실 겁니다.

Xms1024m 은 Heap영역의 시작크기를 나타내고, 

Xmx1024m 은 Heap영역의 최대크기를 나타 냅니다.

일단 저는 1기가의 메모리를 할당 하였습니다.

여기서 주의할 점은 Heap영역의 최대크기는 Heap영역의 시작크기 보다 같거나 커야 한다는 사실 입니다.

만약 최대크기가 작아지면 시스템 부하에 걸릴 수 있다고 합니다.

ini 파일 설정을 마친 후에는 이클립스를 실행 후




2. 이클립스 상단 메뉴
에 Window -> Preferances ->  Genaral -> 'Show heap status' 를 체크해 줍니다.




체크 후 OK버튼을 눌러 적용하면,

 
힙사이즈가 1024M 로 늘어난 것을 확인 하실 수 있습니다.

그리고 저 깡통 휴지통 모양을 클릭 하면 가비지컬렉팅 되어 메모리를 정리 합니다.

아참 그리고 중요한 사실은 힙사이즈를 1024M로 늘리면 무조건 이클립스 자체가 컴퓨터 상의 메모리 1024M를 자기 영역으로

확보하므로 다른 작업을 할 경우 메모리가 부족
 할 수 도 있기 때문에,

상황에 맞춰 적당한 영역을 설정 하여 사용 하시기 바랍니다.



그럼 버벅거림 없는 빌드를 이용해 즐거운 코딩 하시기 바랍니다~!ㅎ 


출처: http://blog.daum.net/sbrae/34

반응형

이클립스에 디컴파일러 인 "JAD" 를 설정해 보자.

 

개발하다 문득 클래스 파일이 어떻게 되어 있나 궁굼했다. 그래서 어떻게 확인 할 수 있나 찾아보니..

"JAD" 를 이클립스에 설치하면 class파일을 java 소스처럼 볼 수 있었다. 우 헤헤헤 ~ 

 

"JAD"를 사용하기 위해서는 다음의 2가지 파일이 필요하다.

 

 jad158g.win.zip

    ( jad 실행파일 )

사이트 : http://www.varaneckas.com/jad

 

 net.sf.jadclipse_3.3.0.jar

    ( 플러그인 )

사이트 : http://jadclipse.sourceforge.net/wiki/index.php/Main_Page#Download

 

 

이제 이클립스에 JAD 를 설정해보자.

 

1. jad 는 아무 경로에 압축을 풀면 된다. 난 이클립스가 설치된 경로에 넣어두었다.

나의 이클립스 경로는 (D:\eclipse)

 

2. 설치된 이클립스의 "plugins" 디렉토리 에 다운받는 "net.sf.jadclipse_3.3.0.jar" 플러그인 파일을 복사한다.

 

3. 이클립스를 실행하고 상단 탭 메뉴의 "Window > Preferences" 를 클릭하면 아래와 같이

" JAVA" 항목밑에 "JadClipse" 항목이 추가 되어 있어야 한다.

( 만약 보이지 않는다면 "plugins" 디렉토리에 "net.sf.jadclipse_3.3.0.jar" 파일이 들어있는지 다시 확인 후 이클립스를 재기동 해준다. ) 여기까지 이상이 없다면 "Path to decomplier" 에 jad를 설치한 풀경로를 넣어준다.

난 이클립스 경로에 넣어줬음.

 

 

 

4. General > Editors > File Associations 에서 *.class , *.class without source 를 선택하여

"JadClipse Class File Viewer" 를 선택하여 우측의 default 버튼을 클릭하여 "default" 시켜준다.

(** 만약 항목에 보이지 않는다면 옆에 "Add.."버튼을 클릭하여 추가시켜준다.)

 

 

자!! 이제 모든 설정은 끝~!! 이젠 클래스 파일이 잘 읽혀지는지 확인해 봐야겠지..

아무 클래스 파일을 하나 열었더니... 똬앗~!! 아래처럼 이상한 에러같은게 보이면서 아무내용이 안나왔다.

ㅡㅡ;; 멍미...

 

"class" 파일을 디컴파일 하기 위해서는 프로젝트에 환경변수 안에 참조되어 있어야 했다... ㅜㅜ

아래는 참조된 jar 파일안에 있는 class 파일을 연 모습이다. ^______^

 

 

 

저작자 표시
출처 : http://lovelyjk.tistory.com/72


반응형

이클립스에 EGit 플러그인 설치 후 Github 연동



  • EGit 플러그인 설치

Help > Install New Software.. 이동

Work with의 셀렉트 버튼 클릭 후 Indigo - http://download.eclipse.org/releases/indigo 선택

Collaboration 메뉴 확장 후 Eclipse EGit 체크 후 설치



  • git 설정

window > Preferences > General > Network Connections > SSH2의 key management탭에서 Generate RSA Key 생성 후 Save Private Key 클릭

id_rsa 파일과 id_rsa.pub 파일이 생성이 되는데 원하는 디렉토리에 저장한다. (나는 D:\\git 디렉토리에 저장하였음)

key를 만들어 주는 이유는 github과 연동 시 https로 통신해야 하기 때문이다.


Team > Git > Configuration

New Entry... 버튼 클릭하여 Key, Value 부분에 아래 두 가지 정보를 추가한다.

user.name : namkyu

user.email : lng1982@gmail.com



  • github 가입

https://github.com/ 페이지 이동 후 가입 진행

github setting > SSH Keys 이동하여 id_rsa.pub 안에 들어있는 내용을 넣어준다.






  • git repository 생성

오른쪽 상단에 있는 Create a new repo 아이콘 클릭



Repository name input box 부분에 적당한 이름 추가 후 "Create repository" 버튼 클릭

생성 완료 페이지에 https://github.com/namkyu/EgitTest.git URL이 보이는데 해당 URL copy



  • 이클립스와 github repository 연결

이클립스에서 EGitTest 자바 프로젝트 생성

Team > Share Project > Git

Use or create repository in parent folder of project 체크 박스 체크

"Create Repository" 버튼 클릭


Git Repositories View에 EgitTest가 생성되어 있음

Remotes 클릭 후 오늘쪽 마우스 > Create remote

Remote name은 "origin" 입력

change 버튼 클릭 후 아래 정보 추가



"Finish" 버튼 클릭

여기까지 설정을 했으면 이제 github과의 연동이 완료된 것이다.

이후 EGitTest 프로젝트 우클릭 후 Team > Push up stream 을 누르면 github 저장소에 commit 한다.




  • 맘에 드는 프로젝트 내 이클립스로 다운로드 받고 싶을 때

github에는 많은 오픈 소스 프로젝트가 올라오고 있다. 

소스를 다운로드 받아 공부하고 싶을 때에는 https://github.com/사용자아이디/다운로드받을프로젝트.git 와 같은 URL을 copy한 후 Git Repositories에서 설정 추가하여 소스 다운로드 받는다.


출처: http://lng1982.tistory.com/154

반응형

eclipse에 github 연결해서 웹저장소에서 버전관리(repository)하기


아직 Git 플러그인을 설치하지 않았거나 github에서 repository를 만들지 않았다면, 위 2개의 글을 먼저 확인하시고 다시 오세요.

그리고 혹시, 다른 repository와 프로젝트가 연결돼 있다면 아래 그림처럼 disconnect 하셔서 먼저 연결을 끊으셔야 합니다.






Git Repositories 에서 [Clone a Git repository]를 클릭하세요~


URI에 https의 github URI를 입력해 주세요.

아래 그림처럼 Host와 Repository path를 분리해서 넣어주시구요.

github.com에서 만든 계정(user/password)도 입력해 주세요.


혹시, github.com의 repository URI를 모르신다면 아래 그림처럼 github.com 로그인하고 해당 repository 클릭해서 URI 확인하시면 됩니다.


[Next] 누르시고요.




자, repositories를 생성했으니 이걸 project와 연결해 보겠습니다.

연결할 project에서 마우스 오른쪽 클릭하셔서 [Team > Share Project...] 클릭하세요.




방금 생성한 repository 선택하시구요. [Finish] 버튼 누르세요.



자, 연결이 되었으니 소스를 올려볼까요?



[Add to Index] 하시면 Storage 영역에 해당 소스들을 올려놓게 됩니다.

*표로 파일이나 폴더가 표시됩니다.




[Commit and push] 하시면 github로 파일을 올릴 수 있습니다.



branch를 선택하시면 되는데요.

다른 branch를 만들지 않았다면 master가 기본입니다.

선택하시면 됩니다.







[OK] 버튼을 누르면 github로 소스 전송이 완료됩니다.

github에 로그인해서 소스가 정말 올라와 있는지 확인해 보겠습니다.




잘 올라와 있네요^^

이젠 저도 github를 잘 활용해서 장소와 상관없이 편리하게 개발도 하고, 다른 사람들과 협업도 해봐야겠습니다.



출처 : http://zzznara2.tistory.com/398


+ Recent posts