Single Java application - project combat (background) - Account Management Background 03. - 03. New Account

Original Address: http://www.work100.net/training/monolithic-project-iot-cloud-admin-manager-add.html
More Tutorials: beam cloud - free course

New Account

No. Article section video
1 Outline -
2 The back-end code implementation -
3 Achieve front page -
4 Testing and certification -
5 Use the form tag library -
6 Use Form Validation -
7 Source code examples -

Please refer above 章节导航to read

1 Overview

This section realization 新增账户function, page effect is as follows:

2. The back-end code implementation

To reduce the coupling, we suggest that you 新增, 编辑, 查看function encoded separately, not mixed in one method.

We now demonstrate the function is relatively simple, but the real business function will become very complicated, if the code is mixed together, then the code complexity will grow exponentially.

Next, we gradually reconstructed ManagerControllerclass.

GET method

@RequestMapping(value = "add", method = RequestMethod.GET)
public String add() {
    return "auth/manager_add";
}

POST method

@RequestMapping(value = "add", method = RequestMethod.POST)
public String add(AuthManager authManager, Model model, RedirectAttributes redirectAttributes) {
    // 表单验证
    if (StringUtils.isBlank(authManager.getUserName())) {
        model.addAttribute("baseResult", BaseResult.fail("用户名不能空"));
        model.addAttribute("authManager", authManager);
        return "auth/manager_add";
    }
    if (authManager.getUserName().length() < 4 || authManager.getUserName().length() > 20) {
        model.addAttribute("baseResult", BaseResult.fail("用户名不能小于4位且不能大于20位"));
        model.addAttribute("authManager", authManager);
        return "auth/manager_add";
    }
    if (StringUtils.isBlank(authManager.getPassword())) {
        model.addAttribute("baseResult", BaseResult.fail("密码不能空且不能少于"));
        model.addAttribute("authManager", authManager);
        return "auth/manager_add";
    }
    if (authManager.getPassword().length() < 6 || authManager.getUserName().length() > 20) {
        model.addAttribute("baseResult", BaseResult.fail("密码不能小于6个位且不能大于20位"));
        model.addAttribute("authManager", authManager);
        return "auth/manager_add";
    }
    if (StringUtils.isBlank(authManager.getRoles())) {
        model.addAttribute("baseResult", BaseResult.fail("角色不能空"));
        model.addAttribute("authManager", authManager);
        return "auth/manager_add";
    }

    // 新增处理
    BaseResult baseResult = authManagerService.insert(authManager);
    if (baseResult.getStatus() == HttpUtils.HTTP_STATUS_CODE_OK) {
        redirectAttributes.addFlashAttribute("baseResult", baseResult);
        return "redirect:/auth/manager/list";
    } else {
        model.addAttribute("baseResult", baseResult);
        return "auth/manager_add";
    }
}

Description :

  • Backend must submit data to verify the legitimacy of the front end, in order to ensure data security

  • The method used BaseResultand HttpUtilstwo classes, the following were introduced

BaseResult class

In order to more convenient operation result is transmitted to the front page, we introduce a generic BaseResultclass, as follows:

package net.work100.training.stage2.iot.cloud.commons.dto;

import net.work100.training.stage2.iot.cloud.commons.utils.HttpUtils;

import java.io.Serializable;

/**
 * <p>Title: BaseResult</p>
 * <p>Description: </p>
 *
 * @author liuxiaojun
 * @date 2020-03-04 11:02
 * ------------------- History -------------------
 * <date>      <author>       <desc>
 * 2020-03-04   liuxiaojun     初始创建
 * -----------------------------------------------
 */
public class BaseResult implements Serializable {
    private int status;
    private String message;


    public static BaseResult success() {
        return createResult(HttpUtils.HTTP_STATUS_CODE_OK, "成功");
    }

    public static BaseResult success(String message) {
        return createResult(HttpUtils.HTTP_STATUS_CODE_OK, message);
    }

    public static BaseResult fail() {
        return createResult(HttpUtils.HTTP_STATUS_CODE_INTERNAL_SERVER_ERROR, "失败");
    }

    public static BaseResult fail(String message) {
        return createResult(HttpUtils.HTTP_STATUS_CODE_INTERNAL_SERVER_ERROR, message);
    }

    public static BaseResult fail(int status, String message) {
        return createResult(status, message);
    }

    public int getStatus() {
        return status;
    }

