一、系统展示

1.登录页面

2.admin 登录后的主页

3.菜单管理

4.角色管理 > 新增角色

5.用户管理

6.添加商品

7.仓库管理

8.供应商管理

9.采购订单管理

10.采购订单导出

11.库存查看

12.采购统计

二、系统需求分析

上面简单的展示了完成后的系统测试截图,你可以下载 war 包部署到自己的 Tomcat 上看,下面开始进入正文。

开发一个(简单)系统,我想首要做的就是进行系统需求分析,弄清楚你为什么要做这个系统,这个系统有哪些功能模块,每个功能具体实现些什么功能。

当然,我这里的主要目的是完成毕业设计,交出毕业论文。但我并没有简单的只是为了完成一个毕业设计而去开发这个系统。主要想法是以开发这套进销存管理系统为例,详细说明一个系统从确认需求、技术选型、架构设计、系统实现到测试部署的整个开发过程。综合运用自己平时所学的知识、技术,及实习获得的经验等,去完整且较好的实现一个系统。搭建一个基础系统框架,形成一定规范,以后在此基础上做开发,可以省去很多诸如搭建框架、加入依赖、配置等工作。

这次开发所做的主要工作及意义如下:

  • ① 学会站在用户的角度分析用户需求,完成需求分析设计等。
  • ② 熟练使用各种类相关开发、设计工具,及开源软件。
  • ③ 熟练掌握 Spring+SpringMVC+Hibernate+ExtJs 的开发技术。
  • ④ 熟练使用 maven 构建工具。
  • ⑤ 站在企业的角度,试着搭建自己的一个底层基础框架。
  • ⑥ 建立完整的燃气管进销存管理系统,进行测试并分析结果。
  • ⑦ 将系统部署到互联网上,以实现真正的 Web 应用。

1.问题分析

首先,对系统进行需求分析,首先需要了解的就是什么是进销存系统,进销存系统也称为供应链管理系统,最基本的内容就是采购、库存、销售、退货管理。进销存系统是对企业生产经营中采购、入库、销售进行跟踪管理,从采购单开始,到商品入库,商品销售出库,每一步都跟踪记录。有效解决企业的分销管理等业务问题。那么燃气管进销存系统有何不同呢,其实进销存系统已经具备了一般商品的进销存功能,燃气管就是一种商品。以此为出发点,开始着手设计系统功能模块。

2.系统模块结构

系统分为 6 大模块,分别是基础设置、采购管理、销售管理、库存管理、统计分析、系统管理。系统设置的角色有 admin、采购员、销售员、库存管理员等。

系统模块结构(使用 xmind 设计):

3.系统总体流程

系统的一个整体流程,从初次使用开始,系统设置一个超级管理员(admin),拥有系统的所有权限。admin 登录系统,设置角色(系统管理员,采购员,销售员,库存管理员),分配对应的权限。然后进入用户管理,录入系统用户。一般管理员登录系统,录入基础数据;采购员需要录入供应商,采购单,退货单;销售员则需录入销售单,退货单。库存管理员就需要在库存管理中进行采购审核和销售审核,采购审核通过则商品入库,增加库存;销售审核通过则商品出库,减少库存。管理员还可以查看每月的采购统计和销售统计。

系统总体流程(使用 visio 设计):

三、开发环境简介

需求确定了,就要进入具体的开发阶段,首先确定开发这个系统综合用到哪些技术、开发工具等。

简单说下这个系统的开发环境:

  • 开发平台:windows 8.1
  • Java 版本:JDK 1.8
  • 项目管理工具:Maven
  • 开发工具:Intellij IDEA
  • 数据库:MySQL 5.1
  • 服务器:Tomcat 8.5
  • 开发框架:Spring4 + SpringMVC + Hibernate5
  • 前端框架:ExtJs 4.2 + JSP
  • 建模工具:PowerDesigner、Visio

1.maven

Maven 是 Apache 软件基金会组织维护的一款自动化构建工具,专注服务于 Java 平台的项目构建和依赖管理。它提供了中央仓库,能帮我们自动下载构件和第三方的开源类库。你只需要在你的项目中以坐标的方式依赖一个 jar 包,maven 就会自动从中央仓库下载,并同时下载这个 jar 包所依赖的其他 jar 包,以及可以下载源码进行阅读。使用 maven 后每个 jar 包本身只在本地仓库中保存一份,极大的节约了存储空间,让项目更轻巧,更避免了重复文件太多而造成的混乱。同时 maven 可以替我们自动的将当前 jar 包所依赖的其他所有 jar 包全部导入进来,无需人工参与,节约了大量的时间和精力。使用 maven,只需要一条简单的命令,就可以自动完成清理、编译、测试、打包、部署的整个过程。我们的项目一般会分为开发环境和生产环境,不同环境对应不同的配置文件,使用 maven,你就可以配置两个环境,打包的时候指定运行的环境,就可以将对应的配置文件替换,以此减少手工操作及可能带来的失误操作等。

2.Intellij IDEA

IDEA 是 Java 语言开发的集成环境,Intellij 被公认为最好的 Java 开发工具之一。IDEA 在代码自动提示、重构、调试、各类版本工具(maven、SVN 等)整合等方面都是比较强的。本人是在实习期间转用 idea 开发的,之前一直使用 eclipse,相比 eclipse,idea 在调试、代码自动提示等方面更显优势。项目在 idea 中有一个更友好的目录结构,尤其是多工程项目。当然,eclipse 比 idea 更容易上手,使用 idea 可以提高你的开发速度,但前提是你需要记住大量的快捷键。使用 idea 的调试功能,比如,你只需要按快捷键 Alt+F8,然后输入表达式,就可以快速求值;在调试的时候,idea 会在变量的后面以不同的颜色显示变量的值,你就可以很清楚的知道调试的每一步,非常方便。使用好 IDEA 能在很大程度上提高我们的开发速度。

3.ExtJs

ExtJs 可以用来开发富客户端的 AJAX 应用,是用 JavaScript 写的与后台技术无关的前端 AJAX 框架,主要用于创建前端用户界面,拥有强大的数据处理功能,以及图表统计等。同时,ExtJs 拥有很多个性化的主题供你选择,是开发后台管理系统的一个不错的选择。

四、底层架构设计

在进行进销存系统的设计和编码之前,首先设计一个自己的底层框架,这个底层框架在之后可以作为其它具体项目开发的一个基础,从而不必每次开发项目时,都去做很多重复的工作。这个底层框架主要包括一个开发的规范,以及一些通用的工具类等,更重要的是分类别引入各个框架,如 Spring、Hibernate、各个配置文件等。同时,如果以后在开发中,增加的一些新功能,还可以往这个底层中添加,不断的去完善。

1.规范

在进行框架设计之前,为了使软件开发过程顺畅、提高代码的可靠性,可读性和可维护性等,首先需要确定的就是开发规范了,俗话说,没有规矩不成方圆,软件开发亦是如此。下面列出一些简单的需要遵守的规范。

