SAAS-HRM system overview and construction environment

SAAS-HRM system overview and construction environment

learning target:

Understand the basic concepts of SaaS

Understand the basic requirements and development methods of SAAS-HRM Master the use case diagram of Power Designer

Complete the environment construction of SAAS-HRM parent module and public module Complete the enterprise CRUD function in enterprise microservices

Getting to know SaaS for the first time

Three models of cloud services

IaaS (Infrastructure as a Service)

IaaS (Infrastructure as a Service) , that is, infrastructure as a service. The service provided to consumers is the utilization of all computing infrastructure, including processing CPU, memory, storage, network and other basic computing resources, and users can deploy and run arbitrary software, including operating systems and applications. The consumer does not manage or control any cloud computing infrastructure, but has control over the choice of operating system, storage space, deployed applications, and possibly limited control of network components (such as routers, firewalls, load balancers, etc.)

PaaS (Platform as a Service)

PaaS (Platform-as-a-Service) , that is, platform as a service. The service provided to consumers is to deploy the applications developed or acquired by customers using the provided development languages ​​and tools (such as Java, python, .Net, etc.) to the provider's cloud computing infrastructure. Customers do not need to manage or control the underlying cloud infrastructure, including networks, servers, operating systems, storage, etc., but customers can control the deployed applications and possibly the configuration of the hosting environment where the applications run

SaaS (Software as a Service)

SaaS (Software-as-a-Service), that is, software as a service. To provide consumers with complete software solutions, you can obtain software applications from software service providers by renting or purchasing, and organizational users can connect to the application through the Internet (usually using a Web browser). All infrastructure, middleware, application software, and application data reside in the service provider's data center. The service provider manages the hardware and software, and ensures the availability and security of applications and data under appropriate service agreements. SaaS enables organizations to get applications up and running quickly with minimal upfront cost.

difference and connection

Sao Dai’s understanding: You can better understand these three concepts through the following picture. IAAS is to provide you with hardware resources such as servers on cloud services. You don’t need to buy servers, just rent IAAS. PAAS is to provide you with hardware resources , also provides software resources (running environment), you only need to deploy the source code of the project, and SAAS is a project that someone else has done, you can buy it directly and use it, you don’t need to develop it, just pay for it!

Overview of SaaS

Detailed explanation of Saas

SaaS (Software-as-a-service) means software as a service. Simply put, it is the online system model, that is, the software online service provided by the software service provider.

Application field and industry prospect

In terms of applicable objects, SaaS software can be divided into individual-oriented and enterprise-oriented SaaS products: online documents, account management, file management, schedule planning, photo management, contact management, and other cloud-type services

Enterprise-oriented SaaS products mainly include: CRM (customer relationship management), ERP (enterprise resource planning management), online video or group conference calls, HRM (human resource management), OA (office system), field management, Financial management, approval management, etc.

Comparison of Saas and traditional software

  • Reduce enterprise costs: buy on demand, rent and use immediately, no need to pay attention to software development and maintenance.
  • Rapid software update iteration: Compared with traditional software, because SaaS is deployed in the cloud, the software update iteration speed is accelerated
  • Supports remote work: Once data is stored in the cloud, users can access their information from any Internet-connected computer or mobile device

SaaS-HRM Requirements Analysis

What is SaaS-HRM

SaaS-HRM is a human resource management system based on the saas model. It is different from traditional human resources software applications. Users only need to open a browser to manage the salary, performance, social security, entry and exit of hundreds of people.

prototype analysis

The idea of ​​prototype analysis is to quickly construct an initial system prototype that can reflect user needs after obtaining a set of basic requirements. Let users see an overview of the future system in order to judge which functions meet the requirements and which aspects need to be improved, and then continue to further supplement, refine and modify these requirements. And so on, iteratively, until the user is satisfied and thus develop a complete system.

Simply put, the prototype analysis method is to obtain the most real needs of users in the shortest time and in the most intuitive way

UML use case diagram

UML Unified Modeling Language