    public void setStatus(int status) {
        this.status = status;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    private static BaseResult createResult(int status, String message) {
        BaseResult baseResult = new BaseResult();
        baseResult.setStatus(status);
        baseResult.setMessage(message);
        return baseResult;
    }
}

Class file location iot-cloud-commonsin the project net.work100.training.stage2.iot.cloud.commons.dtounder the class package.

HttpUtils class

To BaseResultreturn a status code configured generic class HttpUtils, as follows:

package net.work100.training.stage2.iot.cloud.commons.utils;

/**
 * <p>Title: Http状态码</p>
 * <p>Description: </p>
 * <p>Url: http://www.work100.net/training/monolithic-project-iot-cloud-admin.html</p>
 *
 * @author liuxiaojun
 * @date 2019-07-14 20:51
 * ------------------- History -------------------
 * <date>      <author>       <desc>
 * 2019-07-14   liuxiaojun     初始创建
 * -----------------------------------------------
 */
public class HttpUtils {

    public static final int HTTP_STATUS_CODE_CONTINUE = 100;
    public static final int HTTP_STATUS_CODE_SWITCHING_PROTOCOLS = 101;
    public static final int HTTP_STATUS_CODE_OK = 200;
    public static final int HTTP_STATUS_CODE_CREATED = 201;
    public static final int HTTP_STATUS_CODE_ACCEPTED = 202;
    public static final int HTTP_STATUS_CODE_NON_AUTHORITATIVE_INFORMATION = 203;
    public static final int HTTP_STATUS_CODE_NO_CONTENT = 204;
    public static final int HTTP_STATUS_CODE_RESET_CONTENT = 205;
    public static final int HTTP_STATUS_CODE_PARTIAL_CONTENT = 206;
    public static final int HTTP_STATUS_CODE_MULTIPLE_CHOICES = 300;
    public static final int HTTP_STATUS_CODE_MOVED_PERMANENTLY = 301;
    public static final int HTTP_STATUS_CODE_MOVED_TEMPORARILY = 302;
    public static final int HTTP_STATUS_CODE_FOUND = 302;
    public static final int HTTP_STATUS_CODE_SEE_OTHER = 303;
    public static final int HTTP_STATUS_CODE_NOT_MODIFIED = 304;
    public static final int HTTP_STATUS_CODE_USE_PROXY = 305;
    public static final int HTTP_STATUS_CODE_TEMPORARY_REDIRECT = 307;
    public static final int HTTP_STATUS_CODE_BAD_REQUEST = 400;
    public static final int HTTP_STATUS_CODE_UNAUTHORIZED = 401;
    public static final int HTTP_STATUS_CODE_PAYMENT_REQUIRED = 402;
    public static final int HTTP_STATUS_CODE_FORBIDDEN = 403;
    public static final int HTTP_STATUS_CODE_NOT_FOUND = 404;
    public static final int HTTP_STATUS_CODE_METHOD_NOT_ALLOWED = 405;
    public static final int HTTP_STATUS_CODE_NOT_ACCEPTABLE = 406;
    public static final int HTTP_STATUS_CODE_PROXY_AUTHENTICATION_REQUIRED = 407;
    public static final int HTTP_STATUS_CODE_REQUEST_TIMEOUT = 408;
    public static final int HTTP_STATUS_CODE_CONFLICT = 409;
    public static final int HTTP_STATUS_CODE_GONE = 410;
    public static final int HTTP_STATUS_CODE_LENGTH_REQUIRED = 411;
    public static final int HTTP_STATUS_CODE_PRECONDITION_FAILED = 412;
    public static final int HTTP_STATUS_CODE_REQUEST_ENTITY_TOO_LARGE = 413;
    public static final int HTTP_STATUS_CODE_REQUEST_URI_TOO_LONG = 414;
    public static final int HTTP_STATUS_CODE_UNSUPPORTED_MEDIA_TYPE = 415;
    public static final int HTTP_STATUS_CODE_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
    public static final int HTTP_STATUS_CODE_EXPECTATION_FAILED = 417;
    public static final int HTTP_STATUS_CODE_INTERNAL_SERVER_ERROR = 500;
    public static final int HTTP_STATUS_CODE_NOT_IMPLEMENTED = 501;
    public static final int HTTP_STATUS_CODE_BAD_GATEWAY = 502;
    public static final int HTTP_STATUS_CODE_SERVICE_UNAVAILABLE = 503;
    public static final int HTTP_STATUS_CODE_GATEWAY_TIMEOUT = 504;
    public static final int HTTP_STATUS_CODE_HTTP_VERSION_NOT_SUPPORTED = 505;
}

Class file location iot-cloud-commonsin the project net.work100.training.stage2.iot.cloud.commons.utilsunder the class package.

AuthManagerService service interface

Reconstruction of AuthManagerServicethe service interface insertas the following code:

/**
 * 新增
 *
 * @param authManager
 * @return
 */
BaseResult insert(AuthManager authManager);

AuthManagerServiceImpl service implementation

Reconstruction of AuthManagerServiceImplservice implementation insertmethod, the code is as follows:

@Override
public BaseResult insert(AuthManager authManager) {
    if (authManagerDao.getByUserName(authManager.getUserName()) != null) {
        return BaseResult.fail("用户名已经存在");
    }
    try {
        // 生成 userKey
        authManager.setUserKey(generateUserKey(authManager.getUserName()));

        // 密码加密
        authManager.setPassword(EncryptionUtils.encryptPassword(EncryptionUtils.EncryptionType.MD5, authManager.getPassword()));
        authManager.setCreated(new Date());
        authManager.setUpdated(new Date());

        authManagerDao.insert(authManager);
        return BaseResult.success("新增账户成功");
    } catch (Exception ex) {
        return BaseResult.fail("未知错误");
    }
}

New generateUserKeymethods to achieve userKeygeneration logic, as follows:

/**
 * 生成 userKey
 *
 * @param userName 用户名
 * @return
 */
private String generateUserKey(String userName) {
    String strDate = DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss");
    String sourceUserKey = String.format("%s%s", userName.toLowerCase(), strDate);
    return EncryptionUtils.encryptText(EncryptionUtils.EncryptionType.MD5, sourceUserKey);
}

3. achieve front page

View file manager_add.jsp

In views/auth/adding a directory manager_add.jspview file, code is as follows:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
    <title>新增账户 - 后台账户 | IoT-Admin</title>
    <jsp:include page="../includes/resources_head.jsp" />
</head>
<body class="hold-transition sidebar-mini">
<div class="wrapper">

