진형아빠이야기

스프링 부트는 excutable jar를 지원합니다. 

뭔말인고 하니 그냥 웹서버고 와스고 신경쓸거 없이 내장 톰캣을 통해서 프로젝트에서 한번에 말아서 배포하고 실행이 가능하다는 말씀!

게다가 H2같은 데이터베이스 까지 사용한다고 하면 WAS와 DB까지 하나의 JAR로 말아서 실행해버리는게 가능합니다.


일반적인 자바의 경우 웹 아파치 올리고 와스 톰캣 올리고 스프링 올리고 MYSQL연결하는 등의 작업을 할 필요가 없다는 말입니다.


성능이랑 세세한 튜닝은 어떻게 하냐고요?

네! 맞습니다. 그런건 디테일하게 신경쓰지 않았습니다. 사실 그 정도 질문을 하실 정도면 굳이 어렵지 않게 JAR를 WAR로 바꾸어서 일반적인 환경으로 다시 세팅할수도 있을듯 합니다. 


즉, 초기 세팅에 힘을 괜히 빼고 싶지 않은 경우 설정하면 좋을듯 합니다. 


우선 프로젝트를 만듭니다. 

뭐 어렵지 않게...그냥 데이터베이스도 없이 화면의 스트링을 리턴해주는 웹 애플리케이션을 만들어보겠습니다. 

여기서의 목적은 실행 JAR생성하고 실행하는데 목적이 있으니까요..^^


STEP1. 프로젝트 생성하기

이 부분은 간단하기도 하고 알고 있을거라고 생각하고 넘어가겟습니다.

Web모듈을 넣어서 간단하게 REST 리턴에 대한 확인을 수행할 예정입니다. 




STEP2. 프로젝트 실행 확인하기

이렇게 이클립스STS에서 실행하면 프로그램이 돌아가는것을 확인할 수 있습니다.

STEP3. 실행JAR로 패키징 하기

일반적인 케이스의 경우는 Maven으로 Command창에서 명령어로 입력하게 됩니다. 

하지만 저는...


그렇습니다. MAVEN패스 설정을 안해놓았네요. ㅎㅎㅎ

귀찮아서 그냥 이클립스에서 패키징을 해보도록 하겠습니다. 

MAVEN으로 업데이트 하고 난 후 Maven install을 실행합니다.


프로젝트에서 Run as - Maven build 를 선택해서 진행합니다.


Goal에서는 package를 입력해서 진행합니다.


오잉 근데...이렇게 에러가 나네요. 중간에 보시면...Perhaps you are running on a JRE ratger than a JDK? 라는 문장이 보이네요.

아무래도 JAVA옵션을 체크해봐야 겟습니다.

이클립스의 Preferences-Java-Installed JREs를 선택해서 [Add]를 눌러서 JDK를 추가합니다. 


JDK를 추가한 후 Run as - Maven Build(Goal:package)를 실행하면 다음과 같이 Build SUCCESS 메세지가 나타납니다. 


STEP4. 파일이름

이름이 맘에 안들지만 어찌 되었던 실행가능 JAR파일이 만들어졌습니다.

해당 파일을 자바가 설치된 리눅스 혹은 윈도우 에 올려놓습니다. 

일반적으로 WAS의 폴더에 놓는것을 생각하실수 있지만 잊지 말것은 이 JAR파일안에 서버가 포함되어있습니다.

Java -jar test.jar 의 명령어를 주어서 즉시 실행시켜봅니다. 




STEP5. 브라우저에서 결과 확인하기 

이제 브라우저에서 방금 프로젝트를 싱핼시켰던 결과를 확인할 수 있습니다. 

신기하네요. ㅎㅎㅎ

사실 저도 아직 이 구조에서의 클러스터링 등 여러가지 설정은 해보지 않아서 더 살펴봐야겠지만...

급하면 바로 WAR로 변경해서 예전 구조로 오기가 어렵지 않을거라고 생각됩니다.






신고

Comment +0

스프링부트 프레임워크를 사용한 입력값 검증입니다. 

일반적인 스프링 프레임워크에서도 거의 동일하게 사용이 가능할겁니다.

hibernate-validator를 사용하였습니다. 


Step1.

pom설정

프로젝트를 기본으로 생성 후 pom.xml에서는 다음과 같이 추가해줍니다. 

