The user can register an account to carry on the goods purchase operation.

Create User Table in the Database

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
-- Create a table called user, it contains the following fields:
CREATE TABLE user (
  `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
  `created_at` INT(11) NOT NULL,
  `updated_at` INT(11) NOT NULL,
  `last_logged_on` INT(11) NOT NULL,
  `first_name` VARCHAR(50) NOT NULL,
  `last_name` VARCHAR(50) NOT NULL,
  `phone` VARCHAR(50) NOT NULL DEFAULT '',
  `email` VARCHAR(90) NOT NULL DEFAULT '',
  `password` VARCHAR(60) NOT NULL,    -- BCrypt Encryption
  `type` TINYINT(1) NOT NULL DEFAULT 1,    -- 1: Consumer, 2: Merchant
  `is_enabled` TINYINT(1) NOT NULL DEFAULT 0,
  `avatar` VARCHAR(512) NOT NULL DEFAULT '',
  `introduction` VARCHAR(512) NOT NULL DEFAULT '',
  `reference_id` BIGINT NOT NULL DEFAULT 0,
  PRIMARY KEY (`id`),
  UNIQUE KEY `index_email` (`email`)
);

Add Dependencies

Add Dependencies into Common Module

Copy and paste the following content into the pom.xml file under the common directory:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.9</version>
        </dependency>
        <dependency>
            <groupId>commons-beanutils</groupId>
            <artifactId>commons-beanutils</artifactId>
            <version>1.9.3</version>
        </dependency>

Add Dependency into Service Module

Copy and paste the following content into the pom.xml file under the service directory:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
            <version>2.1.4.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-mail</artifactId>
            <version>2.1.4.RELEASE</version>
        </dependency>

Add Configurations

Add the following content into application.properties file under the controller/src/main/resources directory:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
file.path=C:\\Users\\Dong\\Desktop\\java_shop_img
spring.servlet.multipart.max-file-size=10MB
spring.servlet.multipart.max-request-size=10MB
domain.name=http://127.0.0.1:8080
# Gmail Account
spring.mail.host=smtp.gmail.com
spring.mail.port=587
spring.mail.username=your_gmail_account
spring.mail.password=your_gmail_password
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.connectiontimeout=5000
spring.mail.properties.mail.smtp.timeout=5000
spring.mail.properties.mail.smtp.writetimeout=5000
spring.mail.properties.mail.smtp.starttls.enable=true

Gmail Settings

You have to turn the following setting in your google account first before trying the user registration function:

img

Create ResultMsg Model

  • Right click common/src/main/java directory: New > Package
  • Fill in “co.dongchen.shop.common.result”
  • Click “OK” button
img
  • Right click common/src/main/java/co.dongchen.shop.common/result directory: New > Java Class
  • Fill in “ResultMsg”
  • Click “OK” button
img

Copy and paste the following content into ResultMsg.java:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
package co.dongchen.shop.common.result;

import com.google.common.base.Joiner;
import com.google.common.collect.Maps;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Map;

public class ResultMsg {

    public static final String ERROR_MSG_KEY = "errorMsg";
    public static final String SUCCESS_MSG_KEY = "successMsg";

    private String errorMsg;
    private String successMsg;

    public boolean isSuccess(){
        return errorMsg == null;
    }

    public String getErrorMsg() {
        return errorMsg;
    }

    public void setErrorMsg(String errorMsg) {
        this.errorMsg = errorMsg;
    }

    public String getSuccessMsg() {
        return successMsg;
    }

    public void setSuccessMsg(String successMsg) {
        this.successMsg = successMsg;
    }

    public static ResultMsg errorMsg(String msg) {
        ResultMsg resultMsg = new ResultMsg();
        resultMsg.setErrorMsg(msg);
        return resultMsg;
    }

    public static ResultMsg successMsg(String msg) {
        ResultMsg resultMsg = new ResultMsg();
        resultMsg.setSuccessMsg(msg);
        return resultMsg;
    }

    public Map<String, String> asMap() {
        Map<String, String> map = Maps.newHashMap();
        map.put(SUCCESS_MSG_KEY, successMsg);
        map.put(ERROR_MSG_KEY, errorMsg);
        return map;
    }

    public String asUrlParams(){
        Map<String, String> map = asMap();
        Map<String, String> newMap = Maps.newHashMap();
        map.forEach((k,v) -> {if(v!=null)
            try {
                newMap.put(k, URLEncoder.encode(v,"utf-8"));
            } catch (UnsupportedEncodingException e) {}});
        return Joiner.on("&").useForNull("").withKeyValueSeparator("=").join(newMap);
    }
}

Create User Model

  • Right click common/src/main/java/co.dongchen.shop.common/model directory: New > Java Class
  • Fill in “User”
  • Click “OK” button
img

Copy and paste the following content into User.java:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
package co.dongchen.shop.common.model;

import org.springframework.web.multipart.MultipartFile;

public class User {

    private Long id;
    private Integer createdAt;
    private Integer updatedAt;
    private Integer lastLoggedOn;
    private String firstName;
    private String lastName;
    private String phone;
    private String email;
    private String password;
    private String newPassword;
    private String confirmedPassword;
    private Integer type;
    private Integer isEnabled;
    private String avatar;
    private String introduction;
    private MultipartFile avatarFile;
    private Long referenceId;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public Integer getCreatedAt() {
        return createdAt;
    }

    public void setCreatedAt(Integer createdAt) {
        this.createdAt = createdAt;
    }

    public Integer getUpdatedAt() {
        return updatedAt;
    }

    public void setUpdatedAt(Integer updatedAt) {
        this.updatedAt = updatedAt;
    }

    public Integer getLastLoggedOn() {
        return lastLoggedOn;
    }

    public void setLastLoggedOn(Integer lastLoggedOn) {
        this.lastLoggedOn = lastLoggedOn;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getNewPassword() {
        return newPassword;
    }

    public void setNewPassword(String newPassword) {
        this.newPassword = newPassword;
    }

    public String getConfirmedPassword() {
        return confirmedPassword;
    }

    public void setConfirmedPassword(String confirmedPassword) {
        this.confirmedPassword = confirmedPassword;
    }

    public Integer getType() {
        return type;
    }

    public void setType(Integer type) {
        this.type = type;
    }

    public Integer getIsEnabled() {
        return isEnabled;
    }

    public void setIsEnabled(Integer isEnabled) {
        this.isEnabled = isEnabled;
    }

    public String getAvatar() {
        return avatar;
    }

    public void setAvatar(String avatar) {
        this.avatar = avatar;
    }

    public String getIntroduction() {
        return introduction;
    }

    public void setIntroduction(String introduction) {
        this.introduction = introduction;
    }

    public MultipartFile getAvatarFile() {
        return avatarFile;
    }

    public void setAvatarFile(MultipartFile avatarFile) {
        this.avatarFile = avatarFile;
    }

    public Long getReferenceId() {
        return referenceId;
    }

    public void setReferenceId(Long referenceId) {
        this.referenceId = referenceId;
    }
}

Create User Helper

  • Right click common/src/main/java directory: New > Package
  • Fill in “co.dongchen.shop.common.util”
  • Click “OK” button
img
  • Right click util directory: New > Java Class
  • Fill in “UserHelper”
  • Click “OK” button
img

Copy and paste the following content into UserHelper.java:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package co.dongchen.shop.common.util;

import co.dongchen.shop.common.model.User;
import co.dongchen.shop.common.result.ResultMsg;
import org.apache.commons.lang3.StringUtils;


public class UserHelper {

    public static ResultMsg validate(User user) {

        // If the password is empty
        if (StringUtils.isBlank(user.getEmail())) {
            return ResultMsg.errorMsg("Email is needed");
        } else if (
                // If the password is empty
                StringUtils.isBlank(user.getPassword()) ||
                // If the confirmed password
                StringUtils.isBlank(user.getConfirmedPassword()) ||
                // If the password and the confirmed password is not matched
                ! user.getPassword().equals(user.getConfirmedPassword())
        ) {
            return ResultMsg.errorMsg("Password and confirmed password is not matched");
        // If the password is less than 6 characters
        } else if (user.getPassword().length() < 6) {
            return ResultMsg.errorMsg("Password must consist of 6 or more characters");
        }
        // If the validation is succeeded then return an empty string instead
        return ResultMsg.successMsg("");
    }
}

Create Bean Helper

  • Right click util directory: New > Java Class
  • Fill in “BeanHelper”
  • Click “OK” button
img
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
package co.dongchen.shop.common.util;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.PropertyUtils;

import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.time.Instant;

public class BeanHelper {

    private static final String createdAtKey  = "createdAt";
    private static final String lastLoggedOnKey  = "lastLoggedOn";
    private static final String updatedAtKey  = "updatedAt";

    public static <T> void setDefaultProp(T target,Class<T> clazz) {
        PropertyDescriptor[] descriptors = PropertyUtils.getPropertyDescriptors(clazz);
        for (PropertyDescriptor propertyDescriptor : descriptors) {
            String fieldName = propertyDescriptor.getName();
            Object value;
            try {
                value = PropertyUtils.getProperty(target,fieldName );
            } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
                throw new RuntimeException("can not set property  when get for "+ target +" and clazz "+clazz +" field "+ fieldName);
            }
            if (String.class.isAssignableFrom(propertyDescriptor.getPropertyType()) && value == null) {
                try {
                    PropertyUtils.setProperty(target, fieldName, "");
                } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
                    throw new RuntimeException("can not set property when set for "+ target +" and clazz "+clazz + " field "+ fieldName);
                }
            }else if (Number.class.isAssignableFrom(propertyDescriptor.getPropertyType()) && value == null) {
                try {
                    BeanUtils.setProperty(target, fieldName, "0");
                } catch (Exception e) {
                    throw new RuntimeException("can not set property when set for "+ target +" and clazz "+clazz + " field "+ fieldName);
                }
            }
        }
    }

    public static <T> void onUpdate(T target){
        try {
            PropertyUtils.setProperty(target, updatedAtKey, Math.toIntExact(Instant.now().getEpochSecond()));
        } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {

        }
    }

    public static <T> void onInsert(T target){
        long timestampLong = Instant.now().getEpochSecond();
        int timestamp = Math.toIntExact(timestampLong);
        try {
            PropertyUtils.setProperty(target, createdAtKey, timestamp);
            PropertyUtils.setProperty(target, lastLoggedOnKey, timestamp);
            PropertyUtils.setProperty(target, updatedAtKey, timestamp);
        } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {

        }
    }
}

Create User Mapper

User Mapper Class

  • Right click service/src/main/java/co.dongchen.shop/mapper directory: New > Java Class
  • Fill in “UserMapper”
  • Change Kind to: Interface
  • Click “OK” button
img

Copy and paste the following content into UserService.java:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
package co.dongchen.shop.mapper;

import co.dongchen.shop.common.model.User;
import org.apache.ibatis.annotations.Mapper;

import java.util.List;

@Mapper
public interface UserMapper {

    List<User> queryUsers();

    int insert(User user);

    int delete(String email);

    int update(User user);

    List<User> queryUsersByCondition(User user);

}

User Mapper XML

  • Right click service/src/main/resources/mapper directory: New > File
  • Fill in “user.xml”
  • Click “OK” button
img

Copy and paste the following content into user.xml:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
<?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="co.dongchen.shop.mapper.UserMapper">

    <select id="queryUsers" resultType="user">
        select first_name, last_name, phone, email, type, created_at from product
    </select>

    <select id="queryUsersByCondition" resultType="user">
        select * from user
        <where>
            <if test="id !=null" >
                and id = #{id}
            </if>
            <if test="email != null">
                and email = #{email}
            </if>
            <if test="isEnabled != null">
                and is_enabled = #{isEnabled}
            </if>
            <if test = "type != null and type!=0">
                and type = #{type}
            </if>
        </where>
    </select>

    <insert id="insert">
        insert into user(
            first_name, last_name, phone, email, password, type, created_at, updated_at, last_logged_on, is_enabled, avatar, introduction, reference_id
        ) values (
            #{firstName}, #{lastName}, #{phone}, #{email}, #{password}, #{type}, #{createdAt}, #{updatedAt}, #{lastLoggedOn}, #{isEnabled}, #{avatar}, #{introduction}, #{referenceId}
        )
    </insert>

    <delete id="delete">
        delete from user where email = #{email}
    </delete>

    <update id="update">
        update user
            <set>
                <if test="firstName != null and firstName != ''">
                    first_name = #{firstName},
                </if>
                <if test="lastName != null and lastName != ''">
                    last_name = #{lastName},
                </if>
                <if test="email != null and email != ''">
                    email = #{email},
                </if>
                <if test="phone != null and phone != ''">
                    phone = #{phone},
                </if>
                <if test="password != null and password != ''">
                    password = #{password},
                </if>
                <if test="updatedAt != null and updatedAt != ''">
                    updated_at = #{updatedAt},
                </if>
                <if test="lastLoggedOn != null and lastLoggedOn != ''">
                    last_logged_on = #{lastLoggedOn},
                </if>
                <if test="isEnabled != null and isEnabled != ''">
                    is_enabled = #{isEnabled},
                </if>
                <if test="avatar != null and avatar != ''">
                    avatar = #{avatar},
                </if>
                <if test="introduction != null and introduction != ''">
                    introduction = #{introduction},
                </if>
            </set>
        where email = #{email}
    </update>

</mapper>

Mybatis Config XML

Copy and paste the following content into mybatis-config.xml file under the service/src/main/resources/mybatis directory:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <settings>
        <!-- Disable Caches  -->
        <setting name="cacheEnabled" value="false"/>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
        <setting name="useGeneratedKeys" value="true"/>
        <setting name="defaultExecutorType" value="REUSE"/>
        <!-- Transaction Timeout -->
        <setting name="defaultStatementTimeout" value="600"/>
    </settings>

    <typeAliases>
        <typeAlias type="co.dongchen.shop.common.model.Product" alias="product" />
        <typeAlias type="co.dongchen.shop.common.model.User" alias="user" />

    </typeAliases>

    <mappers>
        <mapper resource="mapper/product.xml" />
        <mapper resource="mapper/user.xml" />
    </mappers>

</configuration>

Create Security Config

  • Right click service/src/main/java/co.dongchen.shop/config directory: New > Java Class
  • Fill in “SecurityConfig”
  • Click “OK” button
img

Copy and paste the following content into SecurityConfig.java:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package co.dongchen.shop.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/**")
                .permitAll()
                .anyRequest()
                .authenticated()
                .and().csrf().disable();
        super.configure(http);
    }

    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

Create Services

Create File Service

  • Right click service/src/main/java/co.dongchen.shop/service directory: New > Java Class
  • Fill in “FileService”
  • Click “OK” button
img

Copy and paste the following content into FileService.java:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package co.dongchen.shop.service;

import com.google.common.collect.Lists;
import com.google.common.io.Files;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.time.Instant;
import java.util.List;

@Service
public class FileService {

    @Value("${file.path}")
    private String filePath;

    public List<String> getImgPath(List<MultipartFile> files) {
        List<String> paths = Lists.newArrayList();
        files.forEach(file -> {
            File localFile;
            if (!file.isEmpty()) {
                try {
                    localFile = saveToLocal(file, filePath);
                    String path = StringUtils.substringAfterLast(localFile.getAbsolutePath(), filePath);
                    paths.add(path);
                } catch (Exception e) {
                    throw new IllegalArgumentException(e);
                }
            }
        });
        return paths;
    }

    private File saveToLocal(MultipartFile file, String filePath) throws IOException {
        File newFile = new File(filePath + File.separator + Instant.now().getEpochSecond() + File.separator + file.getOriginalFilename());
        if (!newFile.exists()) {
            newFile.getParentFile().mkdirs();
            newFile.createNewFile();
        }
        Files.write(file.getBytes(), newFile);
        return newFile;
    }
}

Create Mail Service

  • Right click service/src/main/java/co.dongchen.shop/service directory: New > Java Class
  • Fill in “MailService”
  • Click “OK” button
img

Copy and paste the following content into MailService.java:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
package co.dongchen.shop.service;

import co.dongchen.shop.common.model.User;
import co.dongchen.shop.mapper.UserMapper;
import com.google.common.base.Objects;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.RemovalListener;
import com.google.common.cache.RemovalNotification;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
public class MailService {

    private final Cache<String, String> emailCache = CacheBuilder.newBuilder().maximumSize(100)
            .expireAfterAccess(15, TimeUnit.MINUTES)
            .removalListener(new RemovalListener<String, String>() {
                @Override
                public void onRemoval(RemovalNotification<String, String> removalNotification) {
                    String email = removalNotification.getValue();
                    User user = new User();
                    user.setEmail(email);
                    List<User> targetUser = userMapper.queryUsersByCondition(user);
                    // Only removes the inactivated users.
                    if (!targetUser.isEmpty() && Objects.equal(targetUser.get(0).getIsEnabled(), 0)) {
                        userMapper.delete(email);
                    }
                }
            }).build();

    @Value("${domain.name}")
    private String domainName;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private JavaMailSender sender;

    public void sendMail(String title, String body, String email) {
        SimpleMailMessage message = new SimpleMailMessage();
        message.setSubject(title);
        message.setTo(email);
        message.setText(body);
        sender.send(message);
    }

    @Async
    public void registerNotification(String email) {
        String randomKey = RandomStringUtils.randomAlphabetic(10);
        emailCache.put(randomKey, email);
        String url = domainName + "/user/activate?key=" + randomKey;
        sendMail("Welcome to our shop, just one more step...", url, email);
    }

    public boolean enable(String key) {
        String email = emailCache.getIfPresent(key);
        if (StringUtils.isBlank(email)) {
            return false;
        }
        User updateUser = new User();
        updateUser.setEmail(email);
        updateUser.setIsEnabled(1);
        userMapper.update(updateUser);
        emailCache.invalidate(key);
        return true;
    }
}

Create User Service

  • Right click service/src/main/java/co.dongchen.shop/service directory: New > Java Class
  • Fill in “UserService”
  • Click “OK” button
img

Copy and paste the following content into UserService.java:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
package co.dongchen.shop.service;

import co.dongchen.shop.common.model.User;
import co.dongchen.shop.common.util.BeanHelper;
import co.dongchen.shop.mapper.UserMapper;
import com.google.common.collect.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
public class UserService {

    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    @Autowired
    private MailService mailService;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private FileService fileService;

    public List<User> getUsers() {
        return userMapper.queryUsers();
    }

    @Transactional(rollbackFor = Exception.class)
    public boolean register(User user) {
        user.setPassword(bCryptPasswordEncoder.encode(user.getPassword()));
        List<String> imgs = fileService.getImgPath(Lists.newArrayList(user.getAvatarFile()));
        if ( ! imgs.isEmpty() ) {
            user.setAvatar(imgs.get(0));
        }
        BeanHelper.setDefaultProp(user, User.class);
        BeanHelper.onInsert(user);
        user.setIsEnabled(0);
        user.setType(1);
        userMapper.insert(user);
        mailService.registerNotification(user.getEmail());
        return true;
    }

    public boolean enable(String key) {
        return mailService.enable(key);
    }
}

Update ShopApplication Controller

Copy and paste the following content into ShopApplication.java file under the controller/src/main/co.dongchen.shop directory:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
package co.dongchen.shop;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;

@SpringBootApplication()
@EnableAsync
@EnableWebSecurity
public class ShopApplication {

	public static void main(String[] args) {
		SpringApplication.run(ShopApplication.class, args);
	}
}

Create User Controller

  • Right click controller/src/main/java/co.dongchen.shop/controller directory: New > Java Class
  • Fill in “UserController”
  • Click “OK” button
img

Copy and paste the following content into UserController.java:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
package co.dongchen.shop.controller;

import co.dongchen.shop.common.model.User;
import co.dongchen.shop.common.result.ResultMsg;
import co.dongchen.shop.common.util.UserHelper;
import co.dongchen.shop.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class UserController {

    @Autowired
    private UserService userService;

    @RequestMapping("user/register")
    public String register(User user, ModelMap modelMap) {
        if (user == null || user.getFirstName() == null || user.getLastName() == null) {
            return "/user/register";
        }

        ResultMsg resultMsg = UserHelper.validate(user);
        if (resultMsg.isSuccess() && userService.register(user)) {
            modelMap.put("email", user.getEmail());
            return "/user/registration_succeeded";
        } else {
            return "redirect:/user/register?" + resultMsg.asUrlParams();
        }
    }

    @RequestMapping("user/activate")
    public String activate(String key){
        boolean result =  userService.enable(key);
        if (result) {
            return "redirect:/home?" + ResultMsg.successMsg("Activation Completed!").asUrlParams();
        }else {
            return "redirect:/user/register?" + ResultMsg.errorMsg("Activation Failed, please make sure to activate the email in 15 minutes").asUrlParams();
        }
    }
}

Create Template

  • Right click controller/src/main/resources/template directory: New > Directory
  • Fill in “user”
  • Click “OK” button
img
  • Right click user directory: New > File
  • Fill in “register.ftl”
  • Click “OK” button
img

Copy and paste the following content into register.ftl:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<html lang="en-NZ">
<@common.header/>
<body>
<form method="post" enctype="multipart/form-data">
    <div>
        <label>First Name</label>
        <input type="text" name="firstName" required>
    </div>
    <div>
        <label>Last Name</label>
        <input type="text" name="lastName" required>
    </div>
    <div>
        <label>Email:</label>
        <input type="text" name="email" required>
    </div>
    <div>
        <label>Phone</label>
        <input type="text" name="phone" required>
    </div>
    <div>
        <label>Password</label>
        <input type="password" name="password" required>
    </div>
    <div>
        <label>Confirmed Password</label>
        <input type="password" name="confirmedPassword" required>
    </div>
    <div>
        <label>Avatar</label>
        <input type="file" accept="image/jpeg,image/png" name="avatarFile" required>
    </div>
    <div>
        <label>Introduction</label>
        <input type="text" name="introduction" required>
    </div>
    <div>
        <button type="submit">Register</button>
    </div>
</form>
</body>
<@common.footer/>
</html>
  • Right click user directory: New > File
  • Fill in “registration_succeeded.ftl”
  • Click “OK” button
img

Copy and paste the following content into registration_succeeded.ftl:

1
2
3
4
5
6
7
8
<html lang="en-NZ">
<@common.header/>
<body>
<h1>Registration Succeeded!</h1>
<p>We have sent an confirmation email and the activation linkage to your inbox (${email}), this link will be expired in 15 minutes, please have a check. Thanks!</p>
</body>
<@common.footer/>
</html>

Verify

Run the App

1
2
// Short Cut for "Run the Program"
Alt + Shift + F10
img

Choose the correspondent option and press enter.

View Register Page in the Browser

1
http://localhost:8080/user/register
img
  • Fill in the Information and click register:
img
  • We will see a registered succeeded page:
img
  • We can see an inactivate user in the database:
img
  • We need to click the activation link in 15 minutes:
img
  • We will see the following page and url after we clicked the link:
img
  • Check the database again
img

Now that the user has been activated, our job is done for now.

References Package org.apache.commons.lang3, Commons BeanUtils, Interface JavaMailSender, Spring Security,

Buy me a coffeeBuy me a coffee