Java单体应用 - 常用框架 - 05.综合实例(iot-admin)

原文地址:http://www.work100.net/training/monolithic-frameworks-example.html
更多教程:光束云 - 免费课程

综合实例

序号 文内章节 视频
1 概述 -
2 创建项目 -
3 使用AdminLTE模板 -
4 创建登录页 -
5 登录功能实现 -
6 提升用户体验 -
7 实例源码 -

请参照如上章节导航进行阅读

1.概述

本节将把「Java单体应用」课程做一个阶段性的总结,通过一个综合的案例将所学知识完整实践一下。

我们后续阶段的课程还有:

为了后续课程的连续性,我们的 综合实例 将搭建一个简单的 IoT管理后台 项目 iot-admin,实现用户的登录功能。

学习的过程要跟着练习并做好笔记!

2.创建项目

2.1.构建项目结构

创建项目文件夹

通过 IntelliJ IDEA 打开前述章节的项目结构,新增一个项目文件夹 iot-admin

创建 POM

添加一个 pom.xml 文件,文件内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>net.work100.training.stage2</groupId>
    <artifactId>iot-admin</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
        </dependency>      
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.25</version>
        </dependency>
    </dependencies>
</project>

然后将 pom.xml 托管到 Maven

完善Maven结构

完善下表的目录结构:

目录或文件 说明
pom.xml POM文件
src/main/java 源码文件夹
src/main/resources 资源文件夹
src/main/webapp 网站文件夹
src/main/webapp/WEB-INF 网站配置文件夹
src/main/webapp/WEB-INF/web.xml 网站配置文件
src/test/java 测试源码文件夹

项目结构如下图:

Java单体应用 - 常用框架 - 05.综合实例(iot-admin)

完善 src/main/webapp/WEB-INF/web.xml 文件,内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

</web-app>

完善项目架构

结合三层架构及MVC架构,在 src/main/java 下构建项目的类包结构,如下表:

类包 说明
net.work100.training.stage2.iot.admin 项目总的类包
net.work100.training.stage2.iot.admin.dao 数据访问层
net.work100.training.stage2.iot.admin.service 服务层
net.work100.training.stage2.iot.admin.web Web层

项目结构如下图:

Java单体应用 - 常用框架 - 05.综合实例(iot-admin)

配置 Spring 和 Log4j

src/main/resources 下添加 spring-context.xmllog4j.properties 文件:

spring-context.xml 代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

</beans>

log4j.properties 代码如下:

log4j.rootLogger=INFO, console, file

log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d %p [%c] - %m%n

log4j.appender.file=org.apache.log4j.DailyRollingFileAppender
log4j.appender.file.File=logs/log.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.A3.MaxFileSize=1024KB
log4j.appender.A3.MaxBackupIndex=10
log4j.appender.file.layout.ConversionPattern=%d %p [%c] - %m%n

构建前端框架结构

参照 Bootstrap - 环境搭建 - 实例 中的步骤构建 Bootstrap 的目录结构:

目录 说明
src/main/webapp/assets/ 静态资源文件目录
src/main/webapp/assets/css/ 自定义样式
src/main/webapp/assets/images/ 自定义图片
src/main/webapp/assets/js/ 自定义JS
src/main/webapp/assets/plugins/ 插件
src/main/webapp/assets/plugins/bootstrap/ Bootstrap插件
src/main/webapp/assets/plugins/bootstrap/css/ Bootstrap 样式表文件
src/main/webapp/assets/plugins/bootstrap/font-awesome/ 第三方字体
src/main/webapp/assets/plugins/bootstrap/js/ Bootstrap JS文件
src/main/webapp/assets/plugins/bootstrap/jquery-3.4.1.min.js jQuery

src/main/webapp 下新建 index.jsp 文件,代码如下:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>IoT-Admin</title>
</head>
<body>
    Hello IoT-Admin
</body>
</html>

项目结构如下图:

Java单体应用 - 常用框架 - 05.综合实例(iot-admin)

配置 Tomcat

参考 架构模式 - 实践练习 中所述的 Tomcat 配置方式将运行环境配好,并运行验证效果:

Java单体应用 - 常用框架 - 05.综合实例(iot-admin)

3.使用AdminLTE模板

3.1.下载 AdminLTE