    <jsp:include page="../includes/layout_header.jsp" />

    <jsp:include page="../includes/layout_left.jsp" />

    <!-- Content Wrapper. Contains page content -->
    <div class="content-wrapper">
        <!-- Content Header (Page header) -->
        <div class="content-header">
            <div class="container-fluid">
                <div class="row mb-2">
                    <div class="col-sm-6">
                        <h1 class="m-0 text-dark">新增账户</h1>
                    </div><!-- /.col -->
                    <div class="col-sm-6">
                        <ol class="breadcrumb float-sm-right">
                            <li class="breadcrumb-item"><a href="#">后台账户</a></li>
                            <li class="breadcrumb-item active">新增账户</li>
                        </ol>
                    </div><!-- /.col -->
                </div><!-- /.row -->
            </div><!-- /.container-fluid -->
        </div>
        <!-- /.content-header -->

        <!-- Main content -->
        <div class="content">
            <div class="container-fluid">
                <div class="row">
                    <div class="col">
                        <div class="card card-gray">
                            <!-- /.card-header -->
                            <!-- form start -->
                            <form action="/auth/manager/add" method="post">
                                <div class="card-body">
                                    <div class="row">
                                        <div class="col-md-6">
                                            <div class="form-group">
                                                <label for="userName">用户名</label>
                                                <input type="text" class="form-control" id="userName" name="userName" placeholder="请输入用户名" value="${authManager.userName}">
                                            </div>
                                            <div class="form-group">
                                                <label for="password">密码</label>
                                                <input type="password" class="form-control" id="password" name="password" placeholder="请输入密码">
                                            </div>
                                            <div class="form-group">
                                                <label for="status">状态</label>
                                                <select class="form-control select2" style="width: 100%;" id="status" name="status">
                                                    <option value="0" selected="selected">未激活</option>
                                                    <option value="1">激活</option>
                                                    <option value="2">锁定</option>
                                                    <option value="3">删除</option>
                                                </select>
                                            </div>
                                        </div>
                                        <div class="col-md-6">
                                            <div class="form-group">
                                                <label for="roles">角色</label>
                                                <select class="select2" id="roles" name="roles" multiple="multiple" data-placeholder="请选择角色" style="width: 100%;">
                                                    <option value="admin" ${authManager.roles.contains("admin")?"selected":""}>admin</option>
                                                    <option value="editor" ${authManager.roles.contains("editor")?"selected":""}>editor</option>
                                                </select>
                                            </div>
                                            <div class="form-group">
                                                <label for="superuser">是否超级用户</label>
                                                <select class="form-control select2" id="superuser" name="superuser" style="width: 100%;">
                                                    <option value="0" selected="selected">否</option>
                                                    <option value="1">是</option>
                                                </select>
                                            </div>
                                        </div>
                                    </div>
                                </div>
                                <!-- /.card-body -->