타임리프는 뭐 추가보다는 처음 프로젝트 생성할때 체크를 하시는게 편하겟네요. 

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
        </dependency>


Step2.

Data Class설정

실제 데이터를 담게 될 클래스에 어노테이션으로 유효성 체크를 해줍니다.

나중에 유효성 체크에서 오류 메세지를 커스터마이징 하기 위해서 @Size에 살펴보시면 message부분이 있습니다. 

messages.properties의 값에서 일치하는 값을 한 후 화면에 출력하게 됩니다.

package com.kiai;

import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

public class PersonForm {

    @Size(min=2, max=30, message = "{error.description}")
    private String name;

    @NotNull
    @Min(18)
    private Integer age;

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String toString() {
        return "Person(Name: " + this.name + ", Age: " + this.age + ")";
    }
}



Step3.

Controller 클래스 설정

public String checkPersonInfo(@Valid PersonForm personForm, BindingResult bindingResult) {


        if (bindingResult.hasErrors()) {

            return "form";

        }


이 부분을 잘 봐야 합니다. @Valid로 유효성 체크를 하겟다고 하고, 결과는 BindingResult 에 있습니다. 

메서드의 첫 부분에  if (bindingResult.hasErrors()) {~} 로 체크하여 유효성에서 오류가 발생하면 처리할 수 있도록 했습니다.

이 코드에서는 return "form"; 으로 form.html을 콜하도록 하였습니다.

package com.kiai;

import javax.validation.Valid;

import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@Controller
public class WebController extends WebMvcConfigurerAdapter {

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/results").setViewName("results");
    }

    @RequestMapping(value="/", method=RequestMethod.GET)
    public String showForm(PersonForm personForm) {
        return "form";
    }

    @RequestMapping(value="/", method=RequestMethod.POST)
    public String checkPersonInfo(@Valid PersonForm personForm, BindingResult bindingResult) {

        if (bindingResult.hasErrors()) {
            return "form";
        }

        return "redirect:/results";
    }
}


Step4.

MessageConfig 설정하기

이 예제에서는 스프링부트의 기본  MessageSource를 사용합니다.     

package com.kiai;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.validation.Validator;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@Configuration
public class MessageConfig extends WebMvcConfigurerAdapter
{
    @Autowired
    private MessageSource messageSource;

    @Bean
    public LocalValidatorFactoryBean validator()
    {
        LocalValidatorFactoryBean localValidatorFactoryBean = new LocalValidatorFactoryBean();
        localValidatorFactoryBean.setValidationMessageSource(messageSource);
        return localValidatorFactoryBean;
    }

    @Override
    public Validator getValidator()
    {
        return validator();
    }
}


Step5.

form.html 작성

th:~로 하는것은 타임리프 엔진의 문법이다. jstl같은...그쪽을 알아보도록 하자. 

