Tạo Web API: Spring Boot - Maven - Swagger

Hi all,
Hôm nay rãnh rỗi, làm cái tutorial tạo web API bằng Spring boot hướng dẫn anh em.
Trước hết, mình dùng maven để built project nên ai thiếu maven thì cài vào, maven - eclipse trong dạy nhau học đã có topic hướng dẫn anh em tìm setup xem nhé.
Mình dùng eclipse và Ubuntu nhưng nó cũng tương tự với window,nên không vấn đề gi.
Đầu tiên, tạo maven project, nếu bạn không có plugin maven hoặc muốn dùng command line thì gõ lệnh như sau:

mvn archetype:generate -DgroupId=com.canh
   -DartifactId=JavaSpring 
   -DarchetypeArtifactId=maven-archetype-quickstart 
   -DinteractiveMode=false

DgroupId là tên package, thông thường nếu có domain riêng thì dùng tên domain nhưng ghi ngược lại, điều này đảm bảo khi public ra cộng đồng sẽ không bị trùng.
DartifactId là project name.
DarchetypeArtifactId=maven-archetype-quickstart để chỉ rằng bạn chỉ muốn generate cấu trúc project Maven đơn giản:

.
└── JavaSpring
    ├── pom.xml
    └── src
        ├── main
        │   └── java
        │       └── com
        │           └── canh
        │               └── App.java
        └── test
            └── java
                └── com
                    └── canh
                        └── AppTest.java

Tiếp đó, tạo project eclipse với maven. nếu có plugin maven trong eclipse thì có thể sử dùng plugin đó để tạo, nếu không có hoặc muốn dùng command line thì gõ lệnh:

mvn eclipse:eclipse

Lệnh này sẽ đọc file pom và generate eclipse project cho nên nhớ cd đến thư mục chứa file pom trước khi dùng lệnh này.
Lúc này cấu trúc thư mục vừa tạo sẽ như sau:

.
└── JavaSpring
    ├── .classpath
    ├── pom.xml
    ├── .project
    └── src
        ├── main
        │   └── java
        │       └── com
        │           └── canh
        │               └── App.java
        └── test
            └── java
                └── com
                    └── canh
                        └── AppTest.java

Giờ chỉ cần dùng chức năng add exist project trong eclipse là sử dụng được rồi

Tiếp theo là phần Spring boot.
Sau khi add project vào eclipse, mở file pom.xml lên và add thư viện spring boot vào:

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

<dependencies>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-web</artifactId>
	</dependency>
	<dependency>
		<groupId>junit</groupId>
		<artifactId>junit</artifactId>
		<scope>test</scope>
	</dependency>
</dependencies>

Chú ý khi thêm bất cứ gì vào file pom.xml bạn cần update lại project của mình, ở đây mình dùng lệnh để update:

mvn clean install

Vậy là có thể implement API với Spring boot,
Trong project, mình tạo một số package và folder package như hình dưới:

.
├── main
│   ├── assembly
│   │   └── assembly.xml
│   ├── java
│   │   └── com
│   │       └── canh
│   │           ├── App.java
│   │           ├── config
│   │           │   └── WebConfig.java
│   │           ├── dto
│   │           │   └── UserDto.java
│   │           ├── services
│   │           │   ├── ExampleServicesImpl.java
│   │           │   └── ExampleServices.java
│   │           └── web
│   │               └── api
│   │                   └── ExampleController.java
│   ├── resources
│   │   └── application.properties
│   └── script
│       └── startServer.sh
└── test
    └── java
        └── com
            └── canh
                └── AppTest.java

Giờ các bạn chỉ chú ý đến main.java.com.canh, mấy cái khác liên quan đến config để deploy, có thời gian mình sẽ giải thích.
App.java:

package com.canh;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Configuration;

/**
 * Hello world!
 *
 */
@Configuration
@EnableAutoConfiguration
@SpringBootApplication
public class App 
{
    public static void main( String[] args )
    {
    	SpringApplication.run(App.class, args);
    }
}

App.java là file chính dùng để start program, nhớ add thêm annotation như trên để Spring nhận biết.

UseDto.java: Dùng để chứa json object từ client gửi lên server

/**
 * 
 */
package com.canh.dto;

/**
 * @author canh
 *
 */
public class UserDto {
	String userName;
	String password;

	/**
	 * @return the user
	 */
	public String getUserName() {
		return userName;
	}

	/**
	 * @param user
	 *            the user to set
	 */
	public void setUserName(String userName) {
		this.userName = userName;
	}

	/**
	 * @return the password
	 */
	public String getPassword() {
		return password;
	}

	/**
	 * @param password
	 *            the password to set
	 */
	public void setPassword(String password) {
		this.password = password;
	}

}

ExampleServices.java: Inteface định nghĩa 2 services:

/**
 * 
 */
package com.canh.services;

/**
 * @author canh
 *
 */
public interface ExampleServices {
	String test(String user, String password);

	String getNameForID(String userID);
}

ExampleServicesImpl.java: implement interface:

package com.canh.services;

import org.springframework.stereotype.Service;

/**
 * 
 * @author canh
 *
 */
@Service
public class ExampleServicesImpl implements ExampleServices {

	@Override
	public String test(String user, String password) {
		if (user != null) {
			return "success";
		}
		return "error";

	}

	@Override
	public String getNameForID(String userID) {

		return new String("canh - " + userID);
	}

}

chú ý là add thêm annotation @Service để Spring nhận biết.
Cuối cùng là ExampleController.java :

package com.canh.web.api;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestBody;
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.RestController;

import com.canh.dto.UserDto;
import com.canh.services.ExampleServices;
/**
 * 
 * @author canh
 *
 */
@RestController
@RequestMapping("/example")
public class ExampleController {
	
	@Autowired
	private ExampleServices examplServices;
	
	@RequestMapping(value="/login" ,method = RequestMethod.POST, consumes=MediaType.APPLICATION_JSON_VALUE,produces=MediaType.ALL_VALUE)
	public ResponseEntity<String>login(@RequestBody UserDto user){
		String result = examplServices.test(user.getUserName(),user.getPassword());
		return new ResponseEntity<String>(result,HttpStatus.OK);
	}
	
	@RequestMapping(value="/nameForID" ,method = RequestMethod.GET,produces=MediaType.ALL_VALUE)
	public ResponseEntity<String>nameForID(@RequestParam(value = "userID") String userID) {
		String result = examplServices.getNameForID(userID);
		return new ResponseEntity<String>(result, HttpStatus.OK);
	}
	
}

@RequestMapping("/example"): định nghĩa url truy cập các API được tạo trong class này
@RestController: Với annotation này, nó sẽ thông báo cho Spring biết, class này dùng để nhận các request từ client lên.
@Autowired: tự động set method hoặc khởi tạo đối tượng.

Sau khi xong những bước trên các bạn có thể run file App.java để start server. Port mặc định là 8080, nhưng các bạn có thể thây đổi port bằng cách tạo file application.properties như cấu trúc bên trên và đổi port:

server.port=9090

Vậy là xong, các bạn build lại project có thể dùng lệnh

mvn package
hoặc
mvn clean install

Nhưng làm sao để test: Các bạn có thể add addon postman trên chrome để test, hoặc viết code unit test. Mình sẽ hướng dẫn viết unit test trong bài khác nếu anh em muốn :smile:
Đường dẫn test cho login API bên trên: http://localhost:9090/example/login.

Giờ mình muốn hướng các bạn đến vấn đề này: Khi tạo xong web API làm sao để người khác biết cách sử dụng? viết document, tất nhiên nhưng đừng nghĩ đến mở word hay code một trang html để tạo API document. Đó cũng là một cách nhưng hãy nghĩ để cách tốt nhất có thể. Tốt là cung cấp đủ thông tin cần thiết và nhanh chóng.
Ở bài này mình hướng dẫn dùng Swagger để tạo API document cho web Api vừa tạo xong.

Add thêm thư viện swagger vào pom.xml

<dependency>
		<groupId>io.springfox</groupId>
		<artifactId>springfox-swagger2</artifactId>
		<version>2.2.2</version>
</dependency>
<dependency>
	<groupId>io.springfox</groupId>
	<artifactId>springfox-swagger-ui</artifactId>
	<version>2.2.2</version>
</dependency>

sau đó implement file WebConfig.java như dưới:

package com.canh.config;

import org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration.WebMvcAutoConfigurationAdapter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;


import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration
@EnableWebMvc
@EnableSwagger2
public class WebConfig extends WebMvcAutoConfigurationAdapter {
	@Bean
	public Docket managementDocket(){
		return new Docket(DocumentationType.SWAGGER_2).groupName("my-project").apiInfo(apiInfo()).select().paths( PathSelectors.regex("/.*")).build();
	}

	private ApiInfo apiInfo(){
		return new ApiInfoBuilder().title("My-project").description("Document for API").termsOfServiceUrl("https://canh1412.wordpress.com/").contact("Canh").license("Proprietary").licenseUrl("https://canh1412.wordpress.com/").version("1.0").build();
	}

}

build lại project và start lại program, lúc này API document API sẽ được tự động generate và anh em có thể test API mình đã tạo trên đó: http://localhost:9090/swagger-ui.html# :

Chúc anh em cuối tuần vui vẻ :slight_smile:
github: https://github.com/nguyenhuuca/JavaSpringBootExample

12 Likes

Hướng dẫn rất hữu ích. Mong bạn có nhiều bài hơn

1 Like
83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?