<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.edwith.webbe</groupId>
<artifactId>calculator</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>calculator Maven Webapp</name>
<url>http://maven.apache.org</url>
<!-- Eclipse에서는 web.xml 파일을 작성하지 않고, Java Config를 사용할 때 failOnMissingWebXml를
false로 설정합니다. -->
<!-- spring 버전은 5.0.2.RELEASE버전을 사용합니다. 2020/02/03일 기준 최신버전 -->
<properties>
<failOnMissingWebXml>false</failOnMissingWebXml>
<spring.version>5.2.3.RELEASE</spring.version>
</properties>
<dependencies>
<!-- servlet-api이다. tomcat에 배포될 경우엔 사용되지 않도록 하기 위해서 scope를 provided로 설정하였다. -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!-- jsp-api이다. tomcat에 배포될 경우엔 사용되지 않도록 하기 위해서 scope를 provided로 설정하였다. -->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.2-b02</version>
<scope>provided</scope>
</dependency>
<!-- jstl은 tomcat이 기본 지원하지 않는다. 그렇기 때문에 tomcat에도 배포가 되야 한다. -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- spring webmvc에 대한 의존성을 추가한다. spring webmvc에 대한 의존성을 추가하게 되면 spring-web,
spring-core등이 자동으로 의존성이 추가된다. -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- RestController의 json 변환을 위해 필요함 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.8</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.8</version>
</dependency>
<!-- java 9 이상에서 추가해줘야 합니다. @PostConstruct 등을 사용하려면 필요함 -->
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- swagger2 의존성 추가 Swagger 사용을 위해서는 구현체인 springfox-swagger2 가 필요하며, 또
가장 중요한 (사용목적이라해도 과언이 아닌) UI 적으로 확인을 위해서는 springfox-swagger-ui 이렇게 2개의 라이브러리가
필요하다. -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.6.1</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.6.1</version>
</dependency>
</dependencies>
<build>
<finalName>calculator</finalName>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>utf-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
</project>
package org.edwith.webbe.calculator.config;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
import javax.servlet.*;
public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
// Spring 기본 Config 클래스 지정
// ApplicationConfig.class 사용
@Override
protected Class<?>[] getRootConfigClasses() {
return Class<?>[] {ApplicationConfig.class};
}
//Spring MVC Config 클래스 지정
// MvcConfig.class 사용
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[] {MvcConfig.class};
}
// DispatcherServlet이 동작할 맵핑 정보 설정
// "/"으로 설정해 모든 요청을 DispatcherServlet이 처리하도록 함
@Override
protected String[] getServletMappings() {
return new String[] {"/"};
}
// 인코딩 필터 설정
@Override
protected Filter[] getServletFilters() {
CharacterEncodingFilter encodingFilter = new CharacterEncodingFilter();
encodingFilter.setEncoding("UTF-8");
return new Filter[] {encodingFilter};
}
}
package org.edwith.webbe.calculator.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages= {"org.edwith.webbe.calculator.service"})
public class ApplicationConfig {
}
MvcConfig.java
package org.edwith.webbe.calculator.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration
@EnableWebMvc
@EnableSwagger2
@ComponentScan(basePackages = { "org.edwith.webbe.calculator.controller" })
public class MvcConfig implements WebMvcConfigurer {
// DefaultServlet에 대한 설정
// DispatcherServlet이 처리하지 못하는 URL은 DefaultServlet이 처리
// 자동 생성된 Swaager 페이지를 보기 위함
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
/*
* Swagger 사용 시에는 Docket Bean 을 품고있는 설정 클래스 1개가 기본으로 필요하다. Spring Boot 에서는 이
* 기본적인 설정파일 1개로 Swagger 와 Swagger UI 를 함께 사용가능하지만, Spring MVC 의 경우 Swagger UI 를
* 위한 별도의 설정이 필요하다. 이는, Swagger UI 를 ResourceHandler 에 수동으로 등록해야 하는 작업인데, Spring
* Boot 에서는 이를 자동으로 설정해주지만 Spring MVC 에서는 그렇지 않기 때문이다.
*/
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2).select().apis(RequestHandlerSelectors.any()) // // 현재 // 할당된 모든 URL 리스트를
// 추출
.paths(PathSelectors.ant("/api/**"))// PathSelectors.any() 를 할경우 모든 경로가 다 사용된다. RestController가 아닌 것 까지
// 사용된다.
.build().apiInfo(apiInfo()).useDefaultResponseMessages(false);
}
//API Info
private ApiInfo apiInfo() {
Contact contact = new Contact("MinKyeong Kim", "https://www.edwith.org", "cherrypy91@gmail.com");
ApiInfo apiInfo = new ApiInfo("Swagger Sample", "APIs Sample", "Sample Doc 0.1v", "", contact,
"This sentence will be display.", "/");
return apiInfo;
}
}
package org.edwith.webbe.calculator.service;
import org.springframework.stereotype.Service;
@Service
public class CalculatorService {
public int plus(int value1, int value2) {
return value1+value2;
}
public int minus(int value1, int value2) {
return value1-value2;
}
}
package org.edwith.webbe.calculator.dto;
public class CalculatorResult {
public static final String PLUS_OPERATION = "+";
public static final String MINUS_OPERATION = "-";
public static final String MULTIPLE_OPERATION = "*";
public static final String DIVIDE_OPERATION = "/";
private int value1;
private int value2;
private int result;
private String operation;
public int getValue1() {
return value1;
}
public void setValue1(int value1) {
this.value1 = value1;
}
public int getValue2() {
return value2;
}
public void setValue2(int value2) {
this.value2 = value2;
}
public int getResult() {
return result;
}
public void setResult(int result) {
this.result = result;
}
public String getOperation() {
return operation;
}
public void setOperation(String operation) {
this.operation = operation;
}
}
다음 명세에 맞게 매핑
CalculatorApiController.java
package org.edwith.webbe.calculator.controller.api;
import org.edwith.webbe.calculator.dto.CalculatorResult;
import org.edwith.webbe.calculator.service.CalculatorService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
@RestController //응답 결과를 json으로 보내기 위함
@RequestMapping(path="api/calculator") //공통적으로 path 지정(기본 path로 받아들여짐)
public class CalculatorApiController {
@Autowired
private CalculatorService calculatorService;
//Swagger가 제공하고 있는 어노테이션
//간단한 설명을 적어줄 때 사용
@ApiOperation(value = "덧셈 구하기")
// Response Message에 대한 설명
@ApiResponses({
@ApiResponse(code = 200, message = "OK"),
@ApiResponse(code = 500, message = "Exception")
})
@GetMapping("/plus")
public CalculatorResult plus(@RequestParam("value1") int value1, @RequestParam("value2") int value2) {
CalculatorResult calculatorResult = new CalculatorResult();
calculatorResult.setValue1(value1);
calculatorResult.setValue2(value2);
calculatorResult.setOperation(CalculatorResult.PLUS_OPERATION);
calculatorResult.setResult(calculatorService.plus(value1, value2));
return calculatorResult;
}
@GetMapping("/minus")
public CalculatorResult minus(@RequestParam("value1") int value1, @RequestParam("value2") int value2) {
CalculatorResult calculatorResult = new CalculatorResult();
calculatorResult.setValue1(value1);
calculatorResult.setValue2(value2);
calculatorResult.setOperation(CalculatorResult.MINUS_OPERATION);
calculatorResult.setResult(calculatorService.minus(value1, value2));
return calculatorResult;
}
}
http://localhost:8080/calculator/swagger-ui.html#
URL으로 접근하면 ApiController에서 작성한 operation들을 테스트할 수 있다!
swagger 메인 화면
테스트 해본 화면, 구현해놓은 함수에 따라 작동함