Problems encountered in development

Keywords: Java Database

Problems encountered in development

Processing scheme of enumeration type

Scheme 1: synchronize the set value by using the key value method

1. Define a new field to store the field description corresponding to the enumeration value

Here, quarter is the enumeration value of the corresponding database field

@ApiModelProperty(value = "Quarter, enumeration value: 1, 2, 3, 4 four values represent the quarter of a year Q1,Q2,Q3,Q4 Four quarters can be defined as enumeration in the code")
private Integer quarter;

quarterName is a self-defined property used to display the description information corresponding to the enumeration value (this field does not exist in the database)

@ApiModelProperty(value = "Quarter, city_info Table fields")
    @Excel(name = "quarter")
    public String quarterName;

2. Define a method in the enumeration that can obtain the corresponding description through the enumeration value

//@ApiModelProperty(value = "quarter, enumeration values: 1, 2, 3 and 4 represent Q1, Q2, Q3 and Q4 of a year, which can be defined as enumeration in the code")
public enum quarters {
    /**
     * KPI(1L, "Q1")
     */
    Q1(1, "Q1"),
    /**
     * PRAISE(2L, "Q2")
     */
    Q2(2, "Q2"),
    /**
     * COMPLAINT(3L, "Q3")
     */
    Q3(3, "Q3"),
    /**
     * INCENTIVE(4L, "Q4")
     */
    Q4(4, "Q4");

    /**
     * Quarter enumeration value, corresponding to QM_ accessories_ type field of info table
     */
    public final Integer value;
    /**
     * Quarter corresponding enumeration description
     */
    public final String desc;

    quarters (Integer value, String desc) {
        this.value = value;
        this.desc = desc;
    }

    public Integer getValue() {
        return value;
    }

    public String getDesc() {
        return desc;
    }

    //Get the value according to the key
    public static String getValueByKey(Integer value){
        for (QmMassIntegralStatVo.quarters q : QmMassIntegralStatVo.quarters.values()) {
            if(q.getValue()==value){
                return q.getDesc();
            }
        }
        return "";
    }

}

3. Override set method

What you want to add here is the value of quarterName to send to the front end. The premise that it has a value is that quarter has a value. Therefore, rewrite the set method of quarter to copy quarterName at the same time.

4. Add an annotation to identify that the user-defined attribute does not belong to the database

Without this annotation, when using an object to transfer values (for example, using the insert interface of mp), the transferred object will contain a quarterName attribute value, but it does not exist in the database. A field error appears.

Scheme 2: enumeration conversion using Mybatis

Single enumeration conversion

1. Define enumeration class

public enum QuarterType{
    /**
     * Q1(1, "Q1")
     */
    Q1(1, "Q1"),
    /**
     * PRAISE(2L, "Q2")
     */
    Q2(2, "Q2"),
    /**
     * COMPLAINT(3L, "Q3")
     */
    Q3(3, "Q3"),
    /**
     * INCENTIVE(4L, "Q4")
     */
    Q4(4, "Q4");

    /**
     * Quarter enumeration value, corresponding to QM_ accessories_ type field of info table
     */
    private Integer value;
    /**
     * Quarter corresponding enumeration description
     */
    private String desc;

    QuarterType(Integer value, String desc) {
        this.value = value;
        this.desc = desc;
    }

    public Integer getValue() {
        return value;
    }

    public String getDesc() {
        return desc;
    }

    public void setValue(Integer value) {
        this.value = value;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }

    //Get the value according to the key
    public static String getEnum(Integer value) {
        for (QmMassIntegralStatVo.quarters q : QmMassIntegralStatVo.quarters.values()) {
            if (q.getValue() == value) {
                return q.getDesc();
            }
        }
        return "";
    }

}

2. Create entity class

@Data
@ApiModel(value="QmMassIntegralStat Return front end object", description="Statistical table of mass integral")
@ExcelTarget("Mass integral")
public class QmMassIntegralStatVo extends QmMassIntegralStat implements Serializable {
    
    private QuarterType quarterType;

    @Override
    public String toString() {
        return "QmMassIntegralStatVo{" +
                "quarterType=" + quarterType +
                '}';
    }
}