1.1 基础规范

首先需要遵守的是一些基础规范。一般来说,公司会将域名作为所有命名的一个基础,比如文件名、包名等等。因此我申请了一个域名[www.lyyzoo.com]作为个人域名。然后将 D:/lyyzoo-repo 作为开发的根目录,即个人代码仓库,以后所有的项目都会建到这个目录下。所有的项目开发使用 maven 来管理项目,因此目录结构是标准的 maven 规范目录。

maven 约定的目录结构:

1.2 代码规范

① 命名

  • 所有的命名需要见名之意,尽量保证通过变量名得知变量的含义,需要注释的地方尽量添加注释。
  • 包命名全小写,通过域名倒写 + 模块的形式,如:com.lyyzoo.service
  • 类命名采用 Pascal 名法,大写字母开头,每个单词首字母大写。
  • 方法名采用 Camel 命名法,小写字母开头,每个单词首字母小写;getter 和 setter 使用 Lombok 自动生成,只需添加@Data 注解即可。
  • 变量名采用 Camel 命名法,小写字母开头,每个单词首字母大写。变量名不宜过长,可采用首字母缩写的形式,但要见名之意。
  • 常量名全大写,每个单词之间使用”_”分隔。

② 分层

项目以功能模块划分,不同项目建立不同的工程,使用 maven 的依赖进行管理。包的基本分层有 controller(控制层)、service(业务层)、dao(数据访问层)、entity(模型层)。

2.架构设计

2.1 模块结构

整个项目的底层着重是一些通用的、基础的东西,整合到一起,以便于以后重用。首先,创建一个名为 lyyzoo 的 maven 工程,lyyzoo 将作为底层的根目录。lyyzoo 下有两个主要的子模块,分别为 lyyzoo-base 和 lyyzoo-starter,lyyzoo-base 是基础模块,用于一些简单的 Java 及 JavaEE 程序;lyyzoo-starter 则是 JavaEE 相关,会依赖于 lyyzoo-base,同时引入了 Spring、Hibernate 等第三方框架。然后在各个模块中添加具体的子模块。以后开发中需要用到哪个模块,在依赖中添加那个模块即可。

底层模块结构图:

以下是各个 POM 之间的关系:

①lyyzoo > pom.xml

②lyyzoo-base > pom.xml

③lyyzoo-starter > pom.xml

2.2 依赖管理

结构建好后,就需要进行一些详细的依赖配置工作了,lyyzoo 是所有模块的父类,所以在 lyyzoo 中需要添加公用的属性、依赖管理、maven 插件等。

首先将所有的版本号提出来,放到里,这样一旦需要切换到另一个版本时,就可以只改个版本号就达到目的了。其中列出了一些属性如下:包括底层的版本、Java 版本、Spring、Hibernate 的版本等等。

<properties><!-- Global --><lyyzoo.version>1.0-SNAPSHOT</lyyzoo.version><java.version>1.8</java.version><maven.compiler.source>${java.version}</maven.compiler.source><maven.compiler.target>${java.version}</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><!-- lombok --><lombok.version>1.16.14</lombok.version><!-- log --><slf4j.version>1.7.7</slf4j.version><logback.version>1.1.3</logback.version><!-- jdbc --><mysql.version>5.1.38</mysql.version><!-- http://mvnrepository.com/artifact/com.mchange/c3p0/ --><c3p0.version>0.9.5.2</c3p0.version><!-- test --><junit.version>4.12</junit.version><!-- servlet --><servlet.version>3.1.0</servlet.version><!-- spring --><spring.version>4.2.6.RELEASE</spring.version><aspectjrt.version>1.7.3</aspectjrt.version><aspectjweaver.version>1.7.3</aspectjweaver.version><!-- hibernate --><hibernate.version>5.0.1.Final</hibernate.version><hibernate.jpa.version>1.0.0.Final</hibernate.jpa.version>
</properties>

接着,引入依赖管理,在 lyyzoo 中引入其它项目将会用到的所有三方 jar 包的依赖,所有的依赖都添加到中,这样就可以方便的管理所有的 jar 包了。下面列出引入的一部分 jar 包,其它的可参考源码。

① 首先需要引入 lyyzoo 下的其它模块,如 lyyzoo-base-core、lyyzoo-starter-base 等模块。

<!-- lyyzoo -->
<dependency><groupId>com.lyyzoo</groupId><artifactId>lyyzoo-base-core</artifactId><version>${lyyzoo.version}</version>
</dependency>
<dependency><groupId>com.lyyzoo</groupId><artifactId>lyyzoo-base-data</artifactId><version>${lyyzoo.version}</version>
</dependency>
<dependency><groupId>com.lyyzoo</groupId><artifactId>lyyzoo-starter-base</artifactId><version>${lyyzoo.version}</version>
</dependency>
<dependency><groupId>com.lyyzoo</groupId><artifactId>lyyzoo-starter-jpa</artifactId><version>${lyyzoo.version}</version>
</dependency>

②JDBC 相关,相关 jar 包有 c3p0,用于作数据库连接池;MySQL 驱动包;dbutils,对 JDBC 进行了简单的封装,使用起来简单方便。

<!-- jdbc -->
<dependency><groupId>com.mchange</groupId><artifactId>c3p0</artifactId><version>${c3p0.version}</version>
</dependency>
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>${mysql.version}</version>
</dependency>
<dependency><groupId>commons-dbutils</groupId><artifactId>commons-dbutils</artifactId><version>1.5</version>
</dependency>

③ 日志相关:

<!-- log -->
<dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>${slf4j.version}</version>
</dependency>
<dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>${logback.version}</version>
</dependency>
<!-- slf4j -->
<dependency><groupId>org.slf4j</groupId><artifactId>log4j-over-slf4j</artifactId><version>${slf4j.version}</version>
</dependency>

④Spring 相关,包括了 Spring aop、Spring mvc 等。

<!-- springframework -->
<dependency><groupId>org.springframework</groupId><artifactId>spring-aop</artifactId><version>${spring.version}</version>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId><version>${spring.version}</version>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-beans</artifactId><version>${spring.version}</version>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring.version}</version>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-context-support</artifactId><version>${spring.version}</version>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>${spring.version}</version>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>${spring.version}</version>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-jms</artifactId><version>${spring.version}</version>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-orm</artifactId><version>${spring.version}</version>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-tx</artifactId><version>${spring.version}</version>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-web</artifactId><version>${spring.version}</version>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>${spring.version}</version>
</dependency>

⑤hibernate 相关:

<dependency><groupId>org.hibernate</groupId><artifactId>hibernate-c3p0</artifactId><version>${hibernate.version}</version>
</dependency>
<dependency><groupId>org.hibernate.common</groupId><artifactId>hibernate-commons-annotations</artifactId><version>${hibernate.version}</version>
</dependency>
<dependency><groupId>org.hibernate</groupId><artifactId>hibernate-core</artifactId><version>${hibernate.version}</version>
</dependency>
<dependency><groupId>org.hibernate</groupId><artifactId>hibernate-entitymanager</artifactId><version>${hibernate.version}</version>
</dependency>

所有的依赖添加好后,就需要为各个子模块添加具体的依赖了,根据每个子模块的功能,添加相关的依赖,而不是将所有的依赖一次性加入。这样我们就可以根据自己开发的项目的需要,添加模块依赖,而不是一次性加入所有 jar 包,避免冗余,增大项目的体积。下面以 lyyzoo-base-data 和 lyyzoo-starter-jpa 为例说明。

lyyzoo-base-data 模块是基础数据相关,主要与数据库打交道,那么就需要引入 MySQL 驱动、数据库连接池 c3p0 等,pom.xml 如下:

<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><parent><groupId>com.lyyzoo</groupId><artifactId>lyyzoo-base</artifactId><version>1.0-SNAPSHOT</version></parent><artifactId>lyyzoo-base-data</artifactId><name>${project.artifactId}</name><packaging>jar</packaging><dependencies><!-- dbutils --><dependency><groupId>commons-dbutils</groupId><artifactId>commons-dbutils</artifactId></dependency><!-- jdbc --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>com.mchange</groupId><artifactId>c3p0</artifactId></dependency><!-- test --><dependency><groupId>com.lyyzoo</groupId><artifactId>lyyzoo-base-test</artifactId><scope>test</scope></dependency></dependencies>
</project>

lyyzoo-starter-jpa 是 Java 持久化相关,所以主要引入 hibernate 相关的依赖,同时,starter-jpa 会依赖 base-data 及 starter-base,pom.xml 如下:

<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><parent><groupId>com.lyyzoo</groupId><artifactId>lyyzoo-starter</artifactId><version>1.0-SNAPSHOT</version></parent><artifactId>lyyzoo-starter-jpa</artifactId><name>${project.artifactId}</name><packaging>jar</packaging><dependencies><dependency><groupId>com.lyyzoo</groupId><artifactId>lyyzoo-base-data</artifactId></dependency><dependency><groupId>com.lyyzoo</groupId><artifactId>lyyzoo-starter-base</artifactId></dependency><dependency><groupId>org.hibernate</groupId><artifactId>hibernate-c3p0</artifactId></dependency><dependency><groupId>org.hibernate.common</groupId><artifactId>hibernate-commons-annotations</artifactId></dependency><dependency><groupId>org.hibernate</groupId><artifactId>hibernate-core</artifactId></dependency><dependency><groupId>org.hibernate</groupId><artifactId>hibernate-ehcache</artifactId></dependency><dependency><groupId>org.hibernate.javax.persistence</groupId><artifactId>hibernate-jpa-2.1-api</artifactId></dependency><dependency><groupId>org.hibernate</groupId><artifactId>hibernate-validator</artifactId></dependency><dependency><groupId>com.lyyzoo</groupId><artifactId>lyyzoo-starter-test</artifactId><scope>test</scope></dependency></dependencies>
</project>

2.3 类结构

有了前面的基础之后,接下来进行重点的类结构设计。底层需要做的最重要的工作就是将一些通用的类抽象出来,以便于以后重用,从而提高开发效率。例如返回结果和分页类的封装、通用的工具类、JDBC 相关的操作等。

说明一下,整个底层很大一部分是从之前实习的公司(这个就不说了)直接拿过来的,有些则更改了。相信我拿取的这部分代码并不会涉及机密问题,不用于商业用途,仅仅只是学习,应该没多大问题。

(1) lyyzoo-base-core

lyyzoo-base-core 目录结构:

lyyzoo-base-core 是基础核心,封装了返回结果和加入了一些常用的工具类。

com.lyyzoo.bean 包下封装了 BaseBean 和 Result,BaseBean 是 Bean 类的一个基础类,实现了序列化,重写了 toString()方法,如下:

package com.lyyzoo.bean;import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;import java.io.Serializable;/*** BaseBean 实现序列化 <p>** @author bojiangzhou* @date 2017-03-27*/
public abstract class BaseBean implements Serializable {/*** ToStringBuilder – 用于辅助实现Object.toString()方法<p>*/public String toString() {return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);}}

Result 则封装了返回的结果,这里主要与 ExtJs 相对应,ExtJs 进行 AJAX 请求时,返回 success=true,会进入 success()方法;返回 success=false,会进入 failure()方法。同时,封装了返回消息、标识、错误信息等,便于前端拿到相应数据。

package com.lyyzoo.bean;import lombok.Data;import java.util.Map;/*** 封装返回结果<p>** @author bojiangzhou* @date 2017-03-27*/
@Data
public class Result extends BaseBean {private static final long serialVersionUID = 1L;/*** 成功标志*/public boolean success;/*** 返回标示*/public Integer code;/*** 相关消息*/public String msg;/*** 相关数据*/public Object data;/*** 错误详细*/public Map<String, Object> errors;public Result() {}public Result(boolean success) {this.success = success;}public Result(boolean success, Integer code, Object data, String msg) {this(success);this.code = code;this.data = data;this.msg = msg;}public Result(Integer code, Map<String, Object> errors, String msg) {this.success = false;this.code = code;this.errors = errors;this.msg = msg;}public boolean isSuccess() {return this.success;}public boolean hasErrors() {if (this.errors != null && this.errors.size() > 0) {return true;}return false;}
}

其它的主要是一些工具类,例如 Arrays 继承了 org.apache.commons.lang3.ArrayUtils,使得 Arrays 具有了丰富的操作集合的工具。再如 Dates,Dates 里封装了大量的对日期操作的方法,比如格式化日期、获取某个日期当天的开始时间和结束时间等。

(2) lyyzoo-starter-base

lyyzoo-starter-base 目录结构:

lyyzoo-starter-base 是 Web 应用程序的一个基础,主要封装了基础实体类以及 spring-base 和日志的配置。实体的顶层是 AbstractEntity,AbstractEntity 继承 BaseBean。AbstractEntity 重写了 equals 和 hashCode 方法,主要做的处理是,如果两个实体的 id 相同也算这两个对象为同一个对象。代码如下:

package com.lyyzoo.data.entity;import com.lyyzoo.bean.BaseBean;import java.io.Serializable;/*** 抽象实体类 重写equals和hashCode方法** @author bojiangzhou* @date 2017-03-28*/
@SuppressWarnings("serial")
public abstract class AbstractEntity<ID extends Serializable> extends BaseBean implements Serializable {public abstract ID getId();@Overridepublic boolean equals(Object obj) {if (null == obj) {return false;}if (this == obj) {return true;}if (!getClass().equals(obj.getClass())) {return false;}AbstractEntity<?> that = (AbstractEntity<?>) obj;return null == this.getId() ? false : this.getId().equals(that.getId());}@Overridepublic int hashCode() {int hashCode = 17;hashCode += null == getId() ? 0 : getId().hashCode() * 31;return hashCode;}}