Unified Modeling Language (UML) , also known as unified modeling language or standard modeling language, is an OMG standard that started in 1997. It is a graphical language that supports modeling and software system development, providing models for all stages of software development Visualization and visualization support, from requirements analysis to specification, to construction and configuration. The development of object-oriented analysis and design (OOA&D, OOAD) method appeared a climax from the late 1980s to the mid-1990s, and UML is the product of this climax. It not only unifies the representation methods of Booch, Rumbaugh and Jacobson, but also further develops them, and finally unifies them into a standard modeling language accepted by the public. UML contains many graphics (use case diagrams, class diagrams, state diagrams, etc.), among which use case diagrams are the graphics that best reflect the system structure

use case diagram

Use case diagram (use case) is mainly used to describe the relationship between users and use cases. Describes who will use the system and what they can do with it. A use case diagram contains multiple model elements, such as system, actor, and use case, and shows various relationships among these elements, such as generalization, association, and dependency. It presents a model diagram of system functionality that can be observed by external users.

Requirements Analysis Software

Power Designer is the CASE tool set of Sybase Corporation, which can be used to analyze and design the management information system conveniently, and it almost includes the whole process of database model design. Using Power Designer, you can make data flow diagrams, conceptual data models, physical data models, and also make structural models for data warehouses, as well as control team design models.

  • Download and install

Use the installation package prepared in the first day of information to install Power Designer, the installation process is slightly

  • Use Power Designer to draw a use case diagram drawing steps:

File => Create New Model => Select Modeltypes => Use Case

Basic use case diagram:

system design

development method

The SaaS-IHRM system adopts the development method of front-end and back-end separation.

The back end provides data to the front end, and the front end is responsible for HTML rendering (which can be rendered on the server or in the browser) and user interaction. Both parties standardize the content of the interface in the form of documents

Technology Architecture

  • Front-end technology stack

Vue.js front-end technology ecological architecture with Node.js as the core

  • Backend technology stack

SpringBoot+SpringCloud+SpringMVC+SpringData (Spring family bucket)

system structure

API documentation

The course provides front-end and back-end development interface documents (written in Swagger language), and integrates with Ngin. After double-clicking the Nginx execution file to start, enter http://localhost:801 in the address bar to access the API documentation

Sao Dai Tip: If Api-ngnix is ​​started here, but cannot be accessed, you need to put this folder in a folder without Chinese before you can access it, and then you can jump to the following page, then I open the task manager, kill Shut down Nginx, then restart, still the following page, then I put the compressed package back into a folder without Chinese, and then restart it after decompression, I guess it should be to put the compressed package in a folder without Chinese In the folder, I copied the folder at first!

engineering construction

Explanation of pre-knowledge points

The backend of the Saas-HRM system uses SpringBoot+SpringCloud+SpringMVC+SpringData. The frontend of the Saas-HRM system uses the vue framework based on nodejs to complete the writing. Use the element-ui component library to quickly develop the front-end interface.

Development environment requirements

  • JDK1.8
  • database mysql 5.7
  • Development tool idea 2017.1.2 maven version 3.3.9

lombok plugin

lombok is an auxiliary tool that can reduce java code and improve developer productivity. It uses annotations to automatically generate code such as setter/getter/toString()/constructor during compilation

  • Install plug-ins in idea
  • Add plugin dependencies to the pom file
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.16.16</version>
</dependency>
  • Common Notes

The @Data annotation is on the class; it provides getting and setting methods for all properties of the class, and also provides equals, canEqual,

hashCode, toString methods

@Setter : Annotated on the property; provide a setting method for the property

@Setter: Annotate on the attribute; provide a getting method for the attribute @NoArgsConstructor: Annotate on the class; provide a parameterless constructor for the class @AllArgsConstructor: Annotate on the class; provide a full parameter constructor for the class

build parent project