3. Create enumeration conversion class

@Slf4j
@MappedTypes({QuarterType.class})  //The annotation here identifies which enumerations need to be used. It is required
public class QuarterTypeHandler extends BaseTypeHandler<QuarterType> {

    private Class<QuarterType> type;

    private QuarterType[] enums;

    /**
     * Set the conversion class and enumeration class content set by the configuration file for more convenient and efficient implementation by other methods
     * @param type Transformation class set in configuration file
     */
    public QuarterTypeHandler(Class<QuarterType> type) {
        if (type == null)
            throw new IllegalArgumentException("Type argument cannot be null");
        this.type = type;
        this.enums = type.getEnumConstants();
        if (this.enums == null)
            throw new IllegalArgumentException(type.getSimpleName()
                    + " does not represent an enum type.");
    }

    @Override
    public void setNonNullParameter(PreparedStatement preparedStatement, int i, QuarterType quarterType, JdbcType jdbcType) throws SQLException {
        preparedStatement.setString(i,quarterType.getDesc());
    }

    @Override
    public QuarterType getNullableResult(ResultSet resultSet, String s) throws SQLException {
    	// The acquisition type is determined according to the database storage type. In this example, the Integer type and the quarterly enumeration value in the corresponding enumeration class are stored in the database, the same below
        Integer i = resultSet.getInt(s);
        if (resultSet.wasNull()) {
            return null;
        }else {
            return QuarterType.getEnum(i);
        }
    }

    @Override
    public QuarterType getNullableResult(ResultSet resultSet, int columnIndex) throws SQLException {
        Integer i = resultSet.getInt(columnIndex);
        if (resultSet.wasNull()) {
            return null;
        }else {
            return QuarterType.getEnum(i);
        }
    }

    @Override
    public QuarterType getNullableResult(CallableStatement callableStatement, int columnIndex) throws SQLException {
        Integer i = callableStatement.getInt(columnIndex);
        if (callableStatement.wasNull()) {
            return null;
        }else {
            return QuarterType.getEnum(i);
        }
    }
}

4. Writing xml

Type identification needs to be added when writing xml

Use when querying:
Use when adding:

5. Writing method

Just write the code of controller, service and mapper layers

Universal enumeration conversion (not fully implemented)

1. Define enumeration interface for easier management

public interface BaseEnum <E extends Enum<E>, T>{
    Set<Class<?>> subClass = Sets.newConcurrentHashSet();
    T getValue();
    String getDesc();
}

2. The enumeration class is defined above, and the enumeration interface is implemented
3. Create an entity class as above

4. Write a general enumeration converter

@Slf4j
@MappedTypes({QuarterType.class})
public class QuarterTypeHandler<E extends BaseEnum> extends BaseTypeHandler<E> {

    private Class<E> type;

    private E[] enums;
    
    /**
     * Set the conversion class and enumeration class content set by the configuration file for more convenient and efficient implementation by other methods
     * @param type Transformation class set in configuration file
     */
    public QuarterTypeHandler(Class<E> type) {
        if (type == null)
            throw new IllegalArgumentException("Type argument cannot be null");
        System.out.println("1234567894512345623"+type);
        this.type = type;
        this.enums = type.getEnumConstants();
        if (this.enums == null)
            throw new IllegalArgumentException(type.getSimpleName()
                    + " does not represent an enum type.");
    }

    /**
     * Enumeration type conversion, because the constructor obtains the subclass enums of enumeration, which makes the traversal more efficient and fast
     * @param value Custom value attribute stored in database
     * @return value Corresponding enumeration class
     */
    //The parameter passed in here should be the same as the parameter type of the enumeration value
    private E locateEnumStatus(Integer value) {
        for(E e : enums) {
            if(e.getValue().equals(value)) {
                return e;
            }
        }
        throw new IllegalArgumentException("Unknown enumeration type:" + value + ",Please check" + type.getSimpleName());
    }

    @Override
    public void setNonNullParameter(PreparedStatement preparedStatement, int i, E e, JdbcType jdbcType) throws SQLException {
        preparedStatement.setString(i,e.getDesc());
    }

