[SpringBoot imitation niuke.com] 03. Develop the registration function

Keywords: Java Spring Boot

Complex functions should be disassembled into relatively simple functions, which is easy to develop
web projects can split functionality on request

Click the registration button to jump to the registration page, which is a request;
Submit the registration information to the server, and the server will send an activation email, which is a request;
Click the link in the activation email, and the server will change the user's status to activated. This is a request

Each request is developed according to the data access layer, business layer and view layer
Some requests do not have a complete three-tier

1 visit the registration page


Now the links of the home page and the registration button are static links. First change them into dynamic links


The web pages in templates cannot be accessed directly, but can only be accessed by Controller
Since the Controller method has been written on the home page, you can click it now. The registration has not been written yet. Click it

Now write the registered Controller method

1.1 Controller

To develop the registration function, use a Controller again

    //Visit the registration page
    @RequestMapping(path = "/register",method = RequestMethod.GET)
    public String getRegister(){
        return "/site/register";
    }

Note: the path in the second line is the URL of the registration page, which should be consistent with the URL in the engine template
The URL in the fourth line is the pathname of the dynamic page in the returned templates

1.2 dynamic page

Change the site/register.html under templates to a dynamic page

1.2.1 processing static resources from beginning to end


1.2.2 handling the head

The head in the head
index.html

register.html

2 submit registration data

2.1 data access layer

Provides methods for inserting users and modifying user status

2.2 business layer

1. Return various error messages
2. Registered user
3. Send activation email

coding...
[SpringBoot learning] 01. Send email to SpringBoot
[SpringBoot learning] 02. Encrypt the password with MD5

//Register user and send activation email
    public Map<String,Object> register(User user){
        //The error information is encapsulated by map
        Map<String, Object> map = new HashMap<>();
        //Null value judgment
        if(user==null){
            throw new IllegalArgumentException("User cannot be empty!");
        }
        if(StringUtils.isBlank(user.getUsername())){
            map.put("usernameMsg","User name cannot be empty!");
            return map;
        }
        if(StringUtils.isBlank(user.getPassword())){
            map.put("passwordMsg","Password cannot be empty!");
            return map;
        }
        if(StringUtils.isBlank(user.getEmail())){
            map.put("emailMsg","Mailbox cannot be empty!");
            return map;
        }
        //Verify user name
        User u = userMapper.selectByName(user.getUsername());
        if(u!=null){
            map.put("usernameMsg","The user name already exists!");
            return map;
        }
        //Verify mailbox
        u=userMapper.selectByEmail(user.getEmail());
        if(u!=null){
            map.put("emailMsg","This mailbox has been registered!");
            return map;
        }

        //Registered user
        user.setSalt(CommunityUtil.generateUUID().substring(0,5));
        user.setPassword(CommunityUtil.md5(user.getPassword()+user.getSalt()));
        user.setType(0);
        user.setStatus(0);
        user.setActivationCode(CommunityUtil.generateUUID());
        user.setHeaderUrl(String.format("http://images.nowcoder.com/head/%dt.png", new Random().nextInt(1000)));
        user.setCreateTime(new Date());

        userMapper.insertUser(user);

        //Send activation email
        Context context = new Context();
        context.setVariable("email",user.getEmail());
        // http://localhost:8080/community/activation/id/code
        String url = domain + contextPath + "/activation/" + user.getId() + "/" + user.getActivationCode();
        context.setVariable("url", url);
        String content = templateEngine.process("/mail/activation", context);
        mailClient.sendMail(user.getEmail(), "Activate account", content);


        return map;
    }

2.3 modify email to dynamic template

2.4 viewing layer

//Receive registration data and send activation email
    @RequestMapping(path = "/register",method = RequestMethod.POST)
    public String register(User user, Model model){
        Map<String,Object> map = userService.register(user);
        //no problem
        if(map.isEmpty()||map==null){
            model.addAttribute("Msg","Registration is successful. We have sent an activation email to your email. Please go to activate as soon as possible!");
            model.addAttribute("target","/index");
            return "site/operate-result";
        }
        //something the matter
        else{
            model.addAttribute("usernameMsg",map.get("usernameMsg"));
            model.addAttribute("passwordMsg",map.get("passwordMsg"));
            model.addAttribute("emailMsg",map.get("emailMsg"));
            return "site/register";
        }
    }

2.5 dynamic formwork

The pages returned by the view layer should be changed to static templates

2.5.1 site/operate-result.html


2.5.2 site/register.html

action: when submitting a form, the destination of sending form data is / register, which will be processed by the Controller method whose address is mapped to / register

method="post" th:action="@{/register}"

The front end passes the value to the back end

The question that puzzles me for a long time: how can the data submitted by the front end in form be encapsulated into classes and passed to the back end?
My guess is:

After the request is submitted, the DispatcherServlet is passed to the corresponding Controller method. The input parameters of this method include User. Then match the attributes of User class from the data submitted by the form, encapsulate the data into User class, and then pass it to the Controller method
This needs to see the source code to confirm
It is certain that the name value on the front end is consistent with the input parameter of the Controller method, and the dispatcher servlet will assign it to the value of the corresponding input parameter

The back end passes the value to the front end

1. html page

2. Pass JSON string

3 activate registered account

After clicking the activation link, the server will change the user's status from 0 to 1

3.1 data access layer

It provides the function of modifying status according to user id

3.2 business layer

Provide the method to activate the user: if the incoming activation code is consistent with the activation code in the database, the activation is successful
Put the state constant in the interface and use the class of the state constant to inherit the interface

    //Activate user
    public int activation(int userId,String code){
        User user = userMapper.selectById(userId);
        if(user.getStatus()==1)
            return ACTIVATION_REPEAT;
        else{
            if(user.getActivationCode().equals(code)){
                userMapper.updateStatus(userId, 1);
                return ACTIVATION_SUCCESS;
            }
            else
                return ACTIVATION_FAIL;
        }
    }

3.3 viewing layer

//Activate user
    // http://localhost:8080/community/activation/id/code
    @RequestMapping(path = "/activation/{userId}/{activationCode}",method = RequestMethod.GET)
    public String activation(Model model,@PathVariable("userId")int userId,@PathVariable("activationCode")String code){
        int result = userService.activation(userId, code);
        if(result==ACTIVATION_REPEAT){
            model.addAttribute("Msg","Invalid operation. You have activated this account and do not need to reactivate it.");
            model.addAttribute("target", "/index");
        }else if(result==ACTIVATION_SUCCESS){
            model.addAttribute("Msg","Activation succeeded,Your account can be used normally!");
            model.addAttribute("target", "/login");
        }else{
            model.addAttribute("Msg","Activation failed,The activation code you provided is incorrect!");
            model.addAttribute("target", "/index");
        }
        return "/site/operate-result";
    }

3.4 dynamic pages involved in the view layer

4 test

Well, why can't you request server data asynchronously.....
talk later

Some bugs have been changed. Another bug is how to asynchronously display whether the account has been registered or not?
Oh, the teacher didn't realize asynchronous display originally. I'll think about how to display it

Posted by chocopi on Mon, 22 Nov 2021 05:17:32 -0800