Create the parent project ihrm_parent in IDEA and import the corresponding coordinates as follows:

    <packaging>pom</packaging>
    <name>ihrm_parent</name>
    <description>IHRM-黑马程序员</description>
    
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.5.RELEASE</version>
        <relativePath/>
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <fastjson.version>1.2.47</fastjson.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-logging</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>${fastjson.version}</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.16</version>
        </dependency>
    </dependencies>

    <repositories>
        <repository>
            <id>spring-snapshots</id>
            <name>Spring Snapshots</name>
            <url>https://repo.spring.io/snapshot</url>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </repository>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>

    <pluginRepositories>
        <pluginRepository>
            <id>spring-snapshots</id>
            <name>Spring Snapshots</name>
            <url>https://repo.spring.io/snapshot</url>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </pluginRepository>
        <pluginRepository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </pluginRepository>
    </pluginRepositories>
    <build>
        <plugins>
            <!--编译插件-->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                </configuration>
            </plugin>

            <!--单元测试插件-->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.12.4</version>
                <configuration>
                    <skipTests>true</skipTests>
                </configuration>
            </plugin>
        </plugins>
    </build>

Build common submodules

Build the common submodule ihrm-common

Create a return result entity class

Create a new com.ihrm.common.entity package, create a class Result under the package, and use it to return results from the controller class

package com.ihrm.common.entity;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;


@Data
@NoArgsConstructor
public class Result {

    private boolean success;//是否成功
    private Integer code;// 返回码
    private String message;//返回信息
    private Object data;// 返回数据

    public Result(ResultCode code) {
        this.success = code.success;
        this.code = code.code;
        this.message = code.message;
    }

    public Result(ResultCode code,Object data) {
        this.success = code.success;
        this.code = code.code;
        this.message = code.message;
        this.data = data;
    }

    public Result(Integer code,String message,boolean success) {
        this.code = code;
        this.message = message;
        this.success = success;
    }

    public static Result SUCCESS(){
        return new Result(ResultCode.SUCCESS);
    }

    public static Result ERROR(){
        return new Result(ResultCode.SERVER_ERROR);
    }

    public static Result FAIL(){
        return new Result(ResultCode.FAIL);
    }
}

Create a class PageResult for returning paging results

package com.ihrm.common.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.List;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class PageResult<T> {
    private Long total; //总条数
    private List<T> rows;
}

return code definition class

package com.ihrm.common.entity;

public enum ResultCode {

    SUCCESS(true,10000,"操作成功!"),
    //---系统错误返回码-----
    FAIL(false,10001,"操作失败"),
    UNAUTHENTICATED(false,10002,"您还未登录"),
    UNAUTHORISE(false,10003,"权限不足"),
    SERVER_ERROR(false,99999,"抱歉,系统繁忙,请稍后重试!");

    //---用户操作返回码----
    //---企业操作返回码----
    //---权限操作返回码----
    //---其他操作返回码----

    //操作是否成功
    boolean success;
    //操作代码
    int code;
    //提示信息
    String message;

    ResultCode(boolean success,int code, String message){
        this.success = success;
        this.code = code;
        this.message = message;
    }

    public boolean success() {
        return success;
    }

    public int code() {
        return code;
    }

    public String message() {
        return message;
    }

}

Distributed ID Generator

At present, the microservice architecture is prevalent, and there will be some global ID requirements in the operation of the distributed system, so we cannot use the self-increment function of the database itself to generate the primary key value, and only the program can generate the unique primary key value . We use the open source twitter (unofficial Chinese customary name: twitter. It is a foreign website, a social network and microblogging service) snowFlake (雪花) algorithm.

Analysis of each segment:

section

effect

illustrate

1bit

reserved (not used)

---

41bit

Timestamp, accurate to milliseconds

Can support a span of up to 69 years

5bit

machine id

Supports up to 2 to the 5th power (32) nodes

5bit

business code

Supports up to 2 to the 5th power (32) nodes

12bit

counter in milliseconds

Each node generates up to 212 (4096) ids per millisecond

By default, the 41-bit timestamp can support the algorithm to be used until 2082, the 10-bit working machine ID can support 1024 machines, and the serial number supports 1 millisecond to generate 4096 self-incrementing sequence IDs. The advantage of SnowFlake is that it is self-increasing according to time as a whole Sorting, and ID collisions will not occur in the entire distributed system (distinguished by data center IDs and machine IDs), and the efficiency is high. After testing, SnowFlake can generate about 260,000 IDs per second

