springboot Computer Shop Project 6. Added receipt address 7. Provincial and Urban Display

Posted by jiehuang001 on Wed, 02 Feb 2022 05:36:06 +0100

6. Added receipt address

1. New Receipt Address-Database Table Creation

CREATE TABLE t_address (
	aid INT AUTO_INCREMENT COMMENT 'Receipt address id',
	uid INT COMMENT 'Owned User id',
	name VARCHAR(20) COMMENT 'Consignee Name',
	province_name VARCHAR(15) COMMENT 'province-Name',
	province_code CHAR(6) COMMENT 'province-Administrative Code',
	city_name VARCHAR(15) COMMENT 'city-Name',
	city_code CHAR(6) COMMENT 'city-Administrative Code',
	area_name VARCHAR(15) COMMENT 'area-Name',
	area_code CHAR(6) COMMENT 'area-Administrative Code',
	zip CHAR(6) COMMENT 'Postal Code',
	address VARCHAR(50) COMMENT 'Detailed address',
	phone VARCHAR(20) COMMENT 'Mobile phone',
	tel VARCHAR(20) COMMENT 'Fixed line',
	tag VARCHAR(6) COMMENT 'Label',
	is_default INT COMMENT 'Default or not:0-No default, 1-default',
	created_user VARCHAR(20) COMMENT 'Creator',
	created_time DATETIME COMMENT 'Creation Time',
	modified_user VARCHAR(20) COMMENT 'Modifier',
	modified_time DATETIME COMMENT 'Modification Time',
	PRIMARY KEY (aid)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

2. Add Receipt Address - Create Entity Class

package com.jiabowen.store.entity;

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

@Data
@AllArgsConstructor
@NoArgsConstructor
/**Receipt Address Entity Class*/
public class Address extends BaseEntity {
    private Integer aid;
    private Integer uid;
    private String name;
    private String provinceName;
    private String provinceCode;
    private String cityName;
    private String cityCode;
    private String areaName;
    private String areaCode;
    private String zip;
    private String address;
    private String phone;
    private String tel;
    private String tag;
    private Integer isDefault;
}

3. New Receipt Address - Persistence Layer

3.1 Sequence of development of each function

Current Receipt Address Module: List Display, Modify, Delete, Set Default, Add Receipt Address. Order of development: Add harvest address - List display - Set default harvest address - Modify delivery address

3.2 Planning for SQL statements to be executed

1. Corresponding insert statements:

insert into t_address (except aid List of Outer Fields) values(Field Value List)

2. A user's harvest address specifies that a maximum of 20 data corresponds to each other, and queries are made before inserting user data. An exception to the logical request for the receipt address

select count(*) from t_address where uid = ?

3.3 Interfaces and Abstract Methods

Create an interface Address in which to define the above two Sql statement abstract method mappings.

/**
     * Insert the user's receipt address
     * @param address Receipt Address Data
     * @return Number of rows affected
     */
Integer insert(Address address);

/**
     * Count the number of receipt addresses based on the user's id
     * @param uid User's id
     * @return Total number of receipt addresses for the current user
     */
Integer countByUid(Integer uid);

3.4 Configure SQL Mapping

Create an AddressMapper.xml Mapping file, add abstract methods to this file

<?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.jiabowen.store.mapper.AddressMapper">

    <resultMap id="AddressEntityMap" type="com.jiabowen.store.entity.Address">
        <id column="aid" property="aid"/>
        <result column="province_code" property="provinceCode"/>
        <result column="province_name" property="provinceName"/>
        <result column="city_code" property="cityCode"/>
        <result column="city_name" property="cityName"/>
        <result column="area_code" property="areaCode"/>
        <result column="area_name" property="areaName"/>
        <result column="is_default" property="isDefault"/>
        <result column="created_user" property="createdUser"/>
        <result column="created_time" property="createdTime"/>
        <result column="modified_user" property="modifiedUser"/>
        <result column="modified_time" property="modifiedTime"/>
    </resultMap>
    
    <insert id="insert">
        INSERT INTO t_address (
            uid, name, province_name, province_code, city_name, city_code, area_name, area_code, zip,
            address, phone, tel,tag, is_default, created_user, created_time, modified_user, modified_time
        ) VALUES (
            #{uid}, #{name}, #{provinceName}, #{provinceCode}, #{cityName}, #{cityCode}, #{areaName},
            #{areaCode}, #{zip}, #{address}, #{phone}, #{tel}, #{tag}, #{isDefault}, #{createdUser},
            #{createdTime}, #{modifiedUser}, #{modifiedTime}
        )
    </insert>

    <select id="countByUid" resultType="java.lang.Integer">
        select count(*) from t_address where uid = #{uid}
    </select>
</mapper>

Testing mapper layer code

@Test
public void insert(){
    Address address = new Address();
    address.setUid(29);
    address.setName("Zhang San");
    address.setPhone("11122233344");
    System.out.println(addressMapper.insert(address));
}

@Test
public void countByUid(){
    Integer count = addressMapper.countByUid(29);
    System.out.println(count);
}

4. New Receipt Address-Business Layer

4.1 Planning Exceptions

( If the user is inserting the user's address for the first time, the rule is that when the user inserts the first address, the default shipping address is based on the current address, and if the total statistic is 0, the is_of the current address is The default value is set to 1. A query statistic with a result of 0 does not represent an exception.

( The query result is greater than 20, which requires throwing the AddressCountLimitException exception for business control. Create this exception yourself.

public class AddressCountLimitException extends ServiceException {
    //...
}

4.2 Interfaces and Abstract Methods

1. Create an IAddressService interface that defines an abstract method of business

/**
 * Receipt Address Business Layer Interface
 */
public interface IAddressService {
    void addNewAddress(Integer uid, String username, Address address);
}

2. Create an AddressServiceImpl implementation class to implement abstract methods in interfaces

public class AddressServiceImpl implements IAddressService {
    @Autowired
    private AddressMapper addressMapper;
    @Value("${user.address.max-Count}")
    private Integer maxCount;
    @Override
    public void addNewAddress(Integer uid, String username, Address address) {
        //Call the method of harvesting address statistics
        Integer count = addressMapper.countByUid(uid);
        if (count >= maxCount){
            throw new AddressCountLimitException("User receipt address exceeds maximum");
        }
        //Set uid isdefault
        address.setUid(uid);
        Integer isdefault = count == 0 ? 1 : 0;//1 means default, 0 means not default
        address.setIsDefault(isdefault);
        //Complete Log
        address.setCreatedUser(username);
        address.setModifiedUser(username);
        address.setCreatedTime(new Date());
        address.setModifiedTime(new Date());
        
        //Method of inserting receipt address
        Integer rows = addressMapper.insert(address);
        if (rows != 1){
            throw new InsertException("Inserting the user's receipt address caused an unknown exception");
        }
    }
}

configuration file

#Spring reads the data in the configuration file: ${user.address.max-count}
user.address.max-count=20

3. Test if the business tier functionality is working.

@SpringBootTest
@RunWith(SpringRunner.class)
public class AddressServiceTest {
    @Autowired
    IAddressService addressService;
    @Test
    public void addNewAddress() {
        Address address = new Address();
        address.setPhone("11111111111");
        address.setName("Zhang Zhang");
        addressService.addNewAddress(50,"Li Si",address);
    }
}

5. New Receipt Address-Controller

5.1 Handling Exceptions

The business layer throws an exception that the total number of corresponding receipt addresses exceeds the standard and needs to be handled in the baseController

else if (e instanceof AddressCountLimitException) {
    result.setState(4003);
    result.setMessage("Exception for number of receipt addresses exceeding limit for user");
}

5.2 Design Request

/addresses/add_new_address
post
Address address,Httpsession session
JsonResult<Void>

5.3 Processing Requests

Create AddressCountroller in the Control Layer to process requests and responses for user receipt addresses

package com.jiabowen.store.controller;

import com.jiabowen.store.entity.Address;
import com.jiabowen.store.service.IAddressService;
import com.jiabowen.store.util.JsonResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpSession;

@RequestMapping("address")
@RestController
public class AddressController extends BaseController {

    @Autowired
    private IAddressService addressService;

    @RequestMapping("add_new_address")
    public JsonResult<Void> addNewAddress(Address address, HttpSession session){
        Integer uid = getUidFromSession(session);
        String username = getUsernameFormSession(session);
        addressService.addNewAddress(uid,username,address);
        return new JsonResult<>(OK);
    }
}

Test interface:

6 New Receipt Address-Front Interface

<script>
    //1. Listen for the registration button to be clicked, if clicked you can execute a method
    $("#btn-add-new-address").click(function () {
    //2. Send ajax
    $.ajax({
        url: "/address/add_new_address",
        type: "POST",
        data: $("#form-add-new-address").serialize(),
        dataType: "JSON",
        success: function (json) {
            if (json.state == 200){
                alert("New Receipt Address Succeeded")
                console.log(json)
            }else{
                alert("Failed to add new receipt address")
            }
        },
        error: function (xhr) {
            alert("Unknown error when adding new receipt address" + xhr.status)
        }
    });
});
</script>

7 Get a list of provinces and municipalities

1. Get a list of provinces and municipalities

CREATE TABLE t_dict_district (
  id INT(11) NOT NULL AUTO_INCREMENT,
  parent VARCHAR(6) DEFAULT NULL,
  CODE VARCHAR(6) DEFAULT NULL,
  NAME VARCHAR(16) DEFAULT NULL,
  PRIMARY KEY (id)
) ENGINE=INNODB DEFAULT CHARSET=utf8;

The parent attribute represents the code number of the parent region, and the parent code number of the province is + 86

2. Get a list of provinces and municipalities - entity classes

public class District extends BaseEntity {
    private Integer id;
    private String parent;
    private String code;
    private String name;
}

3. Get a list of provinces and municipalities - Permanent Layer

Query statement:

select * from t_dict_district where parent = ? order by code ASC

asc: ascending order

Abstract method definition: DistrictMapper interface

package com.jiabowen.store.mapper;

import com.jiabowen.store.entity.District;

import java.util.List;

public interface DistrictMapper {

    /**
     * Query region information based on parent code
     */
    List<District> findByParent(Integer parent);

}

Interface Mapping

<?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.jiabowen.store.mapper.DistrictMapper">
    <select id="DistrictMapper" resultType="com.jiabowen.store.entity.District">
        select * from t_dict_district where parent = #{parent}
        order by code ASC
    </select>
</mapper>

Test persistence layer

@Test
public void findByParent(){
    List<District> list = districtMapper.findByParent("210100");
    System.err.println(666666);
    for (District district : list) {
        System.out.println(district);
    }
}

4. Get a list of provinces and municipalities - business layer

1. Create an interface IDistrictService and define an abstract method

public interface IDistrictService {
    /**
     * Query region information based on parent code (provincial and urban)
     * @param parent Parent Code
     * @return Multiple Area Information
     */
    List<District> getByParent(String parent);
}

2. Create DistrictServiceImpl implementation class to implement abstract methods

@Service
public class DistrictService implements IDistrictService {

    @Autowired
    private DistrictMapper districtMapper;

    @Override
    public List<District> getByParent(String parent) {
        List<District> list = districtMapper.findByParent(parent);
        /**
         * When transferring network data, null can be set for invalid data in order to avoid the transfer of invalid data as much as possible.
         * Save traffic and increase efficiency
         */
        for (District district : list) {
            district.setId(null);
            district.setParent(null);
        }
        return list;
    }
}

3. Conduct unit testing

@SpringBootTest
@RunWith(SpringRunner.class)
public class DistrictServiceTest {

    @Autowired
    private IDistrictService districtService;

    @Test
    public void getByParent(){
        List<District> list = districtService.getByParent("210100");
        for (District district : list) {
            System.out.println(district);
        }
    }
}

5 Get List of Provincial and Urban Areas - Control Layer

5.1 Design Request

/districts
GET
String parent
JsonResult<List<District>>

5.2 Implementation Request

Create a DistrictController class in which you write methods to handle requests.

@RequestMapping("districts")
@RestController
public class DistrictController extends BaseController {

    @Autowired
    private IDistrictService districtService;

    @RequestMapping({"/",""})
    public JsonResult<List<District>> getByParent(String parent){
        List<District> data = districtService.getByParent(parent);
        return new JsonResult<>(OK, data);
    }
}

Add the districts request to the whitelist.

patterns.add("/districts/**");

Direct request server, access: localhost:8080/districts?parent=86

6 Get a list of provinces and municipalities - front-end page

1. Comment out the JS code used to load the provincial and urban lists through js.

<!--
<script type="text/javascript" src="../js/distpicker.data.js"></script>
<script type="text/javascript" src="../js/distpicker.js"></script>
-->

2. Check if the front-end page has a related name attribute when submitting provincial and urban data

3. Run the front end to see if you can save data (in addition to provincial and urban areas).

Get the name of the province or city

1 Get the name of the province or city

1. The plan obtains the name of the current province or city according to the current code, which corresponds to a query statement

select * from t_dist_districts where code = ?

2. Define in the DistrictMapper interface

String findNameByCode(String code);

3. In DistrictMapper. Add a mapping of an abstract method to the XML file.

<select id="findNameByCode" resultType="java.lang.String">
    select name from t_dict_district where code = #{code}
</select>

4. Unit test methods

@Test
public void findNameByCode(){
    String name = districtMapper.findNameByCode("210000");
    System.out.println(name);
}

2 Get the name of the province or city - the business layer

1. There are no exceptions to handle at the business level

2. Define abstract methods in corresponding business-tier interfaces

String getNameByCode(String code);

3. Implement in subclasses

@Override
public String getNameByCode(String code) {
    String nameByCode = districtMapper.findNameByCode(code);
    return nameByCode;
}

4. Testing

Note: More than 8 lines of code should be tested independently

3Obtaining the name of a province or an urban area-Business layer optimization

1. Adding an address layer depends on the IDistrictService layer

//The business layer that adds a user's receipt address relies on the business interface of IDistrictService
@Autowired
private IDistrictService districtService;

2. In the addNewAddress method, the provincial and urban data obtained from the districtService interface is transferred to the address object, which contains all the data of the user's harvest address.

String provinceNameByCode = districtService.getNameByCode(address.getProvinceCode());
String cityNameByCode = districtService.getNameByCode(address.getCityCode());
String areaNameByCode = districtService.getNameByCode(address.getAreaCode());
address.setProvinceName(provinceNameByCode);
address.setCityName(cityNameByCode);
address.setAreaName(areaNameByCode);
@Service
public class AddressServiceImpl implements IAddressService {

    @Autowired
    private AddressMapper addressMapper;

    //The business layer that adds a user's receipt address relies on the business interface of IDistrictService
    @Autowired
    private IDistrictService districtService;

    @Value("${user.address.max-count}")
    private Integer maxCount;

    @Override
    public void addNewAddress(Integer uid, String username, Address address) {
        //Call the method of harvesting address statistics
        Integer count = addressMapper.countByUid(uid);
        if (count >= maxCount){
            throw new AddressCountLimitException("User receipt address exceeds maximum");
        }

        String provinceNameByCode = districtService.getNameByCode(address.getProvinceCode());
        String cityNameByCode = districtService.getNameByCode(address.getCityCode());
        String areaNameByCode = districtService.getNameByCode(address.getAreaCode());
        address.setProvinceName(provinceNameByCode);
        address.setCityName(cityNameByCode);
        address.setAreaName(areaNameByCode);

        //Set uid isdefault
        address.setUid(uid);
        Integer isdefault = count == 0 ? 1 : 0;//1 means default, 0 means not default
        address.setIsDefault(isdefault);
        //Complete Log
        address.setCreatedUser(username);
        address.setModifiedUser(username);
        address.setCreatedTime(new Date());
        address.setModifiedTime(new Date());

        //Method of inserting receipt address
        Integer rows = addressMapper.insert(address);
        if (rows != 1){
            throw new InsertException("Inserting the user's receipt address caused an unknown exception");
        }
    }
}

4 Get the provincial-urban-front interface

1.addAddress. Write the corresponding provincial and urban display on the HTML page and restrict the content in the corresponding label according to the user's different choices.

2. Write relevant event code

<script>
    //The value attribute represents the code value of the current region
    let defaultOption = "<option value = '0'>---Please select---</option>"
$(document).ready(function () {
    showProvinceList();
    //Set the default Please Select value as the default value for the control

    $("#city-list").append(defaultOption);
    $("#area-list").append(defaultOption);
    $("#province-list").append(defaultOption);
});

$("#city-list").change(function () {
    //Get Administrative Region Parent Code First
    let parent = $("#city-list").val();
    //Empty all option elements in the select drop-down list
    $("#area-list").empty();
    //Fill in the default value "Please Select"
    $("#area-list").append(defaultOption);

    if (parent == 0){
        return;
    }

    $.ajax({
        url: "/districts",
        type: "GET",
        data: "parent=" + parent,
        dataType: "JSON",
        success: function (json) {
            if (json.state == 200){
                let list = json.data;
                for (let i = 0; i < list.length; i++) {
                    let opt = "<option value='"+list[i].code+"'>"+list[i].name+"</option>"
                    $("#area-list").append(opt);
                }
            }else{
                alert("County Information Loading Failed")
            }
        }
    });

});


/*
			* change()Function that monitors whether a control has changed and triggers a parameter whenever it has changed
			* A function(){} needs to be passed
			* */
$("#province-list").change(function () {
    //Get Administrative Region Parent Code First
    let parent = $("#province-list").val();
    //Empty all option elements in the select drop-down list
    $("#city-list").empty();
    $("#area-list").empty();
    //Fill in the default value "Please Select"
    $("#city-list").append(defaultOption);
    $("#area-list").append(defaultOption);

    if (parent == 0){
        return;
    }

    $.ajax({
        url: "/districts",
        type: "GET",
        data: "parent=" + parent,
        dataType: "JSON",
        success: function (json) {
            if (json.state == 200){
                let list = json.data;
                for (let i = 0; i < list.length; i++) {
                    let opt = "<option value='"+list[i].code+"'>"+list[i].name+"</option>"
                    $("#city-list").append(opt);
                }
            }else{
                alert("City Information Loading Failed")
            }
        }
    });

});


/**
			 * Provincial drop-down list data display
			 */
function showProvinceList(){
    $.ajax({
        url: "/districts",
        type: "POST",
        data: "parent=86",
        dataType: "JSON",
        success: function (json) {
            if (json.state == 200){
                let list = json.data;
                for (let i = 0; i < list.length; i++) {
                    let opt = "<option value='"+list[i].code+"'>"+list[i].name+"</option>"
                    $("#province-list").append(opt);
                }
            }else{
                alert("province/Municipality Information Loading Failed")
            }
        }
    });
}


//1. Listen for the registration button to be clicked, if clicked you can execute a method
$("#btn-add-new-address").click(function () {
    //2. Send ajax
    $.ajax({
        url: "/address/add_new_address",
        type: "POST",
        data: $("#form-add-new-address").serialize(),
        dataType: "JSON",
        success: function (json) {
            if (json.state == 200){
                alert("New Receipt Address Succeeded")
                console.log(json)
            }else{
                alert("Failed to add new receipt address")
            }
        },
        error: function (xhr) {
            alert("Unknown error when adding new receipt address" + xhr.status)
        }
    });
});
</script>

Topics: Spring Boot