                                <div class="card-footer">
                                    <button type="submit" class="btn btn-primary">保存</button>
                                    <a href="/auth/manager/list" type="button" class="btn btn-default">返回列表</a>
                                </div>
                            </form>
                        </div>
                        <!-- /.card -->
                    </div>
                </div>
            </div>
            <!-- /.container-fluid -->
        </div>
        <!-- /.content -->
    </div>
    <!-- /.content-wrapper -->

    <jsp:include page="../includes/layout_footer.jsp" />
</div>
<!-- ./wrapper -->
<jsp:include page="../includes/resources_body.jsp" />

<script>
$(function() {
    //Initialize Select2 Elements
    $('.select2').select2();

    //Initialize Select2 Elements
    $('.select2bs4').select2({
        theme: 'bootstrap4'
    });

    if (${baseResult.status != null && baseResult.status != 200}) {
        const Toast = Swal.mixin({
            toast: true,
            position: 'top',
            showConfirmButton: false,
            timer: 2000,
            timerProgressBar: true,
            onOpen: (toast) => {
                toast.addEventListener('mouseenter', Swal.stopTimer)
                toast.addEventListener('mouseleave', Swal.resumeTimer)
            }
        })

        Toast.fire({
            type: 'error',
            title: '${baseResult.message}'
        })
    }
})
</script>
</body>
</html>

Dependence script and controls

End of the file we added a paragraph JSscript:

The following code is to allow selectcontrol application Bootstrap4styles:

//Initialize Select2 Elements
$('.select2').select2();

//Initialize Select2 Elements
$('.select2bs4').select2({
    theme: 'bootstrap4'
});

The following code is an operation result to the message out to show more friendly to the user:

if (${baseResult.status != null && baseResult.status != 200}) {
    const Toast = Swal.mixin({
        toast: true,
        position: 'top',
        showConfirmButton: false,
        timer: 2000,
        timerProgressBar: true,
        onOpen: (toast) => {
            toast.addEventListener('mouseenter', Swal.stopTimer)
            toast.addEventListener('mouseleave', Swal.resumeTimer)
        }
    })

    Toast.fire({
        type: 'error',
        title: '${baseResult.message}'
    })
}

Page used in selectcontrols and prompts 消息depend on the relevant plug-in, which relies plug CSSand JSare in resources_head.jsand resources_body.jsthe introduction of:

resources_head.js code show as below:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<!-- Font Awesome Icons -->
<link rel="stylesheet" href="/static/assets/plugins/fontawesome-free/css/all.min.css">

<!-- iCheck for checkboxes and radio inputs -->
<link rel="stylesheet" href="/static/assets/plugins/icheck-bootstrap/icheck-bootstrap.min.css">

<!-- Select2 -->
<link rel="stylesheet" href="/static/assets/plugins/select2/css/select2.min.css">
<link rel="stylesheet" href="/static/assets/plugins/select2-bootstrap4-theme/select2-bootstrap4.min.css">

<!-- SweetAlert2 -->
<link rel="stylesheet" href="/static/assets/plugins/sweetalert2/sweetalert2.min.css">

<!-- Theme style -->
<link rel="stylesheet" href="/static/assets/css/adminlte.min.css">
<link rel="icon" href="/static/assets/img/favicon.ico">

resources_body.js code show as below:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!-- REQUIRED SCRIPTS -->

<!-- jQuery -->
<script src="/static/assets/plugins/jquery/jquery.min.js"></script>
<!-- Bootstrap -->
<script src="/static/assets/plugins/bootstrap/js/bootstrap.bundle.min.js"></script>
<!-- Select2 -->
<script src="/static/assets/plugins/select2/js/select2.full.min.js"></script>

<!-- SweetAlert2 -->
<script src="/static/assets/plugins/sweetalert2/sweetalert2.min.js"></script>

<!-- AdminLTE -->
<script src="/static/assets/js/adminlte.js"></script>

View file manager_list.jsp

View files manager_list.jspin the bodyadd message prompt end of the script:

<script>
$(function() {
    if (${baseResult.status != null && baseResult.status == 200}) {
        const Toast = Swal.mixin({
            toast: true,
            position: 'top',
            showConfirmButton: false,
            timer: 2000,
            timerProgressBar: true
        })

        Toast.fire({
            type: 'success',
            title: '${baseResult.message}'
        })
    }
})
</script>

4. Run the test

Restart Tomcattest 新增账户function, the following data validation prompt effect at the time of failure:

When successfully added an account, the list will turn the page and success prompted:

5. Use form tag library

In order to simplify the coding view of the page, we can use the " Spring MVC - form tag library " section of the knowledge about the reconstruction of page views.

The introduction of form tag library

In the manager_add.jspintroduction section view page header formtag library, as follows:

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>

Use the form tag

The transformation of formthe form, as follows:

<form:form action="/auth/manager/add" method="post" modelAttribute="authManager">
    <div class="card-body">
        <div class="row">
            <div class="col-md-6">
                <div class="form-group">
                    <label for="userName">用户名</label>
                    <form:input path="userName" cssClass="form-control" placeholder="请输入用户名" />
                </div>
                <div class="form-group">
                    <label for="password">密码</label>
                    <form:password path="password" cssClass="form-control" placeholder="请输入密码" />
                </div>
                <div class="form-group">
                    <label for="status">状态</label>
                    <form:select path="status" cssClass="form-control select2" style="width: 100%;">
                        <option value="0" selected="selected">未激活</option>
                        <option value="1">激活</option>
                        <option value="2">锁定</option>
                        <option value="3">删除</option>
                    </form:select>
                </div>
            </div>
            <div class="col-md-6">
                <div class="form-group">
                    <label for="roles">角色</label>
                    <form:select path="roles" cssClass="select2" multiple="multiple" data-placeholder="请选择角色" style="width: 100%;">
                        <option value="admin" ${authManager.roles.contains("admin")?"selected":""}>admin</option>
                        <option value="editor" ${authManager.roles.contains("editor")?"selected":""}>editor</option>
                    </form:select>
                </div>
                <div class="form-group">
                    <label for="superuser">是否超级用户</label>
                    <form:select path="superuser" cssClass="form-control select2" style="width: 100%;">
                        <option value="0" selected="selected">否</option>
                        <option value="1">是</option>
                    </form:select>
                </div>
            </div>
        </div>
    </div>
    <!-- /.card-body -->