Sao Dai’s understanding: There are four ways of thinking. Database self-increment cannot be guaranteed to be unique in a distributed environment. Uuid is too long and takes up space and memory. Global redis has network delays. Snowflake algorithm is dedicated to id generation in distributed systems

Snowflake Algorithm Code Implementation

package com.ihrm.common.utils;

import java.lang.management.ManagementFactory;
import java.net.InetAddress;
import java.net.NetworkInterface;

//雪花算法代码实现
public class IdWorker {
    // 时间起始标记点,作为基准,一般取系统的最近时间(一旦确定不能变动)
    private final static long twepoch = 1288834974657L;
    // 机器标识位数
    private final static long workerIdBits = 5L;
    // 数据中心标识位数
    private final static long datacenterIdBits = 5L;
    // 机器ID最大值
    private final static long maxWorkerId = -1L ^ (-1L << workerIdBits);
    // 数据中心ID最大值
    private final static long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
    // 毫秒内自增位
    private final static long sequenceBits = 12L;
    // 机器ID偏左移12位
    private final static long workerIdShift = sequenceBits;
    // 数据中心ID左移17位
    private final static long datacenterIdShift = sequenceBits + workerIdBits;
    // 时间毫秒左移22位
    private final static long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;

    private final static long sequenceMask = -1L ^ (-1L << sequenceBits);
    /* 上次生产id时间戳 */
    private static long lastTimestamp = -1L;
    // 0,并发控制
    private long sequence = 0L;

    private final long workerId;
    // 数据标识id部分
    private final long datacenterId;

