1.架設MongoDB
使用docker compose把MongoDB環境建立起來,並將container放到對應的network(iwlp-network).以便其他的container調用
container使用HOST(宿主)時區
volumes:
- /etc/localtime:/etc/localtime:ro
docker-compose.yml
version : '3'
services:
mongodb:
image: 'mongo:3.2.21-jessie'
container_name: iwlp-mongodb
ports:
- "27017:27017"
environment:
MONGO_INITDB_ROOT_USERNAME: username
MONGO_INITDB_ROOT_PASSWORD: password
volumes:
- /etc/localtime:/etc/localtime:ro
- ./containers/mongodb/iwlp-mongodb:/data/db
networks:
- iwlp-network
networks:
iwlp-network:
driver: bridge
留意紅字的地方,換上自己的設定即可
2.建設MongoDB Web UI
有了MongoDB後,首要任務為需要一個簡單好用的GUI可以操作MongoDB
這裡使用Mongo-express,重要的設定參數為
ME_CONFIG_MONGODB_ADMINUSERNAME: mangodb的連線帳號
ME_CONFIG_MONGODB_ADMINPASSWORD: mangodb的連線密碼
ME_CONFIG_MONGODB_SERVER: mangodb的container名稱
depends_on: 設定container的相依容器,dockercompose會依據依賴順序啟動服務
因此修改一下原有的docker-compose.yml,並加入mongodb-ui
version : '3'
services:
mongodb:
image: 'mongo:3.2.21-jessie'
container_name: iwlp-mongodb
ports:
- "27017:27017"
environment:
MONGO_INITDB_ROOT_USERNAME: username
MONGO_INITDB_ROOT_PASSWORD: password
volumes:
- /etc/localtime:/etc/localtime:ro
- ./containers/mongodb/iwlp-mongodb:/data/db
networks:
- iwlp-network
mongodb-ui:
image: 'mongo-express:0.49'
container_name: iwlp-mongodb-ui
ports:
- "27081:8081"
environment:
ME_CONFIG_MONGODB_ADMINUSERNAME: username
ME_CONFIG_MONGODB_ADMINPASSWORD: password
ME_CONFIG_MONGODB_SERVER: iwlp-mongodb
depends_on:
- mongodb
volumes:
- /etc/localtime:/etc/localtime:ro
networks:
- iwlp-network
networks:
iwlp-network:
driver: bridge
version : '3'
services:
mongodb:
image: 'mongo:3.2.21-jessie'
container_name: iwlp-mongodb
ports:
- "27017:27017"
environment:
MONGO_INITDB_ROOT_USERNAME: username
MONGO_INITDB_ROOT_PASSWORD: password
volumes:
- /etc/localtime:/etc/localtime:ro
- ./containers/mongodb/iwlp-mongodb:/data/db
networks:
- iwlp-network
mongodb-ui:
image: 'mongo-express:0.49'
container_name: mongodb-ui
ports:
- "27081:8081"
environment:
ME_CONFIG_MONGODB_ADMINUSERNAME: username
ME_CONFIG_MONGODB_ADMINPASSWORD: password
ME_CONFIG_MONGODB_SERVER:iwlp-mongodb
depends_on:
- iwlp-mongodb
volumes:
- /etc/localtime:/etc/localtime:ro
networks:
-iwlp-network
networks:
iwlp-network:
driver: bridge
進入到專案的目錄{usweHome}/microservices/iwlp
執行docker compose指令,執行yml檔內所描述的微服務
sudo docker-compose up
透過以下連結進入管理頁面
http://{domainName}:27081/
{domainName}請換成你的docker IP或 domain name
3.建立Java專案
利用STS建立Java專案
預設目錄結構
org.iwlp.config
org.iwlp.model
org.iwlp.model.repository
org.iwlp.controller
org.iwlp.service
3.1 設定需要的library
build.gradle
buildscript {
ext {
springBootVersion = '2.1.1.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
group = 'org.iwlp'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
implementation('org.springframework.boot:spring-boot-starter-data-mongodb')
implementation('org.springframework.boot:spring-boot-starter-web')
testImplementation('org.springframework.boot:spring-boot-starter-test')
// lombok
annotationProcessor('org.projectlombok:lombok')
compileOnly('org.projectlombok:lombok')
testAnnotationProcessor('org.projectlombok:lombok')
testCompileOnly('org.projectlombok:lombok')
// gson
compile group: 'com.google.code.gson', name: 'gson', version: '2.8.5'
// commons-lang3
compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.7'
// swagger2
compile group: 'io.springfox', name: 'springfox-swagger2', version: '2.9.2'
compile group: 'io.springfox', name: 'springfox-swagger-ui', version: '2.9.2'
}
3.2 設定datasouce和專案相關配置
application.properties
#datasource
spring.data.mongodb.host=211.20.109.45
spring.data.mongodb.username=username
spring.data.mongodb.password=password
spring.data.mongodb.database=organization_DB
spring.data.mongodb.authentication-database=admin
#domain
server.port=8080
server.servlet.context-path=/iwlp-mongodb/
spring.application.name=iwlp-mongodb
spring.jmx.default-domain=iwlp-mongodb
endpoints.jmx.domain=iwlp-mongodb
endpoints.jmx.uniqueNames=true
3.3 設定Swagger配置
org.iwlp.config.Swagger2Config
package org.iwlp.config;
import java.util.Collections;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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
@EnableSwagger2
public class Swagger2Config {
private static final String SWAGGER2_TITLE = "我要努力偷學程式碼 - 角色權限管理管理 API 文件";
private static final String DESCRIPTION = "提供角色管理 OpenApi 文件";
private static final String CONTACT = "我要努力偷學程式碼";
private static final String EMAIL = "arder1986@gmail.com";
private static final String URL = "";
private static final String VERSION = "2.0";
@Bean
public Docket newsApi() {
return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select().apis(RequestHandlerSelectors.any()).paths(PathSelectors.any()).build();
}
private ApiInfo apiInfo() {
Contact contact = new Contact(CONTACT, URL, EMAIL);
return new ApiInfo(SWAGGER2_TITLE, DESCRIPTION, VERSION, "TERMS OF SERVICE URL", contact, "LICENSE", "LICENSE URL", Collections.emptyList());
}
}
3.4 設定cross domain
org.iwlp.config.WebConfig
package org.iwlp.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**").allowedHeaders("*").allowedMethods("*").allowedOrigins("*");
registry.addMapping("/v2/**").allowedHeaders("*").allowedMethods("*").allowedOrigins("*");
}
};
}
}
3.5 Document(entity)
建立Role(Document),利用lombok簡化程式碼,自動替類別加入getter/setter
org.iwlp.model.Role
package org.iwlp.model;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(description = "Role Class 表示角色完整資訊")
@Document(collection = "role")
public class Role {
@ApiModelProperty(notes = "系統使用的唯一識別碼", required = true, position = 0)
@Id
private String id;
@ApiModelProperty(notes = "角色名稱", required = true, position = 2)
private String name;
@ApiModelProperty(notes = "角色描述", required = false, position = 3)
private String description;
}
3.6 Repository
org.iwlp.model.repository.RoleRepository
package org.iwlp.model.repository;
import org.iwlp.model.Role;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.mongodb.repository.MongoRepository;
public interface RoleRepository extends MongoRepository<Role, String>{
public Page<Role> findByName(Pageable pageable, String name);
}
3.7 Service
建立Service
核心的操作都會在這類別內開發
org.iwlp.service.RoleService
package org.iwlp.service;
import org.iwlp.exception.NotFoundException;
import org.iwlp.model.Role;
import org.iwlp.model.repository.RoleRepository;
import org.iwlp.utils.PageableUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
@Service
public class RoleService {
private static final String ROLE_NOT_FOUND_EXCEPTION_MESSAGE = "role不存在";
@Autowired
private RoleRepository roleRepo;
public Role createRole(Role role) throws Exception {
role.setId(null);
return roleRepo.save(role);
}
public Role updateRole(String id, Role role) {
Role entity = getRole(id);
entity.setId(id);
entity.setName(role.getName());
return roleRepo.save(entity);
}
public Role getRole(String id) {
StringBuilder msgSb = new StringBuilder("doucment ").append(ROLE_NOT_FOUND_EXCEPTION_MESSAGE).append(", id:").append(id);
return roleRepo.findById(id).orElseThrow(() -> new NotFoundException(msgSb.toString()));
}
public void deleteRole(String id) {
Role entity = getRole(id);
roleRepo.delete(entity);
}
public Page<Role> searchRole(String name, Integer page, Integer size, Sort.Direction direction, String properties) {
Pageable pageable = PageableUtils.initPageable(page, size, direction, properties);
Page<Role> records = null;
if( StringUtils.isEmpty(name)) {
records = roleRepo.findAll(pageable);
} else {
records = roleRepo.findByName(pageable, name);
}
return records;
}
}
3.8 建立Controller
撰寫對外的REST API
org.iwlp.controller.Controller
package org.iwlp.controller;
import org.iwlp.model.Role;
import org.iwlp.service.RoleService;
import org.iwlp.utils.ThrowableUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Sort;
import org.springframework.web.bind.annotation.PathVariable;
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 io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
@Api(value = "/v2/", description = "角色管理", produces = "application/json")
@RestController
@RequestMapping(value = "/api")
public class RoleController {
@Autowired
private RoleService roleServer;
@RequestMapping(method=RequestMethod.POST,value="/role", headers="Content-Type=application/json")
@ApiOperation(value = "新增角色",notes="新增角色")
@ApiImplicitParams({
})
public Object createRole(
@RequestBody Role role
){
try {
return roleServer.createRole(role);
} catch (Exception e) {
return ThrowableUtils.getThrowableResponseEntityAndLog(e);
}
}
@RequestMapping(method=RequestMethod.PUT,value="/role/{id}", headers="Content-Type=application/json")
@ApiOperation(value = "修改角色",notes="修改角色")
@ApiImplicitParams({
@ApiImplicitParam(name = "id", value = "role id", required = true, defaultValue = "",dataType = "string", paramType = "path"),
})
public Role updateRole(
@PathVariable (name="id") String id,
@RequestBody Role role
){
return roleServer.updateRole(id, role);
}
@RequestMapping(method=RequestMethod.GET,value="/role/{id}")
@ApiOperation(value = "取得角色",notes="取得角色")
@ApiImplicitParams({
@ApiImplicitParam(name = "id", value = "role id", required = true, defaultValue = "",dataType = "string", paramType = "path"),
})
public Role getRole(
@PathVariable (name="id") String id
){
return roleServer.getRole(id);
}
@RequestMapping(method=RequestMethod.DELETE,value="/role/{id}")
@ApiOperation(value = "刪除角色",notes="刪除角色")
@ApiImplicitParams({
@ApiImplicitParam(name = "id", value = "role id", required = true,dataType = "string", paramType = "path"),
})
public Object deleteRole(
@PathVariable (name="id") String id
){
try {
roleServer.deleteRole(id);
return true;
} catch (Exception e) {
return ThrowableUtils.getThrowableResponseEntityAndLog(e);
}
}
@RequestMapping(method=RequestMethod.GET,value="/roles")
@ApiOperation(value = "分頁搜尋所有角色",notes="分頁搜尋所有角色")
@ApiImplicitParams({
@ApiImplicitParam(name = "page", value = "page", required = false, example = "1",dataType = "inteage", paramType = "query"),
@ApiImplicitParam(name = "size", value = "size", required = false, example = "10" ,dataType = "int", paramType = "query"),
@ApiImplicitParam(name = "direction", value = "direction", required = false, defaultValue = "ASC",dataType = "string", paramType = "query"),
@ApiImplicitParam(name = "properties", value = "column name", required = false, defaultValue = "id",dataType = "string", paramType = "query")
})
public Page<Role> search(
@RequestParam(value = "page", required = false) Integer page,
@RequestParam(value = "size", required = false) Integer size,
@RequestParam(value = "direction", required = false) Sort.Direction direction,
@RequestParam(value = "properties", required = false) String properties
){
return roleServer.searchRole(null, page, size, direction, properties);
}
}
3.9 Swagger-ui
專案運行後,訪問Swagger-ui
http://localhost:8080/iwlp-mongodb/swagger-ui.html
角色管理的所有REST API
執行新增角色
透過WEB UI檢驗結果
4.原始程式碼
iwlp-mongodb.zip
5.本文參考
[1] Dockerhub mongodb, from https://hub.docker.com/_/mongo/
[2] Dockerhub mongo-express, from https://hub.docker.com/_/mongo-express
[3] 30-2之使用Docker來建構MongoDB環境, from https://ithelp.ithome.com.tw/articles/10184657
[4] Mongo-express Github Project, from https://github.com/mongo-express/mongo-express
[5] 使用 lombok 簡化 Java 程式碼, from https://tw.saowen.com/a/34cc735ccb635faac4eb9d6fa2915eda9db0e8ba8f8d83e7161e0df650130eec?fbclid=IwAR3rl4ZF33r5MCixQuQ6tb5XogTyz2xGOTPCpwvFqAcnXN2sGXjdwSWybvM
https://www.evernote.com/l/AbE_xgynEyNNqoIn53j7reIZsW12rmxqmLM/
沒有留言:
張貼留言