AdminLTE 是一个基于 Bootstrap 的后端模板引擎,最新版本基于 Bootstrap 4 构建,高度可定制且易于使用,适合从小型移动设备到大型台式机的多种屏幕分辨率。
官网地址为 https://adminlte.io/ ,AdminLTE为开源软件,可以前往 Github 获取源码。

本实例将使用 AdminLTE-3.0.2 版本进行演示,源码包已经上传至QQ群,请在 门户首页 下方加入QQ群获取。

AdminLTE 下载后解压缩,文件夹结构如下:

Java单体应用 - 常用框架 - 05.综合实例(iot-admin)

将目录下的文件 index.html 用浏览器打开运行,效果如下:

Java单体应用 - 常用框架 - 05.综合实例(iot-admin)

请在使用 AdminLTE 框架前详细浏览各页面的展示效果,并参照 HTML 源码了解 AdminLTE 的使用方法。

3.2.重构项目

因为 AdminLTE-3.0.2 是基于 Bootstrap 4 构建的,所以接下来我们重构我们的项目。

首先,删除项目中的如下目录:

  • src/main/webapp/assets/plugins
  • src/main/webapp/assets/css
  • src/main/webapp/assets/images
  • src/main/webapp/assets/js

然后,将 AdminLTE-3.0.2 下的文件夹复制到项目中,对应位置为:

AdminLTE-3.0.2 目录 项目中目录
AdminLTE-3.0.2/plugins src/main/webapp/assets/plugins
AdminLTE-3.0.2/dist/css src/main/webapp/assets/css
AdminLTE-3.0.2/dist/images src/main/webapp/assets/images
AdminLTE-3.0.2/dist/js src/main/webapp/assets/js

重构后的目录结构为:

Java单体应用 - 常用框架 - 05.综合实例(iot-admin)

4.创建登录页

我们参照 AdminLTE-3.0.2/pages/examples/login.html 源码示例构建一个 iot-amdin 项目的登录页。

重构 index.jsp 页面,代码如下:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>IoT-Admin</title>
    <!-- Tell the browser to be responsive to screen width -->
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!-- Font Awesome -->
    <link rel="stylesheet" href="assets/plugins/fontawesome-free/css/all.min.css">
    <!-- icheck bootstrap -->
    <link rel="stylesheet" href="assets/plugins/icheck-bootstrap/icheck-bootstrap.min.css">
    <!-- Theme style -->
    <link rel="stylesheet" href="assets/css/adminlte.min.css">
</head>
<body class="hold-transition login-page">
<div class="login-box">
    <div class="login-logo">
        IoT-Admin 登录
    </div>
    <!-- /.login-logo -->
    <div class="card">
        <div class="card-body login-card-body">
            <p class="login-box-msg">请输入ID和密码登录</p>

            <form action="/login" method="post">
                <div class="input-group mb-3">
                    <input name="loginId" type="text" class="form-control" placeholder="登录ID">
                    <div class="input-group-append">
                        <div class="input-group-text">
                            <span class="fas fa-user"></span>
                        </div>
                    </div>
                </div>
                <div class="input-group mb-3">
                    <input name="loginPwd" type="password" class="form-control" placeholder="登录密码">
                    <div class="input-group-append">
                        <div class="input-group-text">
                            <span class="fas fa-lock"></span>
                        </div>
                    </div>
                </div>
                <div class="row">
                    <div class="col-8">
                        <div class="icheck-primary">
                            <input type="checkbox" id="remember">
                            <label for="remember">
                                记住我
                            </label>
                        </div>
                    </div>
                    <!-- /.col -->
                    <div class="col-4">
                        <button type="submit" class="btn btn-primary btn-block">登录</button>
                    </div>
                    <!-- /.col -->
                </div>
            </form>
        </div>
        <!-- /.login-card-body -->
    </div>
</div>
<!-- /.login-box -->

<!-- jQuery -->
<script src="assets/plugins/jquery/jquery.min.js"></script>
<!-- Bootstrap 4 -->
<script src="assets/plugins/bootstrap/js/bootstrap.bundle.min.js"></script>
<!-- AdminLTE App -->
<script src="assets/js/adminlte.min.js"></script>

</body>
</html>

运行 Tomcat ,启动项目,效果如下:

Java单体应用 - 常用框架 - 05.综合实例(iot-admin)

5.登录功能实现

后端代码实现和 架构模式 - 实践练习 章节所述方式类似,我们将其实现代码进行改造。