    public IdWorker(){
        this.datacenterId = getDatacenterId(maxDatacenterId);
        this.workerId = getMaxWorkerId(datacenterId, maxWorkerId);
    }
    /**
     * @param workerId
     *            工作机器ID
     * @param datacenterId
     *            序列号
     */
    public IdWorker(long workerId, long datacenterId) {
        if (workerId > maxWorkerId || workerId < 0) {
            throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
        }
        if (datacenterId > maxDatacenterId || datacenterId < 0) {
            throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
        }
        this.workerId = workerId;
        this.datacenterId = datacenterId;
    }
    /**
     * 获取下一个ID
     *
     * @return
     */
    public synchronized long nextId() {
        long timestamp = timeGen();
        if (timestamp < lastTimestamp) {
            throw new RuntimeException(String.format("Clock moved backwards.  Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
        }

        if (lastTimestamp == timestamp) {
            // 当前毫秒内,则+1
            sequence = (sequence + 1) & sequenceMask;
            if (sequence == 0) {
                // 当前毫秒内计数满了,则等待下一秒
                timestamp = tilNextMillis(lastTimestamp);
            }
        } else {
            sequence = 0L;
        }
        lastTimestamp = timestamp;
        // ID偏移组合生成最终的ID,并返回ID
        long nextId = ((timestamp - twepoch) << timestampLeftShift)
                | (datacenterId << datacenterIdShift)
                | (workerId << workerIdShift) | sequence;

        return nextId;
    }

    private long tilNextMillis(final long lastTimestamp) {
        long timestamp = this.timeGen();
        while (timestamp <= lastTimestamp) {
            timestamp = this.timeGen();
        }
        return timestamp;
    }

    private long timeGen() {
        return System.currentTimeMillis();
    }

    /**
     * <p>
     * 获取 maxWorkerId
     * </p>
     */
    protected static long getMaxWorkerId(long datacenterId, long maxWorkerId) {
        StringBuffer mpid = new StringBuffer();
        mpid.append(datacenterId);
        String name = ManagementFactory.getRuntimeMXBean().getName();
        if (!name.isEmpty()) {
            /*
             * GET jvmPid
             */
            mpid.append(name.split("@")[0]);
        }
        /*
         * MAC + PID 的 hashcode 获取16个低位
         */
        return (mpid.toString().hashCode() & 0xffff) % (maxWorkerId + 1);
    }

    /**
     * <p>
     * 数据标识id部分
     * </p>
     */
    protected static long getDatacenterId(long maxDatacenterId) {
        long id = 0L;
        try {
            InetAddress ip = InetAddress.getLocalHost();
            NetworkInterface network = NetworkInterface.getByInetAddress(ip);
            if (network == null) {
                id = 1L;
            } else {
                byte[] mac = network.getHardwareAddress();
                id = ((0x000000FF & (long) mac[mac.length - 1])
                        | (0x0000FF00 & (((long) mac[mac.length - 2]) << 8))) >> 6;
                id = id % (maxDatacenterId + 1);
            }
        } catch (Exception e) {
            System.out.println(" getDatacenterId: " + e.getMessage());
        }
        return id;
    }
}

Build public entity class modules

Build the common submodule ihrm_common_model

import coordinates

   <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>com.ihrm</groupId>
            <artifactId>ihrm_common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>

Add entity class

package com.ihrm.domain.company;


import lombok.*;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import java.io.Serializable;
import java.util.Date;

/**
 * 实体类代码:
 *  属性
 *  构造方法
 *  getter,setter方法
 *
 * lombok 插件 : 使用注解的形式替换getter setter,构造方法
 *      如何使用插件
 *          1.安装插件(在工程中引入响应的插件坐标即可)
 *                  <dependency>
 <groupId>org.projectlombok</groupId>
 <artifactId>lombok</artifactId>
 <version>1.16.16</version>
 </dependency>
 *          2.使用注解配置
 *                 配置到实体类上
 *                 @setter      : setter方法
 *                 @getter      :getter方法
 *                 @NoArgsConstructor   无参构造
 *                 @AllArgsConstructor  满参构造
 *                 @Data        : setter,getter,构造方法
 *
 * 使用jpa操作数据
 *      配置实体类和数据库表的映射关系:jpa注解
 *      1.实体类和表的映射关系
 *      2.字段和属性的映射关系
 *          i。主键属性的映射
 *          ii。普通属性的映射
 */
@Entity
@Table(name = "co_company")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Company implements Serializable {
    private static final long serialVersionUID = 594829320797158219L;
    //ID
    @Id
    private String id;
    /**
     * 公司名称
     */
    private String name;
    /**
     * 企业登录账号ID
     */
    private String managerId;
    /**
     * 当前版本
     */
    private String version;
    /**
     * 续期时间
     */
    private Date renewalDate;
    /**
     * 到期时间
     */
    private Date expirationDate;
    /**
     * 公司地区
     */
    private String companyArea;
    /**
     * 公司地址
     */
    private String companyAddress;
    /**
     * 营业执照-图片ID
     */
    private String businessLicenseId;
    /**
     * 法人代表
     */
    private String legalRepresentative;
    /**
     * 公司电话
     */
    private String companyPhone;
    /**
     * 邮箱
     */
    private String mailbox;
    /**
     * 公司规模
     */
    private String companySize;
    /**
     * 所属行业
     */
    private String industry;
    /**
     * 备注
     */
    private String remarks;
    /**
     * 审核状态
     */
    private String auditState;
    /**
     * 状态
     */
    private Integer state;
    /**
     * 当前余额
     */
    private Double balance;
    /**
     * 创建时间
     */
    private Date createTime;
}

Sao Dai understands:

@Entity and @Data are two different annotations from different libraries.

  • @Entity: This annotation comes from the Java Persistence API (JPA) and is used to mark a class as an entity class, indicating that it will be mapped to a table in the database.
  • @Data: This annotation comes from the Lombok library, it is a shortcut that can automatically generate getter, setter, toString, equals and hashCode methods.

These two annotations can be used together, but it should be noted that @Data will generate hashCode and equals methods for all fields, which may conflict with the JPA specification or lazy loading. Therefore, caution should be exercised when using @Data.

Enterprise Microservices - Enterprise CRUD

module building

  • Build the enterprise microservice module ihrm_company, pom.xml introduces dependencies
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>com.ihrm</groupId>
            <artifactId>ihrm_common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>com.ihrm</groupId>
            <artifactId>ihrm_common_model</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
  • Add configuration file application.yml
server:
  port: 9001
spring:
  application:
    name: ihrm-company #指定服务名
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/ihrm?useUnicode=true&characterEncoding=utf8&useSSL=false
    username: root
    password: dzl+770880
  jpa:
    database: MySQL
    show-sql: true
    open-in-view: true

Sao Dai understands:

  • database: Specifies the type of database you use, here is MySQL.
  • show-sql: When this property is set to true, the SQL statement 1 generated by JPA will be printed on the console .
  • open-in-view: This property defaults to true, which determines whether to keep the database connection during view rendering.
  • Configure the startup class
@SpringBootApplication(scanBasePackages = "com.ihrm")
@EntityScan("com.ihrm")
public class CompanyApplication {
    public static void main(String[] args) {
        SpringApplication.run(CompanyApplication.class, args);
   }
    @Bean
    public IdWorker idWorkker() {
        return new IdWorker(1, 1);
   }
}

Sao Dai understands: the first parameter of the IdWorker(1, 1) constructor is the ID of the working machine, and the second parameter is the serial number

Enterprise Management-CRUD

Table structure analysis

CREATE TABLE `co_company` (
    `id` varchar(40) NOT NULL COMMENT 'ID',
    `name` varchar(255) NOT NULL COMMENT '公司名称',
    `manager_id` varchar(255) NOT NULL COMMENT '企业登录账号ID',
    `version` varchar(255) DEFAULT NULL COMMENT '当前版本',
    `renewal_date` datetime DEFAULT NULL COMMENT '续期时间',
    `expiration_date` datetime DEFAULT NULL COMMENT '到期时间',
    `company_area` varchar(255) DEFAULT NULL COMMENT '公司地区',
    `company_address` text COMMENT '公司地址',
    `business_license_id` varchar(255) DEFAULT NULL COMMENT '营业执照-图片ID',
    `legal_representative` varchar(255) DEFAULT NULL COMMENT '法人代表',
    `company_phone` varchar(255) DEFAULT NULL COMMENT '公司电话',
    `mailbox` varchar(255) DEFAULT NULL COMMENT '邮箱',
    `company_size` varchar(255) DEFAULT NULL COMMENT '公司规模',
    `industry` varchar(255) DEFAULT NULL COMMENT '所属行业',
    `remarks` text COMMENT '备注',
    `audit_state` varchar(255) DEFAULT NULL COMMENT '审核状态',
    `state` tinyint(2) NOT NULL DEFAULT '1' COMMENT '状态',
    `balance` double NOT NULL COMMENT '当前余额',
    `create_time` datetime NOT NULL COMMENT '创建时间'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

Complete the operation of adding, deleting, modifying and checking the enterprise

Persistence layer (dao)


/**
* 企业数据访问接口
*/
public interface CompanyDao extends JpaRepository<Company, String>, JpaSpecificationExecutor<Company> {
}

JpaRepository provides basic additions, deletions, changes, and queries. JpaSpecificationExecutor is used to do complex conditional queries

Sao Dai understands: Here dao only needs to inherit JpaRepository and JpaSpecificationExecutor. The generic Company of JpaRepository is the entity class of this dao, and String is the type of id of this entity class. Since the id set by this entity class is String type, so this Generics are also of type String

Business logic layer (service)

@Service
public class CompanyService {
    @Autowired
    private CompanyDao companyDao;
    @Autowired
    private IdWorker idWorker;
    /**
     * 添加企业
     *
     * @param company 企业信息
     */
    public Company add(Company company) {
        company.setId(idWorker.nextId() + "");
        company.setCreateTime(new Date());
        company.setState(1);    //启用
        company.setAuditState("0"); //待审核
        company.setBalance(0d);
        return companyDao.save(company);
   }
    public Company update(Company company) {
        return companyDao.save(company);
   }
    public Company findById(String id) {
        return companyDao.findById(id).get();
   }
    public void deleteById(String id) {
        companyDao.deleteById(id);
   }
    public List<Company> findAll() {
        return companyDao.findAll();
   }
}

Sao Dai understands: This is directly the implementation class of the service, and there is no service interface layer. I think this code level is not standardized!

controller

@RestController
@RequestMapping("/company")
public class CompanyController{
    @Autowired
    private CompanyService companyService;
 /**
 * 添加企业
 */
    @RequestMapping(value = "", method = RequestMethod.POST)
    public Result add(@RequestBody Company company) throws Exception {
        companyService.add(company);
        return Result.SUCCESS();
   }
    /**
 * 根据id更新企业信息
 */
    @RequestMapping(value = "/{id}", method = RequestMethod.PUT)
    public Result update(@PathVariable(name = "id") String id, @RequestBody Company
company) throws Exception {
        Company one = companyService.findById(id);
        one.setName(company.getName());
        one.setRemarks(company.getRemarks());
        one.setState(company.getState());
        one.setAuditState(company.getAuditState());
        companyService.update(company);
        return Result.SUCCESS();
   }
    /**
 * 根据id删除企业信息
 */
    @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
    public Result delete(@PathVariable(name = "id") String id) throws Exception {
        companyService.deleteById(id);
        return Result.SUCCESS();
   }
    /**
     * 根据ID获取公司信息
     */
    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
    public Result findById(@PathVariable(name = "id") String id) throws Exception {
        Company company = companyService.findById(id);
        return new Result(ResultCode.SUCCESS);
   }
    /**
     * 获取企业列表
     */
    @RequestMapping(value = "", method = RequestMethod.GET)
    public Result findAll() throws Exception {
        List<Company> companyList = companyService.findAll();
        return new Result(ResultCode.SUCCESS);
   }
}

Sao Dai understands: both the add and findAll methods have no subpath, that is, value = "", I didn't understand it at first, but it can be empty, so how to find this processor? Here it should be judged which processor is sent to by the following request method, that is, if you send a request to /company, it will jump to the corresponding processor according to whether your request type is get or post, but I think it is written like this Very irregular!

test

Test tool postman

Postman provides powerful Web API & HTTP request debugging. The function of the software is very powerful, the interface is simple and clear, the operation is convenient and fast, the design is very user-friendly, and it can send any type of HTTP request (GET, HEAD, POST, PUT..) with any number of parameters.

Use the postman installation package provided in the information to install, and you can use it after successful registration

Use postman to test the enterprise interface

public exception handling

In order to make our code easier to maintain and give users the best user experience, it is necessary to handle possible exceptions in the system. Spring provides @ControllerAdvice annotations and @ExceptionHandler, which can handle exceptions uniformly at the control layer

  • Add custom exception
package com.ihrm.common.exception;
import com.ihrm.common.entity.ResultCode;
import lombok.Getter;
@Getter
public class CommonException extends RuntimeException {
    private static final long serialVersionUID = 1L;
    private ResultCode code = ResultCode.SERVER_ERROR;
    public CommonException(){}
    public CommonException(ResultCode resultCode) {
        super(resultCode.message());
        this.code = resultCode;
   }
}
  • Configure common exception handling
package com.ihrm.common.exception;
import com.alibaba.fastjson.JSON;
import com.ihrm.common.entity.Result;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 全局异常处理
*/
@ControllerAdvice
public class BaseExceptionHandler {
    @ResponseBody
    @ExceptionHandler(value = Exception.class)
    public Result error(HttpServletRequest request, HttpServletResponse response, Exception e) throws IOException {
        e.printStackTrace();
        if (e.getClass() == CommonException.class) {
            CommonException ce = (CommonException) e;
            return new Result(ce.getCode());
       } else {
            return Result.ERROR();
       }
   }
}

cross domain processing

What is cross domain?

When a browser requests resources from a webpage of one domain name to another domain name, any difference in domain name, port, or protocol is cross-domain. We developed the front-end and back-end separately, and also deployed the front-end and back-end separately, so there will inevitably be cross-domain problems.

How to solve cross domain?

It's very simple, just add the annotation @CrossOrigin to the controller class! This annotation is actually the implementation of CORS. CORS (Cross-Origin Resource Sharing, Cross-Origin Resource Sharing) is a standard issued by W3C. Its idea is to use a custom HTTP header to allow the browser to communicate with the server to determine whether the request or response should succeed or fail. . Therefore, in order to implement CORS across domains, some server settings are required, and the front-end also needs to do some configuration and analysis.

Guess you like

Origin blog.csdn.net/qq_50954361/article/details/131333376