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

综合实例

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

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

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

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

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

2.1.构建项目结构

创建项目文件夹

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

创建 POM

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

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">

4.0.0

net.work100.training.stage2

iot-admin

1.0.0-SNAPSHOT

war

org.springframework

spring-context

5.2.3.RELEASE

javax.servlet

javax.servlet-api

4.0.1

junit

junit

4.12

test

org.slf4j

slf4j-log4j12

1.7.25

然后将 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

测试源码文件夹

项目结构如下图:

acf00e9cd98f3ed4cfc26c3c9f603df7.png

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

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">

完善项目架构

结合三层架构及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层

项目结构如下图:

2817caacfb1c945a6f443726753abe41.png

配置 Spring 和 Log4j

在 src/main/resources 下添加 spring-context.xml 和 log4j.properties 文件:

spring-context.xml 代码如下:

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">

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 文件,代码如下:

IoT-Admin

Hello IoT-Admin

项目结构如下图:

9af84e2c2446aac1655754be227bb297.png

配置 Tomcat

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

349885e5e54dec0e69c7f02065ed7ce0.png

3.1.下载 AdminLTE

AdminLTE 是一个基于 Bootstrap 的后端模板引擎,最新版本基于 Bootstrap 4 构建,高度可定制且易于使用,适合从小型移动设备到大型台式机的多种屏幕分辨率。

官网地址为 https://adminlte.io/ ,AdminLTE为开源软件,可以前往 Github 获取源码。

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

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

8cf7cc94e59267bd4ccb98048d063bb5.png

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

1f409b7210e095991cdd79594d3d405c.png

请在使用 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

重构后的目录结构为:

7d6e6c130d3500be1392cb5d72507b4b.png

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

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

IoT-Admin

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

84148166fb8f72a4242189a0f3001234.png

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

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;

/**

*

Title: User

*

Description:

*

* @author liuxiaojun

* @date 2020-02-13 13:21

* ------------------- History -------------------

*

* 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;

/**

*

Title: UserDao

*

Description:

*

* @author liuxiaojun

* @date 2020-02-13 13:16

* ------------------- History -------------------

*

* 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;

/**

*

Title: UserDaoImpl

*

Description:

*

* @author liuxiaojun

* @date 2020-02-13 13:23

* ------------------- History -------------------

*

* 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;

/**

*

Title: UserService

*

Description:

*

* @author liuxiaojun

* @date 2020-02-13 13:25

* ------------------- History -------------------

*

* 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;

/**

*

Title: UserServiceImpl

*

Description:

*

* @author liuxiaojun

* @date 2020-02-13 13:26

* ------------------- History -------------------

*

* 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;

/**

*

Title: LoginController

*

Description:

*

* @author liuxiaojun

* @date 2020-02-13 13:28

* ------------------- History -------------------

*

* 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 文件,内容如下:

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">

loginController

net.work100.training.stage2.iot.admin.web.controller.LoginController

loginController

/login

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

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

首页

这里是首页

5.5.运行

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

名称

用户名

admin

密码

admin

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

582230445cf9cbaa1b7a3178a7c880d2.png

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

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;

/**

*

Title: SpringContext

*

Description:

*

* @author liuxiaojun

* @date 2020-02-13 14:31

* ------------------- History -------------------

*

* 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 文件,内容如下:

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">

修改 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;

/**

*

Title: UserServiceImpl

*

Description:

*

* @author liuxiaojun

* @date 2020-02-13 13:26

* ------------------- History -------------------

*

* 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;

/**

*

Title: LoginController

*

Description:

*

* @author liuxiaojun

* @date 2020-02-13 13:28

* ------------------- History -------------------

*

* 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 验证运行效果。

当用户输入错误的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;

/**

*

Title: LoginController

*

Description:

*

Url: http://www.work100.net/training/monolithic-frameworks-example.html

*

* @author liuxiaojun

* @date 2020-02-13 13:28

* ------------------- History -------------------

*

* 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 文件中引入依赖:

javax.servlet

jstl

1.2

增加 taglib 指令

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

增加错误提示

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

×

${message}

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

IoT-Admin

6.3.验证效果

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

1921e0057ba3806513cea650dc86e4ea.png

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
BootstrapAdmin是使用.NET Core + Bootstrap + PetaPoco + HTML 5 + jQuery构建的后台管理平台。可以用于所有的Web应用程序,目前版本已经升级到NET CORE具备跨平台能力。数据库方面同时支持多种数据库,详细列表见后面数据库的详细列表,切换数据源仅需更改配置文件无需重启应用程序,配置简单灵活。UI前端使用流行的Bootstrap框架布局对移动设备的兼容性非常好,自适应目前市场几乎所有终端设备。本系统还具备单一后台支持多前台的特色,提供单点登录(SSO)的能力。 BootstrapAdmin主要功能: 1、通过配置与前台网站集成 2、构建前台系统分层级菜单 3、提供单一后台支持多前台应用配置 4、提供单点登录 5、集成系统认证授权模块 6、提供角色,部门,用户,菜单,前台应用程序授权 6.1、角色对用户授权 6.2、角色对菜单授权 6.3、角色对部门授权 6.4、角色对应用程序授权(多个前台应用公用一个后台权限管理系统) 6.5、部门对用户授权 7、提供字典表用于前台网站个性化配置 8、完全响应式布局(支持电脑、平板、手机等所有主流设备) 9、内置多数据源支持,配置简单立即生效无需重启 10、内置数据内存缓存机制,页面快速响应 11、内置数据 操作日志 与用户 登录日志 跟踪记录用户 登录主机地点 浏览器 操作系统 信息 优势: 1、前台系统不用编写登录、授权、认证模块;只负责编写业务模块即可 2、后台系统无需任何二次开发,直接发布即可使用 3、前台与后台系统分离,分别为不同的系统(域名可独立) 4、可扩展为多租户应用
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值