    @Override
    public E getNullableResult(ResultSet resultSet, String s) throws SQLException {
        Integer i = resultSet.getInt(s);
        if (resultSet.wasNull()) {
            return null;
        }else {
            return locateEnumStatus(i);
        }
    }

    @Override
    public E getNullableResult(ResultSet resultSet, int columnIndex) throws SQLException {
        Integer i = resultSet.getInt(columnIndex);
        if (resultSet.wasNull()) {
            return null;
        }else {
            return locateEnumStatus(i);
        }
    }

    @Override
    public E getNullableResult(CallableStatement callableStatement, int columnIndex) throws SQLException {
        Integer i = callableStatement.getInt(columnIndex);
        if (callableStatement.wasNull()) {
            return null;
        }else {
            return locateEnumStatus(i);
        }
    }
}

5. Write xml as above

6. Write as above

Mybatis Plus conversion method

https://www.cnblogs.com/dalianpai/p/11771269.html

Define enumeration class

  • Add Getter annotation
  • @EnumValue corresponds to the field name in the database
  • @JsonValue corresponds to the value echoed on the page
@Getter
public enum StateEnum {
    /**
     *
     */

    published(1,"Published"),
    unpublished(0,"Unpublished");

    @EnumValue
    private final int startus;
    @JsonValue
    private final String desc;

    StateEnum(int startus, String desc){
        this.startus = startus;
        this.desc = desc;
    }
}

Entity class

  • @Jsonfield (serializefeatures = serializerfeature. Writeenumusingtostring) identifies the transformation
  • The entity parameter name here and the value name in the enumeration class are consistent with the field name in the database
@ApiModelProperty(value = "Status: 0 - Unpublished, 1 - Published")
@JSONField(serialzeFeatures= SerializerFeature.WriteEnumUsingToString)
private StateEnum startus;

to configure

  • Scan enumerated packages
mybatis-plus:  
  typeEnumsPackage: com.isoftstone.cloudmsp.channel.partner.policy.Enums;

Empty judgment of a large number of attributes

During development, the front end may encounter many required items when filling in the form. After the front end verification, in order to prevent sending data directly to the service, the back end also needs to verify to ensure accuracy.

Here, you can use a single judgment: user.name == null to verify.

However, once more values need to be verified, there will be a lot of if judgment redundancy, which will affect the speed and waste resources.

At this time, you can make judgment by annotation:

@NotBlank(message = "Partner type cannot be empty")
@ApiModelProperty(value = "Partner type")
@TableField(exist=false)
private String partnerType;
  • The @ NotBlank annotation here is javax.validation.constraints.NotBlank; Functions in
  • @NotBlank:
    This can only work on the received String type. Note that it can only be null, and the length must be greater than 0 after calling trim()
  • @NotNull:
    Cannot be null, but can be empty("", "," "), which is generally used for non null verification of basic data types, and the marked field can use @ size/@Max/@Min to control the size of the field value

Prompt configuration

After using the annotation, you need to write the corresponding configuration class to prompt the corresponding message in the annotation

The configuration classes are as follows:

/**
 * @author tingzhenge
 * @date 2021/9/3
 */
@ControllerAdvice
public class ControllerExceptionHandler {

    @ResponseBody
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public RestResult exceptionHandler(MethodArgumentNotValidException e)
    {
        return new RestResult(RestResult.FAIL_CODE, null, e.getBindingResult().getFieldError().getDefaultMessage());
    }
}

Other commonly used

Problems in Activiti workflow

User groups acquire and complete tasks

When the task node does not specify a person in charge, and the person who can operate the node is a certain role. For example, in the first step of approving a leave application, the approval of the Department Manager is generally required, but there may be multiple department managers. Everyone can operate the application, or if a new department manager is added, he should also be able to see and operate such a task belonging to the Department Manager.

In this scenario, we can use user groups to help us complete the above operations.

Now, when defining the process, we write the corresponding role ID on the user group definition.

When completing the task, first judge whether the current user is the permission of the user group. Then let the processor pick up the task and complete the task. In this way, the current processor can be put into "act_hi_task" for subsequent query operations.

// First judge whether to change the task role
List<Task> taskList = processEngine.getTaskService().createTaskQuery()
        .taskCandidateGroup(assignee)
        .list();
if(!taskList.isEmpty()){
    // Obtain the id and person in charge of the task parameter process instance through TaskService
    Task task = taskService.createTaskQuery()
            .processInstanceId(processInstanceId)
            .singleResult();

    // Pick task
    taskService.claim(task.getId(),userName);

    System.out.println("Process instance id = "+task.getProcessInstanceId());
    System.out.println("Process task id = "+task.getId());
    System.out.println("Task name = "+task.getName());

    // Complete the task according to the id of the task
    taskService.complete(task.getId());

Get previous task node information

To obtain the information of the previous node, we query through the information in "ACT_HI_TASKINST", use the process instance Id - processInstanceId to obtain the current task, then correct the fact that the unfinished tasks in the table have no end time feature, and flashback to find the latest information, that is, the information of the previous node.

/**
 * Obtain the information of the previous node according to the process instance id
 *
 * @param proInsId
 * @param historyService
 * @return
 */
public static HistoricTaskInstance queryUpOneNodeMessage(String proInsId, HistoryService historyService) {
    //Previous node
    List<HistoricTaskInstance> list = historyService
            .createHistoricTaskInstanceQuery()
            .processInstanceId(proInsId)
            .orderByHistoricTaskInstanceEndTime()
            .desc()
            .list();
    HistoricTaskInstance taskInstance = null;
    if (!list.isEmpty()) {
        if (list.get(0).getEndTime() != null) {
            taskInstance = list.get(0);
        }
    }
    return taskInstance;
}

/**
 * Obtain the information of the previous node according to the task id
 *
 * @param taskId
 * @return
 */
public static HistoricTaskInstance queryUpOneNode(String taskId, HistoryService historyService) {
    //Previous node
    List<HistoricTaskInstance> list = historyService
            .createHistoricTaskInstanceQuery()
            .taskId(taskId).orderByHistoricTaskInstanceEndTime()
            .desc()
            .list();
    HistoricTaskInstance taskInstance = null;
    if (!list.isEmpty()) {
        if (list.get(0).getEndTime() != null) {
            taskInstance = list.get(0);
        }
    }
    return taskInstance;
}

Use of Pair key value pairs

It can be used when there are only two return values of the function

Under the javax.util package, a simple Pair class can be called directly. The usage is to store the key and value of the attracted type directly through the constructor. There is no corresponding relationship between the key and value, and the type is arbitrary.
Usage:
Pair<String, String> pair = new Pair<>("aku", "female");
pair.getKey();
pair.getValue();

for example

taskInstance.getAssignee());
map.put("lastEndTime",taskInstance.getEndTime());
Pair<String, Date> pair = new Pair<>(taskInstance.getAssignee(),taskInstance.getEndTime());

// When used
Pair<String, Date> pair = taskService.findLastNodeInfo(businessKey);
            qmRecallProcessInfoVo.setLastHandler(pair.getKey());
            qmRecallProcessInfoVo.setLastHandleTime(pair.getValue());

That is, the two returned values are stored in pair in the form of keys and values respectively. You only need to obtain keys and values respectively.

RestTemplate send request

Params request

Use map to build request data

public void PostRequest() throws URISyntaxException {
        URI uri = new URI("http://api.isoftstone.com/iSSC/msgServiceTest/1.0/msgOtherSystem/insertList");
        String token = "eyJhbGciOiJSUzI1NiIsImtpZCI6IjNmNmU4ZDRlOTMzYTI2OGQxOGEzMTJlYzdiOWVlYjZhIiwidHlwIjoiSldUIn0.eyJuYmYiOjE2Mjk4OTY4NzQsImV4cCI6MTYyOTkwMDQ3NCwiaXNzIjoiaHR0cHM6Ly9hcGkuaXNvZnRzdG9uZS5jb20vaWRzIiwiYXVkIjpbImh0dHBzOi8vYXBpLmlzb2Z0c3RvbmUuY29tL2lkcy9yZXNvdXJjZXMiLCJtc2dTZXJ2aWNlIiwibXNnU2VydmljZVRlc3QiXSwiY2xpZW50X2lkIjoiZjE3Njc3NDEtNmIzYS00ZmM3LThmMWQtNjYzNjJlY2RmODFhIiwic2NvcGUiOlsibXNnU2VydmljZSIsIm1zZ1NlcnZpY2VUZXN0Il19.RJUl87KfYJLwlPn9lN6zpVSH9vWQzTdP1q-KLYPJwWnMRACZeF0meTTPWpEq_P4Qwbof25ALhC2E8Njp3LzEblDGS8zWvhqzn0x8iT9Ikrjd2TGlMWlkUpM8qwUi2Hmd52E2eI86XRIXmUwCFVnuFJ44sFlxz2ovDjNoyGEdY3UqOfZ8LQmwlqrVluD4QHi7_a2esiexViwsXxJ7IJvrAwFNg0cKtx0C9-LWX65rS7CamAdMSOOlbKHQQreURkLluzLYauj0r2v9PSKFwCwz-3RiYvh-hnBRUKmhqNj5JC4f8lQZIyQTnZ-Pm27tjh7gTMONGF2OBn1oQr2CDCbdSg";
        RestTemplate restTemplate = new RestTemplate();
        // Build request header
        HttpHeaders headers = new HttpHeaders();
        // Format request header
        MediaType type = MediaType.parseMediaType("application/json");
        headers.setContentType(type);
        headers.add("Authorization","Bearer " + token);

        // Map
        Map<String, Object> param = new HashMap<String, Object>();
        param.put("mobile","13016423117");
        param.put("templateId","65e66878-2f21-4c12-853d-595156fa586e");
        param.put("userDefinedParam","");
        param.put("systemName","MSP Soft cloud");
        HttpEntity<Map<String, Object>> httpEntity = new HttpEntity<>(param,headers);
        String jsonObject = restTemplate.postForEntity(uri,httpEntity,String.class).getBody();
        System.out.println(jsonObject);

        // MultiValueMap
        // MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
        // map.add("mobile","13016423117");
        // map.add("templateId","65e66878-2f21-4c12-853d-595156fa586e");
        // map.add("userDefinedParam",content);
        // map.add("systemName","MSP softcloud");
        // HttpEntity<Object> requestEntity = new HttpEntity<>(map, headers);
        // ResponseEntity<String> exchange = restTemplate.exchange(uri, HttpMethod.POST, requestEntity, String.class);
        // JSONObject jsonObject = JSON.parseObject(exchange.getBody());
        // System.out.println(jsonObject);

    }

JSON request

public void PostRequest() throws URISyntaxException {
        URI uri = new URI("http://api.isoftstone.com/iSSC/msgServiceTest/1.0/msgOtherSystem/insertList");
        String token = "eyJhbGciOiJSUzI1NiIsImtpZCI6IjNmNmU4ZDRlOTMzYTI2OGQxOGEzMTJlYzdiOWVlYjZhIiwidHlwIjoiSldUIn0.eyJuYmYiOjE2Mjk4OTY4NzQsImV4cCI6MTYyOTkwMDQ3NCwiaXNzIjoiaHR0cHM6Ly9hcGkuaXNvZnRzdG9uZS5jb20vaWRzIiwiYXVkIjpbImh0dHBzOi8vYXBpLmlzb2Z0c3RvbmUuY29tL2lkcy9yZXNvdXJjZXMiLCJtc2dTZXJ2aWNlIiwibXNnU2VydmljZVRlc3QiXSwiY2xpZW50X2lkIjoiZjE3Njc3NDEtNmIzYS00ZmM3LThmMWQtNjYzNjJlY2RmODFhIiwic2NvcGUiOlsibXNnU2VydmljZSIsIm1zZ1NlcnZpY2VUZXN0Il19.RJUl87KfYJLwlPn9lN6zpVSH9vWQzTdP1q-KLYPJwWnMRACZeF0meTTPWpEq_P4Qwbof25ALhC2E8Njp3LzEblDGS8zWvhqzn0x8iT9Ikrjd2TGlMWlkUpM8qwUi2Hmd52E2eI86XRIXmUwCFVnuFJ44sFlxz2ovDjNoyGEdY3UqOfZ8LQmwlqrVluD4QHi7_a2esiexViwsXxJ7IJvrAwFNg0cKtx0C9-LWX65rS7CamAdMSOOlbKHQQreURkLluzLYauj0r2v9PSKFwCwz-3RiYvh-hnBRUKmhqNj5JC4f8lQZIyQTnZ-Pm27tjh7gTMONGF2OBn1oQr2CDCbdSg";
        RestTemplate restTemplate = new RestTemplate();
        // Build request header
        HttpHeaders headers = new HttpHeaders();
        // Format request header
        MediaType type = MediaType.parseMediaType("application/json");
        headers.setContentType(type);
        headers.add("Authorization","Bearer " + token);

        // Building JSON
        JSONObject content = new JSONObject();
        content.put("checkCode","Off duty!!!");

        JSONObject json = new JSONObject();
        json.put("mobile","13016431938");
        json.put("templateId","65e66878-2f21-4c12-853d-595156fa586e");
        json.put("userDefinedParam",content);
        json.put("systemName","MSP Soft cloud");
        
        JSONArray array = new JSONArray();
        array.add(json);
        
        // Build request body
        HttpEntity<String> httpEntity = new HttpEntity<String>(array.toString(),headers);
        String jsonObject = restTemplate.postForEntity(uri,httpEntity,String.class).getBody();
        
        System.out.println(jsonObject);
    }
  • notes

    When requesting JSON as follows:

    "[]" can only be found after building JSONObject and putting it into JSONArray. See the above code for details.

OkHttp send request

JSON request

public Boolean sendDriveMSG(String tel, String companyName) throws IOException {
    //Look up the data from the database
    SysSmsServerConfigVo sysSmsServerConfigVo = smsServerConfigMapper.querySmsConfig();
    // Request address
    String url = sysSmsServerConfigVo.getSendUrl();

    // Get token
    String token;
    if (verifyToken()) {
        token = redisTemplate.opsForValue().get("token");
    } else {
        token = getToken();
    }

    // Set request header
    Map header = new HashMap();
    header.put("Authorization", "Bearer " + token);

    // Assemble json requests
    JSONObject json = new JSONObject();
    JSONObject content = new JSONObject();
    json.put("mobile", tel);
    json.put("systemName", "xxxx");
    json.put("templateId", "xxxxxxx");
    content.put("companyName", companyName);
    json.put("userDefinedParam", content);

    JSONArray array = new JSONArray();
    array.add(json);

    // Send request and get results
    Response response = OkHttpUtil.post(url, array.toString(), header);
    if (response.code() == 200) {
        return true;
    }
    return false;
}

Form data format request

FormBody needs to be built to send

public String getToken() {
    //Look up the data from the database
    SysSmsServerConfigVo sysSmsServerConfigVo = smsServerConfigMapper.querySmsConfig();

    OkHttpClient okHttpClient = new OkHttpClient();

    String uri = "https://api.isoftstone.com/ids/connect/token";

    FormBody formBody = new FormBody.Builder()
            .add("client_id", sysSmsServerConfigVo.getAppKey())
            .add("client_secret", sysSmsServerConfigVo.getAppSecret())
            .add("grant_type", "client_credentials")
            .add("scope", "msgService msgServiceTest")
            .build();
    Request request = new Request.Builder()
            .url(uri)
            .post(formBody)
            .build();
    try {
        Response response = okHttpClient.newCall(request).execute();
        String respBody = new String(response.body().bytes(), "gbk");
        System.out.println(respBody);
        // Add the token to Rides, which is valid for 10 minutes
        JSONObject jsonObject = JSON.parseObject(respBody);
        System.out.println(jsonObject.getString("access_token").toString());
        String token = jsonObject.getString("access_token");
        redisTemplate.opsForValue().set("token", token, 3600, TimeUnit.SECONDS);
        return token;
    } catch (Exception e) {
        System.out.println("obtain Token fail");
    }
    return "";
}

Processing scheme in Mybatis Plus

Posted by guzman-el-bueno on Fri, 17 Sep 2021 18:11:27 -0700