BaseEntity 则继承 AbstractEntity,BaseEntity 作为其它实体的父类存在,BaseEntity 定义了主键 ID 的生成策略。代码如下:

package com.lyyzoo.data.entity;import lombok.Data;import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;/*** 统一定义id的entity基类.* <p/>* 抽象实体基类,提供统一的ID,和相关的基本功能* <p/>*/
@Data
@MappedSuperclass
@SuppressWarnings("serial")
public abstract class BaseEntity extends AbstractEntity<Long> {/*** id 字段*/@Idprotected Long id;@Id@GeneratedValue(strategy = GenerationType.IDENTITY)public Long getId() {return this.id;}public void setId(Long id) {this.id = id;}
}

spring-base.xml 是基础配置,主要配置了扫描系统的配置文件、注解等。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns="http://www.springframework.org/schema/beans"xmlns:beans="http://www.springframework.org/schema/beans"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:tx="http://www.springframework.org/schema/tx"xmlns:util="http://www.springframework.org/schema/util"xmlns:mvc="http://www.springframework.org/schema/mvc"xmlns:jee="http://www.springframework.org/schema/jee"xmlns:jdbc="http://www.springframework.org/schema/jdbc"xmlns:tool="http://www.springframework.org/schema/tool"xmlns:dwr="http://www.directwebremoting.org/schema/spring-dwr"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsdhttp://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsdhttp://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsdhttp://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsdhttp://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsdhttp://www.springframework.org/schema/tool http://www.springframework.org/schema/tool/spring-tool.xsdhttp://www.directwebremoting.org/schema/spring-dwr http://www.directwebremoting.org/schema/spring-dwr-3.0.xsd"
><description>Spring Base Config</description><!-- 加载config.properties --><context:property-placeholder location="classpath*:/config/*.properties" file-encoding="UTF-8" /><!-- 使用annotation 自动注册bean, 并保证@Required、@Autowired的属性被注入 --><context:component-scan base-package="com.lyyzoo"><context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/><context:exclude-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/></context:component-scan><!-- 支持上传文件 --><bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/></beans>

(3) lyyzoo-starter-jpa

lyyzoo-starter-jpa 目录结构:

lyyzoo-starter-jpa 集成了持久化相关的操作,配置等。

首先需要做持久化相关的配置(spring-base-jpa.xml),如数据源、SessionFactory、事务管理等。数据源使用 c3p0,数据源相关配置如数据库驱动、地址等写到到配置文件中。配置 Hibernate SessionFactory 的同时,增加了 JdbcTemplate。事务管理器使用 Hibernate 的事务管理。总的配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns="http://www.springframework.org/schema/beans"xmlns:beans="http://www.springframework.org/schema/beans"xmlns:tx="http://www.springframework.org/schema/tx"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:context="http://www.springframework.org/schema/context"xmlns:mvc="http://www.springframework.org/schema/mvc"xmlns:util="http://www.springframework.org/schema/util"xmlns:jee="http://www.springframework.org/schema/jee"xmlns:jdbc="http://www.springframework.org/schema/jdbc"xmlns:tool="http://www.springframework.org/schema/tool"xmlns:dwr="http://www.directwebremoting.org/schema/spring-dwr"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsdhttp://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsdhttp://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsdhttp://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsdhttp://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsdhttp://www.springframework.org/schema/tool http://www.springframework.org/schema/tool/spring-tool.xsdhttp://www.directwebremoting.org/schema/spring-dwr http://www.directwebremoting.org/schema/spring-dwr-3.0.xsd"><description>Spring Jpa</description><!-- 使用C3P0 --><bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"><property name="driverClass" value="${jdbc.driver}"/><property name="jdbcUrl" value="${jdbc.url}"/><property name="user" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/><!-- default: 3 --><!-- 初始化时获取三个连接,取值应在minPoolSize与maxPoolSize之间。--><property name="initialPoolSize" value="${c3p0.initialPoolSize:5}"/><!-- default: 3 --><!-- 连接池保留最小连接数--><property name="minPoolSize" value="${c3p0.minPoolSize:5}"/><!-- default: 15 --><!-- 连接池保留最大连接数。--><property name="maxPoolSize" value="${c3p0.maxPoolSize:15}"/><!-- default: 0(秒) = 永不丢弃--><!-- 最大空闲时间,600 秒内未使用则连接被丢弃。--><property name="maxIdleTime" value="${c3p0.maxIdleTime:600}"/></bean><!-- sessionFactory --><bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean"><property name="dataSource" ref="dataSource" /><property name="hibernateProperties" ><props><prop key="dialect">${hibernate.dialect}</prop><prop key="show_sql">${hibernate.show.sql}</prop><prop key="hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop></props></property><!-- 扫描hibernate注解实体 --><property name="packagesToScan"><list><value>com.lyyzoo.*.entity</value></list></property></bean><!-- jdbcTemplate --><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource"/></bean><bean id="namedParameterJdbcTemplate" class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate"><constructor-arg ref="dataSource"/></bean><bean id="jdbcTemplateSupport" class="com.lyyzoo.data.jdbc.JdbcTemplateSupport"><property name="dataSource" ref="dataSource"/><property name="namedParameterJdbcTemplate" ref="namedParameterJdbcTemplate"/></bean><!-- 事务管理器 --><bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager"><property name="sessionFactory" ref="sessionFactory" /></bean><!-- 事务通知属性 --><tx:advice id="transactionManagerAdvice" transaction-manager="transactionManager"><tx:attributes><tx:method name="get*"        read-only="true"         /><tx:method name="load*"        read-only="true"        /><tx:method name="find*"        read-only="true"        /><tx:method name="list*"        read-only="true"        /><tx:method name="page*"        read-only="true"        /><tx:method name="query*"    read-only="true"        /><tx:method name="*"            propagation="REQUIRED"    /></tx:attributes></tx:advice><!-- AOP 事务 --><aop:config proxy-target-class="true"><aop:pointcut id="serviceMethod" expression="execution(* com.lyyzoo..*Service.*(..))"/><aop:advisor pointcut-ref="serviceMethod" advice-ref="transactionManagerAdvice"/></aop:config><!-- 扫描注解 --><context:component-scan base-package="com.lyyzoo" /></beans>

