1. Build the back-end environment of the project
1.1 construction of micro service module
1.1. 1 build parent project
Create a springboot project and add it to the pom file
<packaging>pom</packaging>
[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-eaa9vaxs-163938974390) (C: \ users \ 1234 \ appdata \ roaming \ typora \ user images \ image-20211209143903804. PNG)]
The parent project mainly puts some version dependencies and public dependencies
<properties> <java.version>1.8</java.version> <cloud.version>Hoxton.RELEASE</cloud.version> <alibaba.version>2.2.0.RELEASE</alibaba.version> <mybatis-plus.version>3.3.1</mybatis-plus.version> <mysql.version>5.1.46</mysql.version> <swagger.version>2.7.0</swagger.version> <jwt.version>0.7.0</jwt.version> <fastjson.version>1.2.29</fastjson.version> <httpclient.version>4.5.1</httpclient.version> <easyexcel.version>2.2.0-beta2</easyexcel.version> <aliyun.version>4.1.1</aliyun.version> <oss.version>3.9.1</oss.version> <jodatime.version>2.10.1</jodatime.version> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>${alibaba.version}</version> <type>pom</type> <scope>import</scope> </dependency> <!--mybatis-plus Persistent layer--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>${mybatis-plus.version}</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql.version}</version> </dependency> <!--swagger--> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>${swagger.version}</version> </dependency> <!--swagger ui--> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>${swagger.version}</version> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>${jwt.version}</version> </dependency> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>${httpclient.version}</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>${fastjson.version}</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>${easyexcel.version}</version> </dependency> <dependency> <groupId>com.aliyun</groupId> <artifactId>aliyun-java-sdk-core</artifactId> <version>${aliyun.version}</version> </dependency> <dependency> <groupId>com.aliyun.oss</groupId> <artifactId>aliyun-sdk-oss</artifactId> <version>${oss.version}</version> </dependency> <!--Date time tool--> <dependency> <groupId>joda-time</groupId> <artifactId>joda-time</artifactId> <version>${jodatime.version}</version> </dependency> <!-- springboot initialization --> <!-- <dependency>--> <!-- <groupId>org.springframework.boot</groupId>--> <!-- <artifactId>spring-boot-starter</artifactId>--> <!-- </dependency>--> <!-- <dependency>--> <!-- <groupId>org.projectlombok</groupId>--> <!-- <artifactId>lombok</artifactId>--> <!-- <optional>true</optional>--> <!-- </dependency>--> <!-- <dependency>--> <!-- <groupId>org.springframework.boot</groupId>--> <!-- <artifactId>spring-boot-starter-test</artifactId>--> <!-- <scope>test</scope>--> <!-- </dependency>--> </dependencies> </dependencyManagement>
1.1. 2. Build common parent project
Common: common module parent node
Common util: tool class module. All modules can depend on it
Service util: the toolkit of service service, which contains the public configuration class of service. All modules can depend on it
The directory structure is as follows
Common module adds dependencies in pom (add dependencies based on what is used in common_util and service_util)
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <scope>provided </scope> </dependency> <!--mybatis-plus--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <scope>provided </scope> </dependency> <!--lombok Used to simplify entity classes: need to install lombok plug-in unit--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <!--swagger--> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> </dependency> </dependencies>
1.1. 3. Build model project
It is mainly used to create entity classes
Add dependencies to pom
<dependencies> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <!--mybatis-plus--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <scope>provided </scope> </dependency> <!--swagger--> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <scope>provided </scope> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <scope>provided </scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-mongodb</artifactId> <scope>provided </scope> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <scope>provided </scope> </dependency> </dependencies>
1.1. 4. Build service module
Used to add various micro service modules
Add dependencies to pom
<packaging>pom</packaging> <dependencies> <dependency> <groupId>com.tjj</groupId> <artifactId>service_util</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> <dependency> <groupId>com.tjj</groupId> <artifactId>model</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> <!--web--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--mybatis-plus--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> </dependency> <!--mysql--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <!--Developer Tools--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency> <!-- Service call feign --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <!-- Service registration --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <!-- flow control --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> <resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.yml</include> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>false</filtering> </resource> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.yml</include> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>false</filtering> </resource> </resources> </build>
1.1. 5 delete redundant folders
guahao_ There is no need to write code in the parent and common modules. Delete the src folder inside
The service module adds sub service modules, so the src folder can also be deleted. To sum up, the deleted file directory structure is as follows
[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-ssmose5w-163938974392) (C: \ users \ 1234 \ appdata \ roaming \ typora user images \ image-20211209154502344. PNG)]
1.2 submit code to git warehouse
To facilitate management, submit the code to the git repository, create a repository in gitee, and copy the address
Create a local repository in the IDEA, and select the parent project level directory from VCs - > create git repository
Then add git - > Add
Then select git - > Manage remotes
Then add the address of the remote warehouse
1.3 requirements
1.3. 1 CRUD of hospital setting table data
Create database, interface, etc. according to requirements
1 add maven sub module to service module – > Service_ Hosp module
2. For the dependencies in the pom of the service Hosp module, add the sub modules first
3. The service Hosp module creates the startup class of the sub module
@SpringBootApplication @ComponentScan(basePackages = "com.tjj") @EnableDiscoveryClient @EnableFeignClients(basePackages = "com.tjj") public class ServiceHospApplication { public static void main(String[] args) { SpringApplication.run(ServiceHospApplication.class, args); } }
4. The model module imports the entity class of the corresponding database table, such as
package com.tjj.model.hosp; @Data @ApiModel(description = "Hospital settings") @TableName("hospital_set") public class HospitalSet extends BaseEntity { private static final long serialVersionUID = 1L; @ApiModelProperty(value = "Hospital name") @TableField("hosname") private String hosname; @ApiModelProperty(value = "Hospital number") @TableField("hoscode") private String hoscode; @ApiModelProperty(value = "api Base path") @TableField("api_url") private String apiUrl; @ApiModelProperty(value = "Signature key") @TableField("sign_key") private String signKey; @ApiModelProperty(value = "Contact name") @TableField("contacts_name") private String contactsName; @ApiModelProperty(value = "Cell Phone ") @TableField("contacts_phone") private String contactsPhone; @ApiModelProperty(value = "state") @TableField("status") private Integer status; }
5. Add Mapper file in service Hosp module
Create the HospitalSetMapper interface in the mapper folder and inherit BaseMapper
package com.tjj.mapper; @Mapper public interface HospitalSetMapper extends BaseMapper<HospitalSet> { }
Add HospitalSetMapper.xml to mapper/xml xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.tjj.hosp.mapper.HospitalSetMapper"> </mapper>
MP encapsulates BaseMapper for us in mapper, and we can use it by direct inheritance.
MP encapsulates IService and ServiceImpl for us in service, and we can use them directly
In the service folder
package com.tjj.service; public interface HospitalSetService extends IService<HospitalSet> { }
package com.tjj.service.impl; @Service public class HospitalSetServiceImpl extends ServiceImpl<HospitalSetMapper, HospitalSet> implements HospitalSetService { }
Mapper is ultimately called in the service. We need to inject mapper into the service for later use However, the ServiceImpl we inherited has been injected for us, so we don't need to inject mapper ourselves. We can call it directly using baseMapper in the future.
6 add controller file
6.1. Adding RestController integrates @ Controller and @ RequestBody, where @ Controller indicates that this class is managed by Spring, and @ RequestBody is the returned data
6.2. Add @ RequestMapping, that is, the access path
6.3. Inject Service into Controller
package com.tjj.controller; @RestController @RequestMapping("/admin/hosp/hospitalSet") public class HospitalSetController { @Autowired private HospitalSetService hospitalSetService; }
4. Add business and query all the information in the hospital setting table
When a list is returned, the @ RequestBody in @ RestController will convert the list into json and return
package com.tjj.controller; @RestController @RequestMapping("/admin/hosp/hospitalSet") public class HospitalSetController { @Autowired private HospitalSetService hospitalSetService; //1. Query all information in the hospital setting table @GetMapping("findAll") public Result findAllHospitalSet() { //Method of calling service List<HospitalSet> list = hospitalSetService.list(); return list; } //2. Delete hospital settings logically @DeleteMapping("{id}") public Result removeHospSet(@PathVariable Long id) { boolean flag = hospitalSetService.removeById(id); return flag; }
1.3.7 mapper is an interface. The interface implementation class of mapper is created dynamically, so you need to add an @ MapperScan annotation on the startup class; However, a config class is created here, and @ MapperScan is added to the config class. The effect is the same, so it is convenient to manage mapper
package com.tjj.config; @Configuration @MapperScan("com.tjj.hosp.mapper") public class HospConfig { }
1.3. 2. Swwager API interface document introduction
In order to facilitate debugging, Swwager2 is introduced to facilitate the testing of various submission methods. You can see the interface name, request method, request parameters, return information, etc.
1. Add dependency
Considering that other modules will also be used, swwager dependency is added to the common module, and other micro service modules can also be used
<dependency><!--add to Swagger rely on --> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.7.0</version> </dependency> <dependency><!--add to Swagger-UI rely on --> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.7.0</version> </dependency>
2. Add swwager configuration
2.1 create the config folder in the service util module, write the configuration class, and configure the configuration content of swagger. The configuration content is generally unchanged (routine, stereotype), and can be copied and pasted directly.
package com.tjj.common.config; @Configuration @EnableSwagger2 public class Swagger2Config { @Bean public Docket webApiConfig(){ return new Docket(DocumentationType.SWAGGER_2) .groupName("webApi") .apiInfo(webApiInfo()) .select() //Only the pages under the api path are displayed .paths(Predicates.and(PathSelectors.regex("/api/.*"))) .build(); } @Bean public Docket adminApiConfig(){ return new Docket(DocumentationType.SWAGGER_2) .groupName("adminApi") .apiInfo(adminApiInfo()) .select() //Only the pages under the admin path are displayed .paths(Predicates.and(PathSelectors.regex("/admin/.*"))) .build(); } private ApiInfo webApiInfo(){ return new ApiInfoBuilder() .title("website-API file") .description("This document describes the website microservice interface definition") .version("1.0") .contact(new Contact("c8a", "https://gitee.com/cao_jianhua/yygh-parent", "1912327276@qq.com")) .build(); } private ApiInfo adminApiInfo(){ return new ApiInfoBuilder() .title("Background management system-API file") .description("This document describes the microservice interface definition of the background management system") .version("1.0") .contact(new Contact("c8a", "https://gitee.com/cao_jianhua/yygh-parent", "1912327276@qq.com")) .build(); } }
2.2 set the scanning rules on the startup class of the service Hosp module, @ ComponentScan(basePackages = "com. TJJ"), so that although the package structure of the configuration file is different (service util is com.tjj.common and service Hosp is com. TJJ), the configuration in service util can still be used.
@SpringBootApplication @ComponentScan(basePackages = "com.tjj") public class ServiceHospApplication { public static void main(String[] args) { SpringApplication.run(ServiceHospApplication.class, args); } }
2.3 access; Swager UI interface for interface testing
http://server:port/swagger-ui.html where server is the server address and port is the port number of the server.
Here, the server address is local and the port number is 8201, i.e http://localhost:8201/swagger-ui.html
2.4 add Chinese annotation of swagger (not required)
@Api(tags = "Hospital setting management") @RestController @RequestMapping("/admin/hosp/hospitalSet") public class HospitalSetController { @Autowired private HospitalSetService hospitalSetService; //1. Query all information in the hospital setting table @ApiOperation(value = "Get all hospitals") @GetMapping("findAll") public Result findAllHospitalSet() { //Method of calling service List<HospitalSet> list = hospitalSetService.list(); return list; } //2. Delete hospital settings logically @ApiOperation(value = "Delete hospital logically") @DeleteMapping("{id}") public Result removeHospSet(@PathVariable Long id) { boolean flag = hospitalSetService.removeById(id); return flag; } }
1.3. 3 unified return type
In actual development, it cannot be developed by one person. Everyone has different return habits (some people like to use true to indicate return success, others like to use 1 to indicate return success). Therefore, all return data have the same return format, which reduces the burden for front-end analysis and display.
1. Add com. In the common util module tjj. common. Result package, and then add a unified return type class
package com.tjj.common.result; @Data @ApiModel(value = "Global unified return results") public class Result<T> { @ApiModelProperty(value = "Return code") private Integer code; @ApiModelProperty(value = "Return message") private String message; @ApiModelProperty(value = "Return data") private T data; public Result(){} protected static <T> Result<T> build(T data) { Result<T> result = new Result<T>(); if (data != null) result.setData(data); return result; } public static <T> Result<T> build(T body, ResultCodeEnum resultCodeEnum) { Result<T> result = build(body); result.setCode(resultCodeEnum.getCode()); result.setMessage(resultCodeEnum.getMessage()); return result; } public static <T> Result<T> build(Integer code, String message) { Result<T> result = build(null); result.setCode(code); result.setMessage(message); return result; } public static<T> Result<T> ok(){ return Result.ok(null); } /** * Operation succeeded * @param data * @param <T> * @return */ public static<T> Result<T> ok(T data){ Result<T> result = build(data); return build(data, ResultCodeEnum.SUCCESS); } public static<T> Result<T> fail(){ return Result.fail(null); } /** * operation failed * @param data * @param <T> * @return */ public static<T> Result<T> fail(T data){ Result<T> result = build(data); return build(data, ResultCodeEnum.FAIL); } public Result<T> message(String msg){ this.setMessage(msg); return this; } public Result<T> code(Integer code){ this.setCode(code); return this; } public boolean isOk() { if(this.getCode().intValue() == ResultCodeEnum.SUCCESS.getCode().intValue()) { return true; } return false; } }
package com.tjj.common.result; @Getter public enum ResultCodeEnum { SUCCESS(200,"success"), FAIL(201, "fail"), PARAM_ERROR( 202, "parameter is incorrect"), SERVICE_ERROR(203, "Service exception"), DATA_ERROR(204, "Data exception"), DATA_UPDATE_ERROR(205, "Data version exception"), LOGIN_AUTH(208, "Not logged in"), PERMISSION(209, "No permission"), CODE_ERROR(210, "Verification code error"), // LOGIN_MOBLE_ERROR(211, "incorrect account number"), LOGIN_DISABLED_ERROR(212, "Change user has been disabled"), REGISTER_MOBLE_ERROR(213, "The phone number is already in use"), LOGIN_AURH(214, "Login required"), LOGIN_ACL(215, "No permission"), URL_ENCODE_ERROR( 216, "URL Encoding failed"), ILLEGAL_CALLBACK_REQUEST_ERROR( 217, "Illegal callback request"), FETCH_ACCESSTOKEN_FAILD( 218, "obtain accessToken fail"), FETCH_USERINFO_ERROR( 219, "Failed to get user information"), //LOGIN_ Error (23005, "login failed"), PAY_RUN(220, "In payment"), CANCEL_ORDER_FAIL(225, "Order cancellation failed"), CANCEL_ORDER_NO(225, "Cannot cancel appointment"), HOSCODE_EXIST(230, "Hospital number already exists"), NUMBER_NO(240, "Insufficient reservation number"), TIME_NO(250, "You can't make an appointment at the current time"), SIGN_ERROR(300, "Signature error"), HOSPITAL_OPEN(310, "The hospital has not been opened and cannot be accessed temporarily"), HOSPITAL_LOCK(320, "The hospital is locked and temporarily inaccessible"), ; private Integer code; private String message; private ResultCodeEnum(Integer code, String message) { this.code = code; this.message = message; } }
The method in the result class is static, and the class name can be used directly Method name to call. All future return types return a result object. such as
@Api(tags = "Hospital setting management") @RestController @RequestMapping("/admin/hosp/hospitalSet") public class HospitalSetController { @Autowired private HospitalSetService hospitalSetService; //1. Query all information in the hospital setting table @ApiOperation(value = "Get all hospitals") @GetMapping("findAll") public Result findAllHospitalSet() { //Method of calling service List<HospitalSet> list = hospitalSetService.list(); return Result.ok(list); } //2. Delete hospital settings logically @ApiOperation(value = "Delete hospital logically") @DeleteMapping("{id}") public Result removeHospSet(@PathVariable Long id) { boolean flag = hospitalSetService.removeById(id); if (flag) { return Result.ok(); } else { return Result.fail(); } } }
1.3. 4 condition query
1. Create vo class (value object) to encapsulate condition values
Create a conditional query object in the model module (the model module is specially used to store entity classes)
package com.tjj.vo.hosp; @Data public class HospitalSetQueryVo { @ApiModelProperty(value = "Hospital name") private String hosname; @ApiModelProperty(value = "Hospital number") private String hoscode; }
2. Write controller to obtain condition object and paging data (current page and number of records per page)
Only a post request can have @ RequestBody '= = =', which is encapsulated into a json string
//3 conditional query with paging @ApiOperation(value = "Conditional query hospital with paging") @PostMapping("findPageHospSet/{current}/{limit}") public Result findPageHospSet(@PathVariable long current, @PathVariable long limit, @RequestBody(required = false) HospitalSetQueryVo hospitalSetQueryVo) { //Create a page object to transfer the current page and the number of records per page Page<HospitalSet> page = new Page<>(current, limit); //Construction conditions QueryWrapper<HospitalSet> wrapper = new QueryWrapper<>(); String hosname = hospitalSetQueryVo.getHosname();//Hospital name String hoscode = hospitalSetQueryVo.getHoscode();//Hospital number if (!StringUtils.isEmpty(hosname)) { wrapper.like("hosname", hospitalSetQueryVo.getHosname()); } if (!StringUtils.isEmpty(hoscode)) { wrapper.eq("hoscode", hospitalSetQueryVo.getHoscode()); } //Call method to realize paging query Page<HospitalSet> pageHospitalSet = hospitalSetService.page(page, wrapper); //Return results return Result.ok(pageHospitalSet); }
-
Add hospital settings, MD encryption
3.1 add com. In the service util module tjj. common. Utils, add MD5 class
package com.tjj.common.utils; public final class MD5 { public static String encrypt(String strSrc) { try { char hexChars[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; byte[] bytes = strSrc.getBytes(); MessageDigest md = MessageDigest.getInstance("MD5"); md.update(bytes); bytes = md.digest(); int j = bytes.length; char[] chars = new char[j * 2]; int k = 0; for (int i = 0; i < bytes.length; i++) { byte b = bytes[i]; chars[k++] = hexChars[b >>> 4 & 0xf]; chars[k++] = hexChars[b & 0xf]; } return new String(chars); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); throw new RuntimeException("MD5 Encryption error!!+" + e); } } }
3.2 encryption: the current time + a random value is currently generated, and then MD5 encryption is performed. Note that the logical value is completely modified. If it is associated with other businesses, an error will occur. When adding, all situations should be taken into account as much as possible, and those values need to be modified (CRUD are the same, and consider it completely as much as possible).
//4 add hospital settings @ApiOperation(value = "Add hospital") @PostMapping("saveHospitalSet") public Result saveHospitalSet(@RequestBody HospitalSet hospitalSet) { //Setting state 1 0 cannot be used hospitalSet.setStatus(1); //Signature key Random random = new Random(); hospitalSet.setSignKey(MD5.encrypt(System.currentTimeMillis()+""+random.nextInt(1000))); //Logical deletion hospitalSet.setIsDeleted(0);ยท //Call service boolean save = hospitalSetService.save(hospitalSet); if(save) { return Result.ok(); } else { return Result.fail(); } }