5.1.创建 User 类

在包 net.work100.training.stage2.iot.admin 下新建一个包 entity,然后在其下新增一个 User

User.java 文件代码如下:

package net.work100.training.stage2.iot.admin.entity;

import java.io.Serializable;

/**
 * <p>Title: User</p>
 * <p>Description: </p>
 *
 * @author liuxiaojun
 * @date 2020-02-13 13:21
 * ------------------- History -------------------
 * <date>      <author>       <desc>
 * 2020-02-13   liuxiaojun     初始创建
 * -----------------------------------------------
 */
public class User implements Serializable {
    private String userName;
    private String loginId;
    private String loginPwd;

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getLoginId() {
        return loginId;
    }

    public void setLoginId(String loginId) {
        this.loginId = loginId;
    }

    public String getLoginPwd() {
        return loginPwd;
    }

    public void setLoginPwd(String loginPwd) {
        this.loginPwd = loginPwd;
    }

    @Override
    public String toString() {
        return "User{" +
                "userName='" + userName + '\'' +
                ", loginId='" + loginId + '\'' +
                '}';
    }
}

5.2.创建 UserDao 接口及其实现 UserDaoImpl

在包 net.work100.training.stage2.iot.admin.dao 下新建一个接口 UserDao

UserDao.java 文件代码如下:

package net.work100.training.stage2.iot.admin.dao;

import net.work100.training.stage2.iot.admin.entity.User;

/**
 * <p>Title: UserDao</p>
 * <p>Description: </p>
 *
 * @author liuxiaojun
 * @date 2020-02-13 13:16
 * ------------------- History -------------------
 * <date>      <author>       <desc>
 * 2020-02-13   liuxiaojun     初始创建
 * -----------------------------------------------
 */
public interface UserDao {
    /**
     * 根据ID及密码获取用户信息
     *
     * @param loginId  登录ID
     * @param loginPwd 登录密码
     * @return
     */
    User getUser(String loginId, String loginPwd);
}

在包 net.work100.training.stage2.iot.admin.dao 下新增一个类包 impl,然后在 impl 包下新建一个类 UserDaoImpl

UserDaoImpl.java 文件代码如下:

package net.work100.training.stage2.iot.admin.dao.impl;

import net.work100.training.stage2.iot.admin.dao.UserDao;
import net.work100.training.stage2.iot.admin.entity.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * <p>Title: UserDaoImpl</p>
 * <p>Description: </p>
 *
 * @author liuxiaojun
 * @date 2020-02-13 13:23
 * ------------------- History -------------------
 * <date>      <author>       <desc>
 * 2020-02-13   liuxiaojun     初始创建
 * -----------------------------------------------
 */
public class UserDaoImpl implements UserDao {

    private static final Logger logger = LoggerFactory.getLogger(UserDaoImpl.class);

    public User getUser(String loginId, String loginPwd) {
        logger.debug("调用方法 getUser(loginId:{}, loginPwd:{})", loginId, loginPwd);

        // 根据 loginId 查询出用户信息
        User user = getUserByLoginId(loginId);
        if (user != null) {
            // 验证 loginPwd 是否正确(区分大小写)
            if (user.getLoginPwd().equals(loginPwd)) {
                return user;
            }
        }
        return null;
    }


    /**
     * 获取模拟的用户数据
     *
     * @param loginId 登录ID
     * @return
     */
    private User getUserByLoginId(String loginId) {
        // 模拟 DB 存在的用户数据
        User dbUser = new User();
        dbUser.setUserName("Xiaojun");
        dbUser.setLoginId("admin");
        dbUser.setLoginPwd("admin");

        // 判断是否存在 loginId 的用户(忽略大小写)
        if (dbUser.getLoginId().equalsIgnoreCase(loginId)) {
            logger.info("匹配上用户:{}", dbUser);
            return dbUser;
        }
        logger.warn("未匹配任何用户,将返回 null");
        return null;
    }
}

5.3.创建 UserService 接口及其实现 UserServiceImpl

在包 net.work100.training.stage2.iot.admin.service 下新建一个接口 UserService

UserService.java 文件代码如下:

package net.work100.training.stage2.iot.admin.service;

import net.work100.training.stage2.iot.admin.entity.User;