然后在 com.lyyzoo.data.domain 包下,Page 封装了分页相关的属性,如当前页数据、页码、每页大小、总页数等。com.lyyzoo.data.util 包下,Sqls 封装了操作 SQL 语句的工具,比如根据传入的查询语句,返回查询总数的 SQL 语句。在 com.lyyzoo.data.jdbc 包下,JdbcTemplateSupport 封装了比较复杂的查询,比如根据传入的参数、分页条件等,自动查询数据、总数并封装到 Page 里返回。com.lyyzoo.data.dao 包下,SimpleDao 封装了基于 Hibernate SessionFactory 的简单的增删改查操作,如 save(),get()等方法。dao 包下,BaseDao 继承 SimpleDao,并代理了 JdbcTemplateSupport,使得 BaseDao 具有 SimpleDao 和 JdbcTemplateSupport 的功能,BaseDao 则作为其它 dao 的一个父类存在。最后,在 com.lyyzoo.service 包下,BaseService 代理了 BaseDao,进行了进一步的封装,BaseService 是其它 service 类的父类,其它 service 就可以直接调用 save、get、page 等内置方法。

(4) lyyzoo-starter-web

lyyzoo-starter-web 自然跟 Web 相关,在 com.lyyzoo.web 包下,BaseController 作为 controller 类的父类,主要封装了返回结果集等信息。还有 Web 相关配置,如视图解析器等内容:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns="http://www.springframework.org/schema/beans"xmlns:beans="http://www.springframework.org/schema/beans"xmlns:tx="http://www.springframework.org/schema/tx"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:context="http://www.springframework.org/schema/context"xmlns:mvc="http://www.springframework.org/schema/mvc"xmlns:task="http://www.springframework.org/schema/task"xmlns:util="http://www.springframework.org/schema/util"xmlns:jee="http://www.springframework.org/schema/jee"xmlns:jdbc="http://www.springframework.org/schema/jdbc"xmlns:tool="http://www.springframework.org/schema/tool"xmlns:dwr="http://www.directwebremoting.org/schema/spring-dwr"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsdhttp://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsdhttp://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsdhttp://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.2.xsdhttp://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsdhttp://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsdhttp://www.springframework.org/schema/tool http://www.springframework.org/schema/tool/spring-tool.xsdhttp://www.directwebremoting.org/schema/spring-dwr http://www.directwebremoting.org/schema/spring-dwr-3.0.xsd"><description>Spring Web</description><!-- 加载config.properties --><context:property-placeholder location="classpath*:/config/*.properties" file-encoding="UTF-8" /><!-- 扫描Controller以及ControllerAdvice --><context:component-scan base-package="com.lyyzoo" use-default-filters="false"><context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/><context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/></context:component-scan><!-- 静态资源映射 --><mvc:resources location="/static/" mapping="/static/**"/><!-- 容器默认的DefaultServletHandler处理 所有静态内容与无RequestMapping处理的URL--><mvc:default-servlet-handler /><!-- 支持@Controller注解 --><mvc:annotation-driven /><!-- 视图解析器 --><bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"><property name="prefix" value="/WEB-INF/view"/><property name="suffix" value=".jsp"/></bean></beans>

(5) 类结构图

类结构图参考《底层类结构.vsd》

五、数据库与实体设计

​ 在开始开发一个系统之前,首先需要做的就是根据需求分析设计系统的实体对象以及对应的数据库表结构,这是开发的基础。

根据前面的需求分析设计的功能模块,实体对象可以分为 5 个模块,分别是系统模块(system)、基础模块(base)、采购模块(purchase)、销售模块(sale)、库存模块(stock)。下面是实体清单:

有了清单之后,利用 PowerDesigner 进行数据库物理模型设计。由于拥有对数据库的完全控制权,所以不对表设置约束,所有的约束在程序代码中进行控制。下面列出各个实体的属性即对应的表,具体可参考《数据库物理模型.pdm》。物理模型设计完成后,创建名为 gpss 的数据库,然后创建各个表。

数据库模型:

六、系统功能实现

1.创建工程

需求分析做完了,技术没问题,底层架构也设计好了,数据库设计好了,前面的所有准备工作做完了,下面就要进行燃气管进销存系统的编码实现了。首先要做的工作就是创建工程,项目名拟为 gpss,即燃气管进销存(Gas Purchase Sale Stock)的缩写,工程名则为 lyyzoo-gpss。

在 IDEA 中创建 lyyzoo-gpss 的 maven 工程,继承 lyyzoo。同时,在 lyyzoo-gpss 下创建两个子模块,分别为 lyyzoo-gpss-base 和 lyyzoo-gpss-web,base 模块包含了系统的 dao、entity、service 等层次,主要为 Java 文件;Web 则包含了 controller 层、JSP、js 等 Web 相关资源文件。

lyyzoo-gpss 目录结构:

lyyzoo-gpss > pom.xml:

<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><parent><groupId>com.lyyzoo</groupId><artifactId>lyyzoo</artifactId><version>1.0-SNAPSHOT</version></parent><groupId>com.lyyzoo.gpss</groupId><artifactId>lyyzoo-gpss</artifactId><name>lyyzoo :: gpss</name><packaging>pom</packaging><modules><module>lyyzoo-gpss-base</module><module>lyyzoo-gpss-web</module></modules><profiles><!-- 开发环境 --><profile><id>dev</id><activation><property><name>env</name><value>dev</value></property></activation></profile><!-- 线上环境 --><profile><id>online</id><activation><property><name>env</name><value>online</value></property></activation></profile></profiles><build><plugins><plugin><groupId>com.juvenxu.portable-config-maven-plugin</groupId><artifactId>portable-config-maven-plugin</artifactId><version>1.1.5</version><executions><execution><goals><goal>replace-package</goal></goals></execution></executions><configuration><portableConfig>src/main/resources/portable/config-${env}.xml</portableConfig></configuration></plugin></plugins></build></project>

lyyzoo-gpss-base 主要是 dao 层、service 层、model 层的集成,所以需要依赖于底层 lyyzoo-starter-jpa、lyyzoo-starter-web。

lyyzoo-gpss-base > pom.xml:

<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><parent><groupId>com.lyyzoo.gpss</groupId><artifactId>lyyzoo-gpss</artifactId><version>1.0-SNAPSHOT</version></parent><artifactId>lyyzoo-gpss-base</artifactId><name>lyyzoo :: gpss :: base</name><packaging>jar</packaging><dependencies><dependency><groupId>com.lyyzoo</groupId><artifactId>lyyzoo-starter-jpa</artifactId></dependency><dependency><groupId>com.lyyzoo</groupId><artifactId>lyyzoo-starter-web</artifactId></dependency></dependencies></project>

lyyzoo-gpss-web 是 Web 相关,是 controller 层所在。依赖于 lyyzoo-gpss-base、lyyzoo-starter-base 等。

lyyzoo-gpss-web > pom.xml:

<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/maven-v4_0_0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>com.lyyzoo.gpss</groupId><artifactId>lyyzoo-gpss</artifactId><version>1.0-SNAPSHOT</version></parent><artifactId>lyyzoo-gpss-web</artifactId><name>lyyzoo :: gpss :: web</name><packaging>war</packaging><dependencies><dependency><groupId>com.lyyzoo.gpss</groupId><artifactId>lyyzoo-gpss-base</artifactId><version>${project.version}</version></dependency><dependency><groupId>com.lyyzoo</groupId><artifactId>lyyzoo-starter-base</artifactId></dependency><dependency><groupId>com.lyyzoo</groupId><artifactId>lyyzoo-starter-jpa</artifactId></dependency><dependency><groupId>com.lyyzoo</groupId><artifactId>lyyzoo-starter-web</artifactId></dependency><dependency><groupId>com.lyyzoo</groupId><artifactId>lyyzoo-starter-test</artifactId></dependency></dependencies><build><finalName>gpss</finalName><outputDirectory>src/main/webapp/WEB-INF/classes</outputDirectory></build></project>

2.系统配置

工程建好后,首要要做的就是系统的配置工作了,如 web.xml,这应该算是 Web 项目的起点了。进入 lyyzoo-gpss-web/src/main/webapp/WEB-INF/web.xml,进行 Web 的配置,主要的一些配置有加载系统的配置文件、Spring、字符过滤器、SpringMVC 等配置。

一些基础的配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://java.sun.com/xml/ns/javaeehttp://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"version="3.0"><display-name>lyyzoo :: gpss</display-name><!-- 加载配置文件 --><context-param><param-name>contextConfigLocation</param-name><param-value>classpath*:/spring/spring-base*.xml</param-value></context-param><!-- Spring --><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener><!-- 编码过滤器 --><filter><filter-name>encodingFilter</filter-name><filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class><init-param><param-name>encoding</param-name><param-value>UTF-8</param-value></init-param><init-param><param-name>forceEncoding</param-name><param-value>true</param-value></init-param></filter><filter-mapping><filter-name>encodingFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping><!-- 访问控制 --><filter><filter-name>VisitFilter</filter-name><filter-class>com.lyyzoo.gpss.filter.VisitFilter</filter-class></filter><filter-mapping><filter-name>VisitFilter</filter-name><url-pattern>/admin/*</url-pattern></filter-mapping><!-- Spring MVC --><servlet><servlet-name>SpringMVC</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>classpath*:/spring/spring-web*.xml</param-value></init-param><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>SpringMVC</servlet-name><url-pattern>/</url-pattern></servlet-mapping><!-- 错误页面 --><error-page><error-code>404</error-code><location>/error/404</location></error-page><error-page><error-code>500</error-code><location>/error/500</location></error-page><error-page><exception-type>java.lang.Throwable</exception-type><location>/error/500</location></error-page><!-- 首页 --><welcome-file-list><welcome-file>/</welcome-file></welcome-file-list></web-app>

接着,配置系统将会用到的一些属性,如 JDBC 驱动、数据库用户名和密码等。在 lyyzoo-gpss-web/src/main/resources/config 下,创建 config.properties 配置文件,这个配置文件中的属性将会被底层 Spring 配置的文件所引用。

比如 JDBC 的属性:

####################################
#            DATABASE
####################################
# local_db
jdbc.driver=net.sf.log4jdbc.DriverSpy
jdbc.url=jdbc:log4jdbc:mysql://localhost:3306/gpss?useUnicode=true&characterEncoding=utf-8&autoReconnect=true&failOverReadOnly=false
jdbc.username=root
jdbc.password=root# 初始化连接
c3p0.initialPoolSize=5
# 连接池保留最小连接数
c3p0.minPoolSize=5
# 连接池保留最大连接数
c3p0.maxPoolSize=15
# 最大空闲时间
c3p0.maxIdleTime=600#hibernate
hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
hibernate.show.sql=false
hibernate.hbm2ddl.auto=update

但是上面的配置只是本机的一个开发环境,如果我将项目发布到生产环境,那就至少需要重新修改数据库地址、用户名和密码。这样是比较麻烦的,所以,在 lyyzoo-gpss-web/src/main/portable 下创建两个 XML 文件,分别为开发环境和生产环境的:config-dev.xml 和 config-online.xml。

config-online.xml:

![](https://www.writebug.com/myres/static/uploads/2022/1/26/b3ff4f808ceb1d2e9f048fb234c43589.writebug

<?xml version="1.0" encoding="utf-8" ?><portable-config><config-file path="WEB-INF/classes/config/config.properties"><!-- JDBC --><replace key="jdbc.driver"><![CDATA[com.mysql.jdbc.Driver]]></replace><replace key="jdbc.url"><![CDATA[jdbc:mysql://192.168.1.91:30112/fff2f025c2b04?useUnicode=true&characterEncoding=utf-8]]></replace><replace key="jdbc.username">a6564a1169d94</replace><replace key="jdbc.password">d3e6d1aea5e04</replace><!-- hibernate --><replace key="hibernate.show.sql">false</replace><replace key="hibernate.hbm2ddl.auto">none</replace><!-- debug --><replace key="app.debug">false</replace><replace key="app.env">online</replace><replace key="logback.level">INFO</replace><replace key="jdbc.resultsettable">ERROR</replace></config-file>
</portable-config>

然后配置一个“不同环境打包”的 maven 插件——“portable-config-maven-plugin”,通过该插件,就可以在打包的时候加上需要打包的环境,例如指定 online 环境,在打包时就会将 config-online.xml 中的属性替换到 config.properties 里,这样一来就不必我们手动去替换了。配置好之后,我们在打包时可以使用命令[mvn clean package –Denv=online]打包线上环境的 war 包。

maven 环境配置,在 lyyzoo-gpss > pom.xml 中配置两个环境:

<profiles><!-- 开发环境 --><profile><id>dev</id><activation><property><name>env</name><value>dev</value></property></activation></profile><!-- 线上环境 --><profile><id>online</id><activation><property><name>env</name><value>online</value></property></activation></profile>
</profiles>

不同环境打包插件(portable-config-maven-plugin)的配置:

<build><plugins><plugin><groupId>com.juvenxu.portable-config-maven-plugin</groupId><artifactId>portable-config-maven-plugin</artifactId><version>1.1.5</version><executions><execution><goals><goal>replace-package</goal></goals></execution></executions><configuration><portableConfig>src/main/resources/portable/config-${env}.xml</portableConfig></configuration></plugin></plugins>
</build>

3.模块分层

3.1lyyzoo-gpss-base

工程建好后,创建包的结构。按照一般的分层方式,分为 dao 层、entity 层、service 层,同时,每层下按模块划分为 system、base、purchase、sale、stock。然后在 entity 下根据表设计创建实体类。

lyyzoo-gpss-base 目录结构:

3.2lyyzoo-gpss-web

然后是 lyyzoo-gpss-web 模块,该模块主要是 controller 层,以及静态资源文件、JSP 文件等。com.lyyzoo.gpss.web 作为 controller 层的包,同样,在 Web 下按系统模块划分。

lyyzoo-gpss-web 目录结构:

3.3 静态资源文件

lyyzoo-gpss-web/src/main/webapp/static 作为静态文件的根目录,static/lib 目录作为三方类库的根目录,如 ExtJs、jQuery、其它的插件等。static/css 是系统 CSS 文件的根目录;static/img 是图片的根目录;static/js 是系统 js 文件根目录,/js 下同样按模块划分。

静态资源文件目录结构:

3.4 JSP 文件

JSP 文件不能直接让用户访问,需要放到/WEB-INF 下,与配置的 Spring 视图解析器相对应,所有的 JSP 文件放到/WEB-INF/view 目录下,view 目录下按模块划分,index.jsp 是系统的登录页面。/WEB-INF/layout/目录下,将 JSP 中需要引入的一些资源等做了整合,如 ExtJs 的文件、meta 描述信息、taglib 等,整合后,JSP 中如果需要引入整合 JSP 即可,可减少很多重复的工作。

taglib.jsp 中引入了标签和设置了资源的路径:

<%@ page contentType="text/html;charset=UTF-8" language="java" %><%-- 引入标签 --%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@taglib prefix="sf" uri="http://www.springframework.org/tags/form" %><%-- 资源路径 --%>
<c:set var="CTX" value="${pageContext.request.contextPath}" />
<c:set var="STATIC_CTX_URL" value="${CTX}/static" />
<c:set var="LIB" value="${STATIC_CTX_URL}/lib" />
<c:set var="JS" value="${STATIC_CTX_URL}/js"/>
<c:set var="CSS" value="${STATIC_CTX_URL}/css"/>
<c:set var="IMG" value="${STATIC_CTX_URL}/img"/>

meta.jsp 中主要设置了一些 meta 描述信息和 ICO 图标:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ include file="/WEB-INF/layout/taglib.jsp" %><meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=9,chrome=1"><meta name="description" content="">
<meta name="author" content="">
<meta name="renderer" content="webkit">
<%-- 图标 --%>
<link type="image/x-icon" href="${IMG}/favicon.ico" rel="icon">

extjs-neptune.jsp 则引入了 ExtJs 相关的 CSS 和 js 文件,以及 jQuery 等:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ include file="/WEB-INF/layout/taglib.jsp" %><link rel="stylesheet" type="text/css" href="${LIB}/ext/4.2.2/theme/ext-theme-neptune/ext-theme-neptune-all.css"/>
<link rel="stylesheet" type="text/css" href="${LIB}/ext/4.2.2/icons/icon.css"/><script type="text/javascript" src="${LIB}/ext/4.2.2/ext-all.js"></script>
<script type="text/javascript" src="${LIB}/ext/4.2.2/locale/ext-lang-zh_CN.js"></script>
<script type="text/javascript" src="${LIB}/jquery/2.1.1/jquery.js"></script>
<script type="text/javascript" src="${JS}/Global.js"></script><script type="text/javascript">window.CTX             = "${CTX}";window.STATIC_CTX_URL  = "${STATIC_CTX_URL}";window.LIB             = "${LIB}";window.JS              = "${JS}";window.CSS             = "${CSS}";window.IMG             = "${IMG}";
</script>

WEB-INF 目录结构:

3.4 登录实现举例

首先创建一个 BaseController,BaseController 继承底层的 BaseController,增加了 HttpSession,以及获取当前登录用户的方法,这样其它的 controller 继承该 BaseController 后,就可以非常方便的获得当前 session 和登录用户了。

BaseController 代码如下:

package com.lyyzoo.gpss.web;import com.lyyzoo.gpss.entity.system.User;
import org.springframework.beans.factory.annotation.Autowired;import javax.servlet.http.HttpSession;/**** <p>** @author bojiangzhou* @date 2017-04-02*/
public class BaseController extends com.lyyzoo.web.BaseController {@Autowiredprotected HttpSession session;public User getCurrentUser(){return (User) session.getAttribute("currentUser");}public Long getCurrentUserId(){return getCurrentUser().getId();}public String getCurrentUserAccount(){return getCurrentUser().getAccount();}}

创建 HomeController 作为登录和主页的处理器。主要包含的方法有访问登录页面,访问登录后的主页,以及登录处理等。Controller 需要加上@Controller 标注该类为 controller,使用@RequestMapping()支持访问 rest 形式的地址访问。HomeController 中注入 UserService,用于处理用户登录相关的业务。

用户进入登录界面,JSP 页面以 <img src=” ${CTX}/vcode”> 的形式请求验证码,验证码使用工具类生成,以流的形式输出,生成的验证码保存到 session 中。用户输入登录账号、密码和验证码登录系统。首先前台会检测输入是否为空等,传到后台,从 session 中取出验证码判断验证码是否正确,不正确则刷新验证码并且需要用户重新输入验证码。验证码通过后,使用登录账号和密码查找数据库,如果有,则将该用户保存到 session 中,跳转到管理页面,登录成功。否则提示用户名或密码错误。

HomeController 代码如下:

package com.lyyzoo.gpss.web;import com.lyyzoo.gpss.entity.system.User;
import com.lyyzoo.gpss.service.system.UserService;
import com.lyyzoo.gpss.util.VCodeGenerator;
import com.lyyzoo.util.Cryptos;
import com.lyyzoo.util.Strings;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.image.BufferedImage;
import java.io.IOException;/*** <p>** @author bojiangzhou* @date 2017-03-29*/
@Controller
@RequestMapping("")
public class HomeController extends BaseController {@Autowiredprivate UserService userService;/*** 到首页/登录页面*/@RequestMapping(value = {"", "/", "/index", "/login"})public String index(){return "/index";}/*** 管理员主页*/@RequestMapping("/admin/home")public String toHome(){return "/home/home";}/*** 登录*/@RequestMapping(value = "/login", method = RequestMethod.POST)public String login(String account, String password, String vcode, HttpSession session){String redirect = REDIRECT("/login");//基本验证if(Strings.isNullOrEmpty(account)){session.setAttribute("errorMsg", "账号必须填写!");return redirect;}if(Strings.isNullOrEmpty(password)){session.setAttribute("errorMsg", "密码必须填写!");return redirect;}if(Strings.isNullOrEmpty(vcode)){session.setAttribute("errorMsg", "验证码必须填写!");return redirect;}//验证码String sessionVcode = (String) session.getAttribute("vcode");if(!vcode.equalsIgnoreCase(sessionVcode)){session.setAttribute("errorMsg", "验证码错误!");return redirect;}//验证用户名和密码password = Cryptos.encryptMd5(password);User loginUser = userService.login(account, password);if(loginUser == null){session.setAttribute("errorMsg", "账号或密码错误!");return redirect;}if(loginUser.getIsLocked() == User.IsLocked.YES){session.setAttribute("errorMsg", "账号已锁定,不能登录!");return redirect;}//保存到session的时候清除密码User currentUser = new User();BeanUtils.copyProperties(loginUser, currentUser);currentUser.setPassword(null);//登录成功session.setAttribute("currentUser", currentUser);return REDIRECT("/admin/home");}/*** 获取验证码*/@RequestMapping("/vcode")public void getVCode(HttpSession session, HttpServletResponse response) throws IOException {//创建验证码生成器对象VCodeGenerator vcGenerator = new VCodeGenerator();//生成验证码String vcode = vcGenerator.generatorVCode();//将验证码保存在session域中,以便判断验证码是否正确session.setAttribute("vcode", vcode);//生成验证码图片BufferedImage vImg = vcGenerator.generatorRotateVCodeImage(vcode, true);//输出图像ImageIO.write(vImg, "gif", response.getOutputStream());}/*** 退出系统*/@RequestMapping("/logoff")public String logoff(HttpSession session){session.invalidate();return REDIRECT("/");}@RequestMapping("/function")public String function(){return "/home/function";}@RequestMapping("/welcome")public String welcome(){return "/home/welcome";}/*** 错误页面* @param code* @return*/@RequestMapping("/error/{code}")public String error(@PathVariable String code) {return "/error/" + code;}}

UserService 中根据用户名和密码获取用户:

package com.lyyzoo.gpss.service.system;@Service
public class UserService extends BaseService<User> {@Autowiredprivate UserDao userDao;/*** 获取登录用户*/public User login(String account, String password){Map<String, Object> filter = new HashMap<>();filter.put("account", account);filter.put("password", password);filter.put("state", Applications.Flag.YES);User loginUser = get(filter);return loginUser;}
}

♻️ 资源

大小: 53.4MB
➡️ 资源下载:https://download.csdn.net/download/s1t16/87392408

基于Java+MySQL实现燃气管进销存管理系统【100010498】相关推荐

  1. python基于PHP+MySQL的药店药品进销存管理系统

    随着科技的发展,针对不同疾病的药品越来越多,不同的药品有不同的属性,用法用量等内容,如何让药店和医药公司更好的对药品进行管理,是很多人都在研究的问题,本系统就是在这样的一个基础上开发出来的 PHP药店 ...

  2. 基于PHP+MySQL的药店药品进销存管理系统

    随着科技的发展,针对不同疾病的药品越来越多,不同的药品有不同的属性,用法用量等内容,如何让药店和医药公司更好的对药品进行管理,是很多人都在研究的问题,本系统就是在这样的一个基础上开发出来的 PHP药店 ...

  3. javaweb仓库管理系统的实现,基于ssm+mysql实现的WMS进销存出库入库系统

    javaweb仓库管理系统的实现,基于ssm+mysql实现的WMS进销存出库入库系统 感兴趣的朋友可以家 3060912346 主要技术 SpringBoot\SSM(两个版本都有) HTML.jQ ...

  4. Java毕设项目珠宝首饰进销存管理系统(java+VUE+Mybatis+Maven+Mysql)

    Java毕设项目珠宝首饰进销存管理系统(java+VUE+Mybatis+Maven+Mysql) 项目运行 环境配置: Jdk1.8 + Tomcat8.5 + Mysql + HBuilderX( ...

  5. JAVA计算机毕业设计珠宝首饰进销存管理系统Mybatis+系统+数据库+调试部署

    JAVA计算机毕业设计珠宝首饰进销存管理系统Mybatis+系统+数据库+调试部署 JAVA计算机毕业设计珠宝首饰进销存管理系统Mybatis+系统+数据库+调试部署 本源码技术栈: 项目架构:B/S ...

  6. java计算机毕业设计珠宝首饰进销存管理系统源码+数据库+系统+lw文档

    java计算机毕业设计珠宝首饰进销存管理系统源码+数据库+系统+lw文档 java计算机毕业设计珠宝首饰进销存管理系统源码+数据库+系统+lw文档 本源码技术栈: 项目架构:B/S架构 开发语言:Ja ...

  7. Java毕设项目珠宝首饰进销存管理系统计算机(附源码+系统+数据库+LW)

    Java毕设项目珠宝首饰进销存管理系统计算机(附源码+系统+数据库+LW) 项目运行 环境配置: Jdk1.8 + Tomcat8.5 + Mysql + HBuilderX(Webstorm也行)+ ...

  8. java基于ssm+vue的企业通用进销存管理系统 element

    随着经济的发展和信息技术的普及,国内许多企业都面临了重大的挑战.企业的管理流程.战略规划如果不能进行调整,极有可能面临淘汰的风险.特别是美妆企业,面对大量的美妆产品和进销售管理,如果不使用信息系统进行 ...

  9. Java、JSP医院药品进销存管理系统

    技术:Java.JSP等 摘要: 近些年,在淘宝网变得越来越家喻户晓的同时,人们从最初对网络销售模式的不信任慢慢转变成一种购物的依赖.在此形势下,我国各领域企业都跻身于网络.药品从古至今都是人们日常生 ...

最新文章

  1. ZooKeeper 源码和实践揭秘
  2. SpringBoot配置文件放在jar外部
  3. Django中html里的分页显示
  4. python快速写入hbase_Python生成HBase 10w+ 条数据说明
  5. nodejs+html转换pdf,Nodejs中使用phantom将html转为pdf或图片格式的方法.pdf
  6. Java 集合系列(4): LinkedList源码深入解析2
  7. 板框导入_板框结构导入有问题?这几个问题最常见,附解决方法!
  8. java中session的作用_java中session的工作原理是什么?和Cookies有何区别?
  9. Oracle笔记 五、创建表、约束、视图、索引、序列、同义词、表空间
  10. vue2.0的Element UI的表格table列时间戳格式化
  11. java正则过滤小括号,java正则表达式获取大括号小括号内容并判断数字和小数亲测可用...
  12. Cookie起源与发展
  13. java青蛙跳井_数学运算归纳
  14. 如何做私域?私域流量运营怎么做?为什么今年都布局企业微信运营?(附企微运营干货)
  15. AUTOSAR DCM
  16. 2019年安徽大学ACM/ICPC实验室新生赛
  17. 难得起了一个大早^_^
  18. pywifi破解密码
  19. 移动端开发之Web App开发
  20. 使用TF Service搭建在线服务:part-1

热门文章

  1. 2021-09-06尤破金9.6晚间黄金走势迎来强势,后市白银原油走势分析及操作建议
  2. 英语句式参考纯享版 - 状语从句
  3. Android 7.0 Launcher3的启动和加载流程分析----转载
  4. 高级系统架构师培训公开课举行
  5. 问题解决——SolidWorks 已停止工作 (Windows7 + SolidWorks 2010 SP0.0)
  6. android超级课程表
  7. 大数据知识框架汇总(四)
  8. 两亲性嵌段共聚物聚苯乙烯-聚丙烯酸(PS-PAA)/载药纳米粒子
  9. 寒霜引擎(镜之边缘:催化剂)中的屏幕空间反射
  10. 快逸报表数据源找不到的一个原因