    <div class="card-footer">
        <button type="submit" class="btn btn-primary">保存</button>
        <a href="/auth/manager/list" type="button" class="btn btn-default">返回列表</a>
    </div>
</form:form>

Transformation back-end code

Reconstruction ManagerControllercontroller GETmethod

@RequestMapping(value = "add", method = RequestMethod.GET)
public String add(Model model) {
    AuthManager authManager = new AuthManager();
    model.addAttribute("authManager", authManager);
    return "auth/manager_add";
}

6. Use Form Validation

Introducing jquery-validation

In includes/resources_body.jspintroducing the document jquery-validationplug-dependent code is as follows:

<!-- jquery-validation -->
<script src="/static/assets/plugins/jquery-validation/jquery.validate.min.js"></script>
<script src="/static/assets/plugins/jquery-validation/additional-methods.min.js"></script>
<script src="/static/assets/plugins/jquery-validation/localization/messages_zh.min.js"></script>

Custom Form id

Defined form id, as follows:

<form:form action="/auth/manager/add" id="form" method="post" modelAttribute="authManager">

Achieve validation script

In view page manager_add.jspfile bodywithin the script at the end, add the following code:

$("#form").validate({
    rules: {
        userName: {
            required: true,
            minlength: 4,
            maxlength: 20
        },
        password: {
            required: true,
            minlength: 6,
            maxlength: 20
        },
        roles: {
            required: true,
            minlength: 1,
            maxlength: 3
        }
    },
    messages: {
        userName: {
            required: " 请输入用户名",
            minlength: " 用户名不能小于4位",
            maxlength: " 用户名不能大于于20位"
        },
        password: {
            required: " 请输入密码",
            minlength: " 密码不能小于6位",
            maxlength: " 密码不能大于于20位"
        },
        roles: {
            required: " 请选择角色",
            minlength: " 至少选择1个角色",
            maxlength: " 至多选择3个角色"
        }
    },
    errorElement: 'span',
    errorPlacement: function(error, element) {
        error.addClass('invalid-feedback');
        element.closest('.form-group').children('label').append(error);
    },
    highlight: function(element, errorClass, validClass) {
        $(element).addClass('is-invalid');
    },
    unhighlight: function(element, errorClass, validClass) {
        $(element).removeClass('is-invalid');
    }
});

Form validation results are as follows:

Example 7. Source

Examples of the source has been managed to the following address:


Previous: Accounts list shows

Next: Edit Account


If you are interested in course content, our attention can sweep the yard 公众号or QQ群in a timely manner to our curriculum update

Guess you like

Origin www.cnblogs.com/liuxiaojun/p/training-monolithic-project-iot-cloud-admin-manager-add.html