/**
 * <p>Title: UserService</p>
 * <p>Description: </p>
 *
 * @author liuxiaojun
 * @date 2020-02-13 13:25
 * ------------------- History -------------------
 * <date>      <author>       <desc>
 * 2020-02-13   liuxiaojun     初始创建
 * -----------------------------------------------
 */
public interface UserService {
    /**
     * 登录验证
     *
     * @param loginId  登录ID
     * @param loginPwd 登录密码
     * @return
     */
    User login(String loginId, String loginPwd);
}

在包 net.work100.training.stage2.iot.admin.service 下新增一个类包 impl,然后在 impl 包下新建一个类 UserServiceImpl

UserServiceImpl.java 文件代码如下:

package net.work100.training.stage2.iot.admin.service.impl;

import net.work100.training.stage2.iot.admin.dao.UserDao;
import net.work100.training.stage2.iot.admin.dao.impl.UserDaoImpl;
import net.work100.training.stage2.iot.admin.entity.User;
import net.work100.training.stage2.iot.admin.service.UserService;

/**
 * <p>Title: UserServiceImpl</p>
 * <p>Description: </p>
 *
 * @author liuxiaojun
 * @date 2020-02-13 13:26
 * ------------------- History -------------------
 * <date>      <author>       <desc>
 * 2020-02-13   liuxiaojun     初始创建
 * -----------------------------------------------
 */
public class UserServiceImpl implements UserService {

    private UserDao userDao = new UserDaoImpl();

    public User login(String loginId, String loginPwd) {
        return userDao.getUser(loginId, loginPwd);
    }
}

5.4.创建 LoginController

实现 Servlet

在包 net.work100.training.stage2.iot.admin.web 下新增一个类包 controller,然后在 controller 包下新建一个类 LoginController

LoginController.java 文件代码如下:

package net.work100.training.stage2.iot.admin.web.controller;

import net.work100.training.stage2.iot.admin.entity.User;
import net.work100.training.stage2.iot.admin.service.UserService;
import net.work100.training.stage2.iot.admin.service.impl.UserServiceImpl;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * <p>Title: LoginController</p>
 * <p>Description: </p>
 *
 * @author liuxiaojun
 * @date 2020-02-13 13:28
 * ------------------- History -------------------
 * <date>      <author>       <desc>
 * 2020-02-13   liuxiaojun     初始创建
 * -----------------------------------------------
 */
public class LoginController extends HttpServlet {

    private UserService userService = new UserServiceImpl();

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        User user = userService.login("admin", "admin");
        System.out.println("--------------doGet test(begin)-----------------");
        System.out.println(user);
        System.out.println("--------------doGet test(end)-----------------");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String loginId = req.getParameter("loginId");
        String loginPwd = req.getParameter("loginPwd");

        User user = userService.login(loginId, loginPwd);

        // 登录成功
        if (user != null) {
            // 重定向到首页
            resp.sendRedirect("/main.jsp");
        }
        // 登录失败
        else {
            // 跳转回登录页
            req.getRequestDispatcher("/index.jsp").forward(req, resp);
        }
    }
}

配置 Servlet 映射

修改 src/main/webapp/WEB-INF/web.xml 文件,内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <servlet>
        <servlet-name>loginController</servlet-name>
        <servlet-class>net.work100.training.stage2.iot.admin.web.controller.LoginController</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>loginController</servlet-name>
        <url-pattern>/login</url-pattern>
    </servlet-mapping>
</web-app>

新建登录成功后展示页面 main.jsp

为了模拟登录验证后的效果,我们在文件夹 src/main/webapp/ 下新建文件 main.jsp,登录成功后将跳转至此页面,代码如下:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>首页</title>
</head>
<body>
这里是首页
</body>
</html>

5.5.运行

启动 Tomcat 进行登录验证,表单输入以下正确的登录数据:

名称
用户名 admin
密码 admin

页面将跳转至 main.jsp,如下图:

Java单体应用 - 常用框架 - 05.综合实例(iot-admin)

输入错误登录数据时,重新返回到登录页。

5.6.使用 Spring IoC

新建 SpringContext 类

新建一个类包 net.work100.training.stage2.iot.admin.commons.context,然后在其下创建 SpringContext

SpringContext.java 文件代码如下:

package net.work100.training.stage2.iot.admin.commons.context;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * <p>Title: SpringContext</p>
 * <p>Description: </p>
 *
 * @author liuxiaojun
 * @date 2020-02-13 14:31
 * ------------------- History -------------------
 * <date>      <author>       <desc>
 * 2020-02-13   liuxiaojun     初始创建
 * -----------------------------------------------
 */
public final class SpringContext {

    public Object getBean(String beanId) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-context.xml");
        return context.getBean(beanId);
    }

}

配置 spring-context.xml

修改 src/main/resources/spring-context.xml 文件,内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- DAO -->
    <bean id="userDao" class="net.work100.training.stage2.iot.admin.dao.impl.UserDaoImpl" />

    <!-- Service -->
    <bean id="userService" class="net.work100.training.stage2.iot.admin.service.impl.UserServiceImpl" />
</beans>

修改 UserServiceImpl

修改 UserServiceImpl.java 代码,如下:

package net.work100.training.stage2.iot.admin.service.impl;

import net.work100.training.stage2.iot.admin.commons.context.SpringContext;
import net.work100.training.stage2.iot.admin.dao.UserDao;
import net.work100.training.stage2.iot.admin.entity.User;
import net.work100.training.stage2.iot.admin.service.UserService;

/**
 * <p>Title: UserServiceImpl</p>
 * <p>Description: </p>
 *
 * @author liuxiaojun
 * @date 2020-02-13 13:26
 * ------------------- History -------------------
 * <date>      <author>       <desc>
 * 2020-02-13   liuxiaojun     初始创建
 * -----------------------------------------------
 */
public class UserServiceImpl implements UserService {

    private SpringContext context = new SpringContext();

    public User login(String loginId, String loginPwd) {
        UserDao userDao = (UserDao) context.getBean("userDao");
        return userDao.getUser(loginId, loginPwd);
    }
}

修改 LoginController

修改 LoginController.java 代码,如下:

package net.work100.training.stage2.iot.admin.web.controller;

import net.work100.training.stage2.iot.admin.commons.context.SpringContext;
import net.work100.training.stage2.iot.admin.entity.User;
import net.work100.training.stage2.iot.admin.service.UserService;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * <p>Title: LoginController</p>
 * <p>Description: </p>
 *
 * @author liuxiaojun
 * @date 2020-02-13 13:28
 * ------------------- History -------------------
 * <date>      <author>       <desc>
 * 2020-02-13   liuxiaojun     初始创建
 * -----------------------------------------------
 */
public class LoginController extends HttpServlet {

    private SpringContext context = new SpringContext();

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        UserService userService = (UserService) context.getBean("userService");
        User user = userService.login("admin", "admin");
        System.out.println("--------------doGet test(begin)-----------------");
        System.out.println(user);
        System.out.println("--------------doGet test(end)-----------------");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        UserService userService = (UserService) context.getBean("userService");
        String loginId = req.getParameter("loginId");
        String loginPwd = req.getParameter("loginPwd");

        User user = userService.login(loginId, loginPwd);

        // 登录成功
        if (user != null) {
            // 重定向到首页
            resp.sendRedirect("/main.jsp");
        }
        // 登录失败
        else {
            // 跳转回登录页
            req.getRequestDispatcher("/index.jsp").forward(req, resp);
        }
    }
}

重新运行

重启 Tomcat 验证运行效果。

6.提升用户体验

当用户输入错误的ID或密码时验证会失败,然后页面会跳转回登录页。

从用户体验角度考虑,需要给用户一个 提示信息,告知其登录验证失败了,下面我们来实现这个功能。

6.1.改造 LoginController

登录验证失败后增加返回错误信息 req.setAttribute("message", "登录ID或登录密码错误"); ,完整代码如下:

package net.work100.training.stage2.iot.admin.web.controller;

import net.work100.training.stage2.iot.admin.commons.context.SpringContext;
import net.work100.training.stage2.iot.admin.entity.User;
import net.work100.training.stage2.iot.admin.service.UserService;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * <p>Title: LoginController</p>
 * <p>Description: </p>
 * <p>Url: http://www.work100.net/training/monolithic-frameworks-example.html</p>
 *
 * @author liuxiaojun
 * @date 2020-02-13 13:28
 * ------------------- History -------------------
 * <date>      <author>       <desc>
 * 2020-02-13   liuxiaojun     初始创建
 * -----------------------------------------------
 */
public class LoginController extends HttpServlet {