중요한것은 <input>태그 다음에 오는 <td>의 th내용들입니다. ${#fields.hasErrors('name')} name의 유효성 체크가 정상인지 if로 체크한고, th:errors="*{name}" 으로 에러가 존재시 name에 해당하는 오류 메세지를 보여주게 됩니다. 딱히, 설정을 안해도 기본적인 메세지가 언어별로 정해져있습니다. 하지만, 맘에 들기 힘들테니...저희는 이전 데이터 클래스를 보시면 message를 설정하여 커스터마이징 했습니다. 

   

<html> <meta charset="UTF-8"/> <body> <form action="#" th:action="@{/}" th:object="${personForm}" method="post"> <table> <tr> <td>Name:</td> <td><input type="text" th:field="*{name}" /></td> <td th:if="${#fields.hasErrors('name')}" th:errors="*{name}">Name Error</td> </tr> <tr> <td>Age:</td> <td><input type="text" th:field="*{age}" /></td> <td th:if="${#fields.hasErrors('age')}" th:errors="*{age}">Age Error</td> </tr> <tr> <td><button type="submit">Submit</button></td> </tr> </table> </form> </body> </html>


Step6

results.html 설정

이 단계는 별거없음. 그냥 보여주기 위함.

    <html>
	<meta charset="UTF-8"/>
	<body>
		유효성 검증 통과 완료!!
	</body>
    </html>
            


Step7.

message.properties 설정하기

error.description=가나다라

기본적으로 resources폴더 밑에 message.properties를 위치합니다.




Step8. 

결과 확인




결론.

이렇게 스프링의 서버사이드 유효성 체크에 대해서 알아보았습니다. 

화면에서 하는 방법이 편하기야 하겠지만...우회하는 방법이 너무 쉽다보니 서버 측에서 유효성 체크하는 방식을 사용하는 습관을 들여야 하겠습니다. 유효성 체크의 어노테이션 사용법에 대해서 숙지할 필요가 있어 보입니다. 

신고

Comment +0

이번은 스프링 프레임워크의 스케줄 태스크에 대해서 포스팅 합니다.

시간을 일정 주기로 주고 JOB을 등록하면 정해진 주기 내지는 시간에 해당 클래스가 동작합니다.


Step1.

프로젝트 생성하기

이건 이전자료도 있고 하니...그냥 패스하겠습니다.

스프링 부트를 사용하신다면 별다르게 Dependency를 선택할 필요는 없습ㄴ디ㅏ.

Step2.

ScheduledTask 클래스 작성하기

여기 예제에서는 fixedRate로...2초 주기로 작동하게 해놓았습니다.

이 주기 부분을 보시려면 나중에 다시 정리하겠지만 cron주기 설정하는 옵션을 찾으면 됩니다.

package com.kiai.scheduled;


import java.text.SimpleDateFormat;
import java.util.Date;

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class ScheduledTask {

    private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");

    @Scheduled(fixedRate = 2000)
    public void reportCurrentTime() {
        System.out.println("The time is now " + dateFormat.format(new Date()));
    }
}


Step3.

@EnableScheduling 등록하기

스프링 부트의 경우 프로젝트명의 Application에 많은 설정을 하게 되는데요.

이 예제에서는 SpringScheduledTaskApplication.java파일에 등록을 합니다. 

일반 스프링 프레임워크라면 설정하는 xml에 하게 될겁니다.

package com.kiai.scheduled;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

@SpringBootApplication
@EnableScheduling //여기 추가됨
public class SpringScheduledTaskApplication {

	public static void main(String[] args) {
		SpringApplication.run(SpringScheduledTaskApplication.class, args);
	}
}


Step4.

결과 확인하기 

예제에서는 단순하게 타임스탬프를 찍었지만 실제로는 주기적으로 작업을 해야하는 로직을 넣으면 될겁니다.


소스코드 별게 없지만 아래 링크서 다운가능합니다.

https://github.com/ralf79/SpringScheduledTask

신고

Comment +0

이전글인 스프링부트로 Rest Webservice만들기에 이어서...

리턴을 JSON이 아닌 XML이 필요한곳도 있을듯 해서 만들어 보았습니다.


작업 순서

프로젝트 생성은 복붙활용이다 보니..클래스 이름등은 알아서들 잘 처리하시기 바랍니다. ^^;;;;

Step1.

프로젝트 생성하기

다음의 그림과 같이 프로젝트 이름을 입력하고 [Next]버튼을 눌러서 다음으로 진행한다. 

Step2.

필요한 라이브러리 설정하기

기본적으로 Web카테고리에서 [Web]만 체크하고 [Finish]버튼을 눌러서 다음으로 진행한다. 



Step3.

클래스 생성하기

우리가 사용할 클래스는 2개이다. 

첫번재는 Controller를 담당할 RestController이고, 두번째는 화면에 리턴할 데이터를 담당할 Data 클래스이다.  

Step4.

pom.xml에 jackson-dataformat-xml관련 dependency를 설정합니다.

이전에도 말씀드렸지만...전 아재라서 Maven이 여전히 익숙하네요. 

어서...Gradle이 손에 익어야 할텐데....

       <dependencies>

<dependency>

              <groupid>com.fasterxml.jackson.dataformat</groupid>

              <artifactid>jackson-dataformat-xml</artifactid>

  </dependency>

</dependencies>



Step5.

Data를 담을 클래스를 만들어 봅니다. 

여기서는 주의할것이 데이터 클래스에 @XmlRootElement 어노테이션을 넣어주는겁니다.

package com.example;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Data {
	private String name;
	private int age;
	private String telNo;
	
	public Data(String name, int age, String telNo) {
		super();
		this.name = name;
		this.age = age;
		this.telNo = telNo;
	}
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getTelNo() {
		return telNo;
	}
	public void setTelNo(String telNo) {
		this.telNo = telNo;
	}
}


Step6.

Controller클래스를 만들어주기

이전의 Rest예제와 달리 어노테이션은 @Controller를 사용했습니다. 

package com.example;

import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class RestController {

	@RequestMapping(value = "/getDataXML",
            method = RequestMethod.GET,
            produces = MediaType.APPLICATION_XML_VALUE)
	public @ResponseBody Data getData(@RequestParam(value="name", defaultValue="hyunwoo") String name){
		return new Data(name, 10, "010-37");
	}
	
}


Step7.

결과 확인하기 

브라우저에서 확인을 하면 www.localhost:8080/getData?name=hhh 를 입력하면 결과를 XML로 확인할 수 있습니다. 

XML의 경우 개인적으로 선호하지 않고 태그 데이터가 많아서 짜증나지만 범용적인 포맷으로 많이 사용되니 알아두어야 할듯 하긴 합니다. 


예제 관련 소스코드 

https://github.com/ralf79/SpringBootRestWebserviceXML

신고

Comment +0

원래는 Spring io의 Building a RESTful Web Service의 글인데 간단한 튜토리얼이 너무 길어서 그냥 내맘대로 편집해보았습니다.


준비물

- 스프링 프레임워크가 설치된 IDE(요새 대세는 인텔리J이지만 나는 아재이므로 SpringToolSuite)

- 이게 다임.!


작업순서

Step1.

프로젝트 생성하기

다음의 그림과 같이 프로젝트 이름을 입력하고 [Next]버튼을 눌러서 다음으로 진행한다. 

Step2.

필요한 라이브러리 설정하기

기본적으로 Web카테고리에서 [Web]만 체크하고 [Finish]버튼을 눌러서 다음으로 진행한다. 



Step3.

클래스 생성하기

우리가 사용할 클래스는 2개이다. 

첫번재는 Controller를 담당할 RestController이고, 두번째는 화면에 리턴할 데이터를 담당할 Data 클래스이다.  


이건 Data클래스 생성자와 Setter Getter를 만들어 놓았다. 

package com.example;

public class Data {
	private String name;
	private int age;
	private String telNo;
	
	public Data(String name, int age, String telNo) {
		super();
		this.name = name;
		this.age = age;
		this.telNo = telNo;
	}
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getTelNo() {
		return telNo;
	}
	public void setTelNo(String telNo) {
		this.telNo = telNo;
	}
}


이것은 RestController 클래스이다. 

URL은 localhost:8080/getData로 잡았다. 그리고 다른값들은 하드코딩을 했지만 name의 경우 URL을 통해서 입력을 받을 수 있도록 했다. 

즉, localhost:8080/getData?name=leehw 이런 식으로 입력하면 leehw라는 값이 name에 입력된다. 물론 아무값도 없을 경우는 defaultValue가 있어서 기본값이 입력된다.

package com.example;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

@org.springframework.web.bind.annotation.RestController
public class RestController {

	@RequestMapping("/getData")
	public Data getData(@RequestParam(value="name", defaultValue="hyunwoo") String name){
		return new Data(name, 10, "010-37");
	}
}


Step4.

실행하기

프로젝트 이름에서 마우스 우클릭을 한후 [Run As] - [Spring boot app]을 선택하면 스프링 부트의 내장 톰캣을 활용해서 서버가 기동된다. 하단의 콘솔로그를 확인하면 서버가 정상적으로 올라오는것을 확인할 수 있다. 


Step5.

확인하기

가장 좋은 것은Advanced REST client 같은 레스트 클라이언트 프로그램을 사용하는 것이지만 굳이 귀찮으신 분들을 위해서...

브라우저에서 테스트를 하면된다. (어차피 나중에 PUT, POST, DELETE등을 하기 위해서는 Advanced REST client를 배우는게 좋타)

브라우저에서 localhost:8080/getData?name=hhh 라고 입력해보자. 다음과 같이 우리가 입력한 값이 포함되어 JSON의 형태로 나타나게 될것이다. 



최종정리

이렇게 우리는 간단하게 @RestController 어노테이션을 사용해서 json으로 리턴하는 Restful WebService만드는 방법에 대해서 알아보았다. REST에는 GET, PUT, POST, DELETE의 4가지 서비스가 있는데 우리는 이중에 GET에 대해서만 알아보았다. 




신고

Comment +0

티스토리 툴바