    private SpringContext context = new SpringContext();

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        UserService userService = (UserService) context.getBean("userService");
        User user = userService.login("admin", "admin");
        System.out.println("--------------doGet test(begin)-----------------");
        System.out.println(user);
        System.out.println("--------------doGet test(end)-----------------");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        UserService userService = (UserService) context.getBean("userService");
        String loginId = req.getParameter("loginId");
        String loginPwd = req.getParameter("loginPwd");

        User user = userService.login(loginId, loginPwd);

        // 登录成功
        if (user != null) {
            // 重定向到首页
            resp.sendRedirect("/main.jsp");
        }
        // 登录失败
        else {
            // 跳转回登录页
            req.setAttribute("message", "登录ID或登录密码错误");
            req.getRequestDispatcher("/index.jsp").forward(req, resp);
        }
    }
}

6.2.改造 index.jsp

引入 JSTL 依赖

这里我们会用到 JSTL 表达式,所以需要先在 pom.xml 文件中引入依赖:

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
</dependency>

增加 taglib 指令

index.jsp 文件头增加如下代码:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

增加错误提示

index.jsp 文件的 form 表单上方增加如下代码:

<c:if test="${message != null}">
    <div class="alert alert-danger alert-dismissible">
       <button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
          ${message}
    </div>
</c:if>

完整 index.jsp 文件代码如下:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>IoT-Admin</title>
    <!-- Tell the browser to be responsive to screen width -->
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!-- Font Awesome -->
    <link rel="stylesheet" href="assets/plugins/fontawesome-free/css/all.min.css">
    <!-- icheck bootstrap -->
    <link rel="stylesheet" href="assets/plugins/icheck-bootstrap/icheck-bootstrap.min.css">
    <!-- Theme style -->
    <link rel="stylesheet" href="assets/css/adminlte.min.css">
</head>
<body class="hold-transition login-page">
<div class="login-box">
    <div class="login-logo">
        IoT-Admin 登录
    </div>
    <!-- /.login-logo -->
    <div class="card">
        <div class="card-body login-card-body">
            <p class="login-box-msg">请输入ID和密码登录</p>
            <c:if test="${message != null}">
                <div class="alert alert-danger alert-dismissible">
                    <button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
                        ${message}
                </div>
            </c:if>
            <form action="/login" method="post">
                <div class="input-group mb-3">
                    <input name="loginId" type="text" class="form-control" placeholder="登录ID">
                    <div class="input-group-append">
                        <div class="input-group-text">
                            <span class="fas fa-user"></span>
                        </div>
                    </div>
                </div>
                <div class="input-group mb-3">
                    <input name="loginPwd" type="password" class="form-control" placeholder="登录密码">
                    <div class="input-group-append">
                        <div class="input-group-text">
                            <span class="fas fa-lock"></span>
                        </div>
                    </div>
                </div>
                <div class="row">
                    <div class="col-8">
                        <div class="icheck-primary">
                            <input type="checkbox" id="remember">
                            <label for="remember">
                                记住我
                            </label>
                        </div>
                    </div>
                    <!-- /.col -->
                    <div class="col-4">
                        <button type="submit" class="btn btn-primary btn-block">登录</button>
                    </div>
                    <!-- /.col -->
                </div>
            </form>
        </div>
        <!-- /.login-card-body -->
    </div>
</div>
<!-- /.login-box -->

<!-- jQuery -->
<script src="assets/plugins/jquery/jquery.min.js"></script>
<!-- Bootstrap 4 -->
<script src="assets/plugins/bootstrap/js/bootstrap.bundle.min.js"></script>
<!-- AdminLTE App -->
<script src="assets/js/adminlte.min.js"></script>

</body>
</html>

6.3.验证效果

运行 Tomcat ,输入错误的登录数据,页面效果如下:

Java单体应用 - 常用框架 - 05.综合实例(iot-admin)

7.实例源码

实例源码已经托管到如下地址:


上一篇:Log4j

下一篇:Spring Web


如果对课程内容感兴趣,可以扫码关注我们的 公众号QQ群,及时关注我们的课程更新

Java单体应用 - 常用框架 - 05.综合实例(iot-admin)
Java单体应用 - 常用框架 - 05.综合实例(iot-admin)

上一篇:消息推送标准协议:MQTT


下一篇:Java单体应用 - 常用框架 - 06.Spring Web(iot-admin2)