4년제 대학교 졸업을 앞두고 있습니다!
대학 시절 마지막 블로그로, 졸업 프로젝트를 요약하고 공유하기 위한 블로그입니다. 제가 선택한 논문 제목은 "가스 파이프라인 네트워크 장비 및 기기 구매, 판매 및 재고 관리 시스템의 백엔드 설계"입니다. 우리 전공에서 제가 유일한 기술 경로를 택하고 있기 때문에 전체 시스템의 설계 및 개발을 완료했습니다. 거의 한 달 가까이 걸린 제 자신의 노력이 마침내 훌륭한 결과를 얻었습니다.
여기에서는 논문에 대해 논의하거나 구체적인 구현 세부 사항을 기록하지 않을 것입니다. 주로 자신만의 시스템 프레임워크를 구축하고 시스템 구현을 단계별로 설명하고, 초보자들이 서로에게서 배울 수 있는 경험을 공유할 것입니다. 전문가들은 이를 나의 기여로 간주할 수 있습니다! !
블로그 마지막에는 시스템 개발과 관련된 모든 서류가 첨부될 예정이지만, 졸업 논문은 제외하고 이 글에는 일반적으로 논문 내용이 포함되어 있습니다!
위는 단순히 시스템 테스트를 완료할 수 있습니다. war 패키지를 다운로드하고 보기 위해 자신의 tomcat에 배포하세요.
(간단한) 시스템을 개발하기 위해 가장 먼저 하고 싶은 일은 시스템 요구 사항을 분석하고 왜 이 시스템을 구축하려는지, 이 시스템에는 어떤 기능 모듈이 있는지, 각 기능은 어떤 기능을 구현하는지 파악하는 것입니다.
물론 이곳에 온 주된 목적은 졸업 프로젝트를 완수하고 졸업 논문을 제출하는 것입니다. 하지만 단순히 졸업 프로젝트를 완성하기 위해 이 시스템을 개발한 것은 아닙니다. 주요 아이디어는 이 구매, 판매 및 재고 관리 시스템의 개발을 예로 들어 요구 사항 확인, 기술 선택, 아키텍처 설계, 시스템 구현부터 테스트 배포까지 시스템의 전체 개발 프로세스를 자세히 설명하는 것입니다. 인턴십 등을 통해 얻은 지식, 기술, 경험을 종합적으로 활용하여 시스템을 완성하고 더 효과적으로 구현합니다. 기본 시스템 프레임워크를 구축하고 특정 사양을 구성한 후 이를 기반으로 개발하면 프레임워크 구축, 종속성 추가, 구성 등의 작업을 많이 줄일 수 있습니다.
이번 개발의 주요 업무와 의의는 다음과 같습니다.
①사용자 관점에서 사용자 요구를 분석하는 방법을 배우고, 완벽한 수요 분석 및 디자인 등을 수행합니다.
② 다양한 관련 개발 및 디자인 도구, 오픈 소스 소프트웨어 사용에 능숙합니다.
③ Spring+SpringMVC+Hibernate+ExtJs 개발 기술에 능숙하다.
4 Maven 버전 관리 도구 사용에 능숙합니다.
⑤ 기업 입장에서 자신만의 기본 프레임워크를 구축해 보세요.
⑥완전한 가스관 구매, 판매, 재고 관리 시스템을 구축하고 테스트를 실시하고 결과를 분석합니다.
⑦시스템을 인터넷에 배포하여 실제 웹 애플리케이션을 구현합니다.
먼저 시스템의 요구사항을 분석하기 위해 가장 먼저 이해해야 할 것은 구매, 판매 및 재고 시스템이 무엇인지입니다. 구매, 판매 및 재고 시스템을 공급망이라고도 합니다. 관리 시스템의 가장 기본적인 컨텐츠는 조달, 재고, 판매, 반품 관리입니다. 구매, 판매 및 재고 시스템은 기업의 생산 및 운영에 있어 구매, 창고 보관 및 판매를 추적하고 관리합니다. 구매 주문부터 창고에 입고되는 상품까지 모든 단계가 추적되고 기록됩니다. 창고에서 매진되었습니다. 기업의 유통관리 등 비즈니스 문제를 효과적으로 해결합니다. 그렇다면 가스관 구매, 판매, 재고 시스템의 차이점은 무엇일까요? 사실 구매, 판매, 재고 시스템에는 이미 일반 상품의 구매, 판매, 재고 기능이 있고, 가스관은 상품입니다. 이를 출발점으로 하여 시스템 기능 모듈을 설계하기 시작했습니다.
시스템은 기본설정, 조달관리, 판매관리, 재고관리, 통계분석, 시스템관리 등 6가지 주요 모듈로 구분됩니다. 시스템에서 설정하는 역할에는 관리자, 구매자, 영업사원, 재고 관리자 등이 포함됩니다.
시스템 모듈 구조(xmind를 사용하여 설계):
시스템의 전체 프로세스는 처음 사용부터 시작하여 모든 권한을 가진 최고 관리자(admin)를 설정합니다. 시스템의 권한. 시스템에 관리자로 로그인하고 역할(시스템 관리자, 구매자, 영업사원, 재고 관리자)을 설정하고 해당 권한을 할당합니다. 그런 다음 사용자 관리를 입력하고 시스템 사용자를 입력하십시오. 일반 관리자는 시스템에 로그인하여 기본 데이터를 입력해야 하며, 구매자는 공급업체, 구매 주문 및 반품 주문을 입력해야 합니다. 재고 관리자는 재고 관리에서 구매 검토 및 판매 검토를 수행해야 합니다. 구매 검토가 통과되면 상품이 창고에 입고되고 판매 검토가 통과되면 상품이 출고됩니다. 창고와 재고가 줄어들 것입니다. 관리자는 월간 구매 통계 및 판매 통계도 볼 수 있습니다.
전체 시스템 프로세스(visio를 사용하여 설계):
일단 요구 사항이 결정되면 구체적인 개발 단계에 진입해야 합니다. 먼저 어떤 기술과 개발을 결정해야 합니다. 도구는 시스템을 개발하는 데 사용됩니다.
overridhood\ 5.1
서버: Tomcat 8 .5
개발 프레임워크: Spring4 + SpringMVC + Hibernate5
프런트 엔드 프레임워크: ExtJs 4.2 + Jsp
모델링 도구: PowerDesigner, Visio
1.maven
Maven Apache Software Foundation에서 유지 관리하는 자동화된 빌드 도구로, Java 플랫폼의 프로젝트 구성 및 종속성 관리에 중점을 둡니다. 구성 요소와 타사 오픈 소스 라이브러리를 자동으로 다운로드하는 데 도움이 되는 중앙 창고를 제공합니다. 프로젝트에서 jar 패키지를 좌표 방식으로 사용하기만 하면 Maven이 자동으로 중앙 창고에서 이를 다운로드하고 동시에 이 jar 패키지가 의존하는 다른 jar 패키지를 다운로드하며 소스를 다운로드할 수 있습니다. 읽기용 코드입니다. Maven을 사용한 후에는 각 jar 패키지 자체의 복사본 하나만 로컬 창고에 저장되므로 저장 공간이 크게 절약되고 프로젝트가 더 가벼워지며 너무 많은 중복 파일로 인한 혼란을 방지할 수 있습니다. 동시에 Maven은 수동 참여 없이 현재 jar 패키지가 의존하는 다른 모든 jar 패키지를 자동으로 가져올 수 있으므로 많은 시간과 에너지를 절약할 수 있습니다. Maven을 사용하면 단 하나의 간단한 명령으로 정리, 컴파일, 테스트, 패키징 및 배포의 전체 프로세스를 자동으로 완료할 수 있습니다. 우리 프로젝트는 일반적으로 개발 환경과 프로덕션 환경으로 구분되며, 서로 다른 환경은 서로 다른 구성 파일에 해당합니다. Maven을 사용하면 두 가지 환경을 구성할 수 있으며, 이를 실행 환경으로 지정하면 해당 구성 파일을 대체할 수 있습니다. 이로 인해 수동 작업이 줄어듭니다. 그리고 가능한 작동 오류.
2.Intellij IDEA
IDEA는 Java 언어 개발을 위한 통합 환경으로 Intellij는 최고의 Java 개발 도구 중 하나로 인정받고 있습니다. IDEA는 자동 코드 프롬프트, 리팩토링, 디버깅 및 다양한 버전 도구(maven, svn 등)의 통합에 비교적 강력합니다. 저는 인턴십 중에 아이디어 개발로 전환했습니다. 저는 이전에 Eclipse를 사용해 왔습니다. Idea는 디버깅 및 자동 코드 프롬프트에 더 많은 이점이 있습니다. 프로젝트, 특히 다중 프로젝트 프로젝트는 보다 친숙한 디렉토리 구조를 가지고 있습니다. 물론 Eclipse는 Idea보다 사용하기 쉽습니다. Idea를 사용하면 개발 속도를 높일 수 있지만 많은 단축키를 기억해야 하는 경우에만 해당됩니다. 예를 들어, idea의 디버깅 기능을 사용하려면 단축키 Alt+F8을 누른 다음 표현식을 입력하면 디버깅 중에 값을 빠르게 평가할 수 있습니다. idea에서는 변수 뒤에 다양한 색상으로 변수 값이 표시됩니다. 디버깅의 모든 단계를 명확하게 알 수 있어 매우 편리합니다. IDEA를 잘 사용하면 개발 속도가 크게 향상될 수 있습니다.
ExtJ는 리치 클라이언트 Ajax 애플리케이션을 개발하는 데 사용할 수 있습니다. 백엔드 기술과는 아무런 관련이 없는 자바스크립트로 작성된 프런트엔드 Ajax 프레임워크입니다. 주로 프런트엔드 사용자 인터페이스를 만드는 데 사용됩니다. 차트 통계 등 강력한 데이터 처리 기능을 갖추고 있습니다. 동시에 ExtJs에는 선택할 수 있는 개인화된 테마가 많이 있으므로 백엔드 관리 시스템 개발에 적합한 선택입니다.
구매, 판매 및 재고 시스템을 설계하고 코딩하기 전에 먼저 이 기본 프레임워크를 나중에 다른 특정 프로젝트 개발의 기초로 사용할 수 있습니다. 프로젝트를 개발할 때 반복적인 작업이 많이 이루어집니다. 이 기본 프레임워크에는 주로 개발 사양과 일부 공통 도구 클래스가 포함되어 있습니다. 더 중요한 것은 Spring, Hibernate 및 다양한 구성 파일과 같은 범주별로 다양한 프레임워크를 소개한다는 것입니다. 동시에 향후 개발 중에 일부 새로운 기능이 추가되면 이 하위 레이어에 추가되어 지속적으로 개선될 수 있습니다.
프레임워크 설계를 수행하기 전에 소프트웨어 개발 프로세스를 원활하게 하고 코드의 신뢰성, 가독성 및 유지 관리성을 향상시키기 위해 가장 먼저 결정해야 할 것은 개발 사양입니다. 소프트웨어 개발에도 마찬가지입니다. 따라야 할 몇 가지 간단한 규칙은 다음과 같습니다.
가장 먼저 준수해야 할 것은 기본사양입니다. 일반적으로 회사에서는 파일 이름, 패키지 이름 등 모든 이름 지정의 기초로 도메인 이름을 사용합니다. 그래서 개인 도메인 이름으로 도메인 이름 [www.lyyzoo.com]을 신청했습니다. 그런 다음 D:/lyyzoo-repo를 개발용 루트 디렉터리, 즉 개인 코드 창고로 사용하면 모든 향후 프로젝트가 이 디렉터리에 구축됩니다. 모든 프로젝트 개발은 Maven을 사용하여 프로젝트를 관리하므로 디렉터리 구조는 표준 Maven 사양 디렉터리입니다.
maven이 동의한 디렉토리 구조:
① 이름 지정
> 가능한 경우 의견을 추가하십시오. 참고.
> 패키지 이름은 모두 소문자로 도메인 이름 + 모듈 형식입니다. 예: com.lyyzoo.service
> 단어는 대문자로 표시됩니다.
> 메소드 이름은 소문자로 시작하는 Camel 명명법을 채택하고 각 단어의 첫 글자는 소문자입니다. getter 및 setter는 Lombok을 사용하여 자동으로 생성됩니다. @Data 주석만 추가하면 됩니다.
> 변수명은 소문자로 시작하는 Camel 명명 방식을 채택하고 있으며, 각 단어의 첫 글자는 대문자로 표기합니다. 변수 이름은 너무 길지 않아야 하며 약어 형태도 가능하지만 이름의 의미가 명확해야 합니다.
> 상수 이름은 모두 대문자이며, 각 단어는 "_"로 구분됩니다.
②Layering
프로젝트는 기능적 모듈로 구분됩니다. 프로젝트마다 서로 다른 프로젝트를 빌드하고 관리를 위해 Maven 종속성을 사용합니다. 패키지의 기본 계층에는 컨트롤러(제어 계층), 서비스(비즈니스 계층), dao(데이터 액세스 계층) 및 엔터티(모델 계층)가 포함됩니다.
전체 프로젝트의 맨 아래 레이어는 공통적이고 기본적인 사항에 중점을 두며 향후 쉽게 재사용할 수 있도록 함께 통합됩니다. 먼저 lyyzoo라는 Maven 프로젝트를 생성합니다. lyyzoo는 기본 루트 디렉터리 역할을 합니다. lyyzoo에는 lyyzoo-base와 lyyzoo-starter라는 두 가지 주요 하위 모듈이 있습니다. lyyzoo-base는 기본 모듈이며 일부 간단한 Java 및 JavaEE 프로그램에 사용됩니다. lyyzoo-starter는 JavaEE와 관련되어 있으며 lyyzoo에 의존합니다. 기본이며 Spring 및 Hibernate와 같은 타사 프레임워크도 도입합니다. 그런 다음 각 모듈에 특정 하위 모듈을 추가합니다. 향후 개발에 사용해야 할 모듈은 종속성에 해당 모듈을 추가하기만 하면 됩니다.
기본 모듈 구조 다이어그램:
다음은 각 POM 간의 관계입니다.
① lyyzoo > pom.xml
② lyyzoo-base > m.
③ 리주 -starter > pom.xml 2.2 종속성 관리구조가 구축된 후에는 몇 가지 세부적인 종속성 구성 작업을 수행해야 합니다. lyyzoo는 모든 모듈의 상위 클래스이므로 공통 항목을 추가해야 합니다. lyyzoo 속성, 종속성 관리, Maven 플러그인 등 먼저 모든 버전 번호를 입력하고
1 <properties> 2 <!-- Global --> 3 <lyyzoo.version>1.0-SNAPSHOT</lyyzoo.version> 4 <java.version>1.8</java.version> 5 <maven.compiler.source>${java.version}</maven.compiler.source> 6 <maven.compiler.target>${java.version}</maven.compiler.target> 7 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 8 <!-- lombok --> 9 <lombok.version>1.16.14</lombok.version>10 <!-- log -->11 <slf4j.version>1.7.7</slf4j.version>12 <logback.version>1.1.3</logback.version>13 <!-- jdbc -->14 <mysql.version>5.1.38</mysql.version>15 <!-- -->16 <c3p0.version>0.9.5.2</c3p0.version>17 <!-- test -->18 <junit.version>4.12</junit.version>19 <!-- servlet -->20 <servlet.version>3.1.0</servlet.version>21 <!-- spring -->22 <spring.version>4.2.6.RELEASE</spring.version>23 <aspectjrt.version>1.7.3</aspectjrt.version>24 <aspectjweaver.version>1.7.3</aspectjweaver.version>25 <!-- hibernate -->26 <hibernate.version>5.0.1.Final</hibernate.version>27 <hibernate.jpa.version>1.0.0.Final</hibernate.jpa.version>28 </properties>
다음으로 종속성 관리를 도입하고 다른 프로젝트에서 사용할 모든 타사 jar 패키지의 종속성을 lyyzoo에 도입합니다. 모든 종속성은
① 먼저 lyyzoo-base-core, lyyzoo-starter-base 및 기타 모듈과 같은 lyyzoo에 다른 모듈을 도입해야 합니다.
1 <!-- lyyzoo --> 2 <dependency> 3 <groupId>com.lyyzoo</groupId> 4 <artifactId>lyyzoo-base-core</artifactId> 5 <version>${lyyzoo.version}</version> 6 </dependency> 7 <dependency> 8 <groupId>com.lyyzoo</groupId> 9 <artifactId>lyyzoo-base-data</artifactId>10 <version>${lyyzoo.version}</version>11 </dependency>12 <dependency>13 <groupId>com.lyyzoo</groupId>14 <artifactId>lyyzoo-starter-base</artifactId>15 <version>${lyyzoo.version}</version>16 </dependency>17 <dependency>18 <groupId>com.lyyzoo</groupId>19 <artifactId>lyyzoo-starter-jpa</artifactId>20 <version>${lyyzoo.version}</version>21 </dependency>
② JDBC 관련 jar 패키지에는 데이터베이스 연결 풀에 사용되는 c3p0, JDBC를 간단하고 쉽게 캡슐화하는 dbutils가 포함되어 있습니다.
1 <!-- jdbc --> 2 <dependency> 3 <groupId>com.mchange</groupId> 4 <artifactId>c3p0</artifactId> 5 <version>${c3p0.version}</version> 6 </dependency> 7 <dependency> 8 <groupId>mysql</groupId> 9 <artifactId>mysql-connector-java</artifactId>10 <version>${mysql.version}</version>11 </dependency>12 <dependency>13 <groupId>commons-dbutils</groupId>14 <artifactId>commons-dbutils</artifactId>15 <version>1.5</version>16 </dependency>
③ 로그 관련:
1 <!-- log --> 2 <dependency> 3 <groupId>org.slf4j</groupId> 4 <artifactId>slf4j-api</artifactId> 5 <version>${slf4j.version}</version> 6 </dependency> 7 <dependency> 8 <groupId>ch.qos.logback</groupId> 9 <artifactId>logback-classic</artifactId>10 <version>${logback.version}</version>11 </dependency>12 <!-- slf4j -->13 <dependency>14 <groupId>org.slf4j</groupId>15 <artifactId>log4j-over-slf4j</artifactId>16 <version>${slf4j.version}</version>17 </dependency>
4Spring 관련, spring aop, spring mvc 등 .
1 <!-- springframework --> 2 <dependency> 3 <groupId>org.springframework</groupId> 4 <artifactId>spring-aop</artifactId> 5 <version>${spring.version}</version> 6 </dependency> 7 <dependency> 8 <groupId>org.springframework</groupId> 9 <artifactId>spring-aspects</artifactId>10 <version>${spring.version}</version>11 </dependency>12 <dependency>13 <groupId>org.springframework</groupId>14 <artifactId>spring-beans</artifactId>15 <version>${spring.version}</version>16 </dependency>17 <dependency>18 <groupId>org.springframework</groupId>19 <artifactId>spring-context</artifactId>20 <version>${spring.version}</version>21 </dependency>22 <dependency>23 <groupId>org.springframework</groupId>24 <artifactId>spring-context-support</artifactId>25 <version>${spring.version}</version>26 </dependency>27 <dependency>28 <groupId>org.springframework</groupId>29 <artifactId>spring-core</artifactId>30 <version>${spring.version}</version>31 </dependency>32 <dependency>33 <groupId>org.springframework</groupId>34 <artifactId>spring-jdbc</artifactId>35 <version>${spring.version}</version>36 </dependency>37 <dependency>38 <groupId>org.springframework</groupId>39 <artifactId>spring-jms</artifactId>40 <version>${spring.version}</version>41 </dependency>42 <dependency>43 <groupId>org.springframework</groupId>44 <artifactId>spring-orm</artifactId>45 <version>${spring.version}</version>46 </dependency>47 <dependency>48 <groupId>org.springframework</groupId>49 <artifactId>spring-tx</artifactId>50 <version>${spring.version}</version>51 </dependency>52 <dependency>53 <groupId>org.springframework</groupId>54 <artifactId>spring-web</artifactId>55 <version>${spring.version}</version>56 </dependency>57 <dependency>58 <groupId>org.springframework</groupId>59 <artifactId>spring-webmvc</artifactId>60 <version>${spring.version}</version>61 </dependency>
⑤ 최대 절전 모드 관련:
1 <dependency> 2 <groupId>org.hibernate</groupId> 3 <artifactId>hibernate-c3p0</artifactId> 4 <version>${hibernate.version}</version> 5 </dependency> 6 <dependency> 7 <groupId>org.hibernate.common</groupId> 8 <artifactId>hibernate-commons-annotations</artifactId> 9 <version>${hibernate.version}</version>10 </dependency>11 <dependency>12 <groupId>org.hibernate</groupId>13 <artifactId>hibernate-core</artifactId>14 <version>${hibernate.version}</version>15 </dependency>16 <dependency>17 <groupId>org.hibernate</groupId>18 <artifactId>hibernate-entitymanager</artifactId>19 <version>${hibernate.version}</version>20 </dependency>
所有的依赖添加好后,就需要为各个子模块添加具体的依赖了,根据每个子模块的功能,添加相关的依赖,而不是将所有的依赖一次性加入。这样我们就可以根据自己开发的项目的需要,添加模块依赖,而不是一次性加入所有jar包,避免冗余,增大项目的体积。下面以lyyzoo-base-data和lyyzoo-starter-jpa为例说明。
lyyzoo-base-data模块是基础数据相关,主要与数据库打交道,那么就需要引入mysql驱动、数据库连接池c3p0等,pom.xml如下:
1 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 2 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 "> 3 <modelVersion>4.0.0</modelVersion> 4 <parent> 5 <groupId>com.lyyzoo</groupId> 6 <artifactId>lyyzoo-base</artifactId> 7 <version>1.0-SNAPSHOT</version> 8 </parent> 9 <artifactId>lyyzoo-base-data</artifactId>10 <name>${project.artifactId}</name>11 <packaging>jar</packaging>12 13 <dependencies>14 <!-- dbutils -->15 <dependency>16 <groupId>commons-dbutils</groupId>17 <artifactId>commons-dbutils</artifactId>18 </dependency>19 <!-- jdbc -->20 <dependency>21 <groupId>mysql</groupId>22 <artifactId>mysql-connector-java</artifactId>23 </dependency>24 <dependency>25 <groupId>com.mchange</groupId>26 <artifactId>c3p0</artifactId>27 </dependency>28 <!-- test -->29 <dependency>30 <groupId>com.lyyzoo</groupId>31 <artifactId>lyyzoo-base-test</artifactId>32 <scope>test</scope>33 </dependency>34 </dependencies>35 </project>
lyyzoo-starter-jpa是Java持久化相关,所以主要引入hibernate相关的依赖,同时,starter-jpa会依赖base-data及starter-base,pom.xml如下:
1 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 2 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 "> 3 <modelVersion>4.0.0</modelVersion> 4 <parent> 5 <groupId>com.lyyzoo</groupId> 6 <artifactId>lyyzoo-starter</artifactId> 7 <version>1.0-SNAPSHOT</version> 8 </parent> 9 <artifactId>lyyzoo-starter-jpa</artifactId>10 <name>${project.artifactId}</name>11 <packaging>jar</packaging>12 13 <dependencies>14 <dependency>15 <groupId>com.lyyzoo</groupId>16 <artifactId>lyyzoo-base-data</artifactId>17 </dependency>18 <dependency>19 <groupId>com.lyyzoo</groupId>20 <artifactId>lyyzoo-starter-base</artifactId>21 </dependency>22 <dependency>23 <groupId>org.hibernate</groupId>24 <artifactId>hibernate-c3p0</artifactId>25 </dependency>26 <dependency>27 <groupId>org.hibernate.common</groupId>28 <artifactId>hibernate-commons-annotations</artifactId>29 </dependency>30 <dependency>31 <groupId>org.hibernate</groupId>32 <artifactId>hibernate-core</artifactId>33 </dependency>34 <dependency>35 <groupId>org.hibernate</groupId>36 <artifactId>hibernate-ehcache</artifactId>37 </dependency>38 <dependency>39 <groupId>org.hibernate.javax.persistence</groupId>40 <artifactId>hibernate-jpa-2.1-api</artifactId>41 </dependency>42 <dependency>43 <groupId>org.hibernate</groupId>44 <artifactId>hibernate-validator</artifactId>45 </dependency>46 <dependency>47 <groupId>com.lyyzoo</groupId>48 <artifactId>lyyzoo-starter-test</artifactId>49 <scope>test</scope>50 </dependency>51 </dependencies>52 </project>
有了前面的基础之后,接下来进行重点的类结构设计。底层需要做的最重要的工作就是将一些通用的类抽象出来,以便于以后重用,从而提高开发效率。例如返回结果和分页类的封装、通用的工具类、JDBC相关的操作等。
说明一下,整个底层很大一部分是从之前实习的公司(这个就不说了)直接拿过来的,有些则更改了。相信我拿取的这部分代码并不会涉及机密问题,不用于商业用途,仅仅只是学习,应该没多大问题。
lyyzoo-base-core 目录结构:
lyyzoo-base-core是基础核心,封装了返回结果和加入了一些常用的工具类。
com.lyyzoo.bean包下封装了BaseBean和Result,BaseBean是Bean类的一个基础类,实现了序列化,重写了toString()方法,如下:
1 package com.lyyzoo.bean; 2 3 import org.apache.commons.lang3.builder.ToStringBuilder; 4 import org.apache.commons.lang3.builder.ToStringStyle; 5 6 import java.io.Serializable; 7 8 /** 9 * BaseBean 实现序列化 <p>10 *11 * @author bojiangzhou12 * @date 2017-03-2713 */14 public abstract class BaseBean implements Serializable {15 16 /**17 * ToStringBuilder – 用于辅助实现Object.toString()方法<p>18 */19 public String toString() {20 return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);21 }22 23 }
Result则封装了返回的结果,这里主要与ExtJs相对应,ExtJs进行ajax请求时,返回success=true,会进入success()方法;返回success=false,会进入failure()方法。同时,封装了返回消息、标识、错误信息等,便于前端拿到相应数据。
1 package com.lyyzoo.bean; 2 3 import lombok.Data; 4 5 import java.util.Map; 6 7 /** 8 * 封装返回结果<p> 9 *10 * @author bojiangzhou11 * @date 2017-03-2712 */13 @Data14 public class Result extends BaseBean {15 private static final long serialVersionUID = 1L;16 17 /**18 * 成功标志19 */20 public boolean success;21 /**22 * 返回标示23 */24 public Integer code;25 /**26 * 相关消息27 */28 public String msg;29 /**30 * 相关数据31 */32 public Object data;33 /**34 * 错误详细35 */36 public Map<String, Object> errors;37 38 public Result() {39 40 }41 42 public Result(boolean success) {43 this.success = success;44 }45 46 public Result(boolean success, Integer code, Object data, String msg) {47 this(success);48 this.code = code;49 this.data = data;50 this.msg = msg;51 }52 53 public Result(Integer code, Map<String, Object> errors, String msg) {54 this.success = false;55 this.code = code;56 this.errors = errors;57 this.msg = msg;58 }59 60 public boolean isSuccess() {61 return this.success;62 }63 64 public boolean hasErrors() {65 if (this.errors != null && this.errors.size() > 0) {66 return true;67 }68 return false;69 }70 }
其它的主要是一些工具类,例如Arrays继承了org.apache.commons.lang3.ArrayUtils,使得Arrays具有了丰富的操作集合的工具。再如Dates,Dates里封装了大量的对日期操作的方法,比如格式化日期、获取某个日期当天的开始时间和结束时间等。
lyyzoo-starter-base 目录结构:
lyyzoo-starter-base是web应用程序的一个基础,主要封装了基础实体类以及spring-base和日志的配置。实体的顶层是AbstractEntity
1 package com.lyyzoo.data.entity; 2 3 import com.lyyzoo.bean.BaseBean; 4 5 import java.io.Serializable; 6 7 /** 8 * 抽象实体类 重写equals和hashCode方法 9 *10 * @author bojiangzhou11 * @date 2017-03-2812 */13 @SuppressWarnings("serial")14 public abstract class AbstractEntity<ID extends Serializable> extends BaseBean implements Serializable {15 16 public abstract ID getId();17 18 @Override19 public boolean equals(Object obj) {20 21 if (null == obj) {22 return false;23 }24 if (this == obj) {25 return true;26 }27 if (!getClass().equals(obj.getClass())) {28 return false;29 }30 31 AbstractEntity<?> that = (AbstractEntity<?>) obj;32 33 return null == this.getId() ? false : this.getId().equals(that.getId());34 }35 36 @Override37 public int hashCode() {38 int hashCode = 17;39 40 hashCode += null == getId() ? 0 : getId().hashCode() * 31;41 42 return hashCode;43 }44 45 }
BaseEntity则继承AbstractEntity,BaseEntity作为其它实体的父类存在,BaseEntity定义了主键ID的生成策略。代码如下:
1 package com.lyyzoo.data.entity; 2 3 import lombok.Data; 4 5 import javax.persistence.GeneratedValue; 6 import javax.persistence.GenerationType; 7 import javax.persistence.Id; 8 import javax.persistence.MappedSuperclass; 9 10 /**11 * 统一定义id的entity基类.12 * <p/>13 * 抽象实体基类,提供统一的ID,和相关的基本功能14 * <p/>15 */16 @Data17 @MappedSuperclass18 @SuppressWarnings("serial")19 public abstract class BaseEntity extends AbstractEntity<Long> {20 21 /**22 * id 字段23 */24 @Id25 protected Long id;26 27 @Id28 @GeneratedValue(strategy = GenerationType.IDENTITY)29 public Long getId() {30 return this.id;31 }32 33 public void setId(Long id) {34 this.id = id;35 }36 }
spring-base.xml是基础配置,主要配置了扫描系统的配置文件、注解等。
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 3 xmlns="http://www.springframework.org/schema/beans" 4 xmlns:beans="http://www.springframework.org/schema/beans" 5 xmlns:context="http://www.springframework.org/schema/context" 6 xmlns:aop="http://www.springframework.org/schema/aop" 7 xmlns:tx="http://www.springframework.org/schema/tx" 8 xmlns:util="http://www.springframework.org/schema/util" 9 xmlns:mvc="http://www.springframework.org/schema/mvc"10 xmlns:jee="http://www.springframework.org/schema/jee"11 xmlns:jdbc="http://www.springframework.org/schema/jdbc"12 xmlns:tool="http://www.springframework.org/schema/tool"13 xmlns:dwr="http://www.directwebremoting.org/schema/spring-dwr"14 xsi:schemaLocation="15 http://www.springframework.org/schema/beans/spring-beans.xsd16 http://www.springframework.org/schema/context/spring-context.xsd17 http://www.springframework.org/schema/aop/spring-aop.xsd18 http://www.springframework.org/schema/tx/spring-tx.xsd19 http://www.springframework.org/schema/util/spring-util.xsd20 http://www.springframework.org/schema/mvc/spring-mvc.xsd21 http://www.springframework.org/schema/jee/spring-jee.xsd22 http://www.springframework.org/schema/jdbc/spring-jdbc.xsd23 http://www.springframework.org/schema/tool/spring-tool.xsd24 http://www.directwebremoting.org/schema/spring-dwr-3.0.xsd"25 >26 27 <description>Spring Base Config</description>28 29 <!-- 加载config.properties -->30 <context:property-placeholder location="classpath*:/config/*.properties" file-encoding="UTF-8" />31 32 <!-- 使用annotation 自动注册bean, 并保证@Required、@Autowired的属性被注入 -->33 <context:component-scan base-package="com.lyyzoo">34 <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>35 <context:exclude-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/>36 </context:component-scan>37 38 <!-- 支持上传文件 -->39 <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>40 41 </beans>
lyyzoo-starter-jpa 目录结构:
lyyzoo-starter-jpa集成了持久化相关的操作,配置等。
首先需要做持久化相关的配置(spring-base-jpa.xml),如数据源、SessionFactory、事务管理等。数据源使用c3p0,数据源相关配置如数据库驱动、地址等写到到配置文件中。配置Hibernate SessionFactory的同时,增加了JdbcTemplate。事务管理器使用Hibernate的事务管理。总的配置如下:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 3 xmlns="http://www.springframework.org/schema/beans" 4 xmlns:beans="http://www.springframework.org/schema/beans" 5 xmlns:tx="http://www.springframework.org/schema/tx" 6 xmlns:aop="http://www.springframework.org/schema/aop" 7 xmlns:context="http://www.springframework.org/schema/context" 8 xmlns:mvc="http://www.springframework.org/schema/mvc" 9 xmlns:util="http://www.springframework.org/schema/util" 10 xmlns:jee="http://www.springframework.org/schema/jee" 11 xmlns:jdbc="http://www.springframework.org/schema/jdbc" 12 xmlns:tool="http://www.springframework.org/schema/tool" 13 xmlns:dwr="http://www.directwebremoting.org/schema/spring-dwr" 14 xsi:schemaLocation=" 15 http://www.springframework.org/schema/beans/spring-beans.xsd 16 http://www.springframework.org/schema/context/spring-context.xsd 17 http://www.springframework.org/schema/aop/spring-aop.xsd 18 http://www.springframework.org/schema/tx/spring-tx.xsd 19 http://www.springframework.org/schema/util/spring-util.xsd 20 http://www.springframework.org/schema/mvc/spring-mvc.xsd 21 http://www.springframework.org/schema/jee/spring-jee.xsd 22 http://www.springframework.org/schema/jdbc/spring-jdbc.xsd 23 http://www.springframework.org/schema/tool/spring-tool.xsd 24 http://www.directwebremoting.org/schema/spring-dwr-3.0.xsd" 25 > 26 27 <description>Spring Jpa</description> 28 29 <!-- 使用C3P0 --> 30 <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> 31 <property name="driverClass" value="${jdbc.driver}"/> 32 <property name="jdbcUrl" value="${jdbc.url}"/> 33 <property name="user" value="${jdbc.username}"/> 34 <property name="password" value="${jdbc.password}"/> 35 36 <!-- default: 3 --> 37 <!-- 初始化时获取三个连接,取值应在minPoolSize与maxPoolSize之间。--> 38 <property name="initialPoolSize" value="${c3p0.initialPoolSize:5}"/> 39 40 <!-- default: 3 --> 41 <!-- 连接池保留最小连接数--> 42 <property name="minPoolSize" value="${c3p0.minPoolSize:5}"/> 43 44 <!-- default: 15 --> 45 <!-- 连接池保留最大连接数。--> 46 <property name="maxPoolSize" value="${c3p0.maxPoolSize:15}"/> 47 48 <!-- default: 0(秒) = 永不丢弃--> 49 <!-- 最大空闲时间,600 秒内未使用则连接被丢弃。--> 50 <property name="maxIdleTime" value="${c3p0.maxIdleTime:600}"/> 51 </bean> 52 53 <!-- sessionFactory --> 54 <bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean"> 55 <property name="dataSource" ref="dataSource" /> 56 <property name="hibernateProperties" > 57 <props> 58 <prop key="dialect">${hibernate.dialect}</prop> 59 <prop key="show_sql">${hibernate.show.sql}</prop> 60 <prop key="hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop> 61 </props> 62 </property> 63 <!-- 扫描hibernate注解实体 --> 64 <property name="packagesToScan"> 65 <list> 66 <value>com.lyyzoo.*.entity</value> 67 </list> 68 </property> 69 </bean> 70 71 <!-- jdbcTemplate --> 72 <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> 73 <property name="dataSource" ref="dataSource"/> 74 </bean> 75 <bean id="namedParameterJdbcTemplate" class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate"> 76 <constructor-arg ref="dataSource"/> 77 </bean> 78 <bean id="jdbcTemplateSupport" class="com.lyyzoo.data.jdbc.JdbcTemplateSupport"> 79 <property name="dataSource" ref="dataSource"/> 80 <property name="namedParameterJdbcTemplate" ref="namedParameterJdbcTemplate"/> 81 </bean> 82 83 <!-- 事务管理器 --> 84 <bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager"> 85 <property name="sessionFactory" ref="sessionFactory" /> 86 </bean> 87 88 <!-- 事务通知属性 --> 89 <tx:advice id="transactionManagerAdvice" transaction-manager="transactionManager"> 90 <tx:attributes> 91 <tx:method name="get*" read-only="true" /> 92 <tx:method name="load*" read-only="true" /> 93 <tx:method name="find*" read-only="true" /> 94 <tx:method name="list*" read-only="true" /> 95 <tx:method name="page*" read-only="true" /> 96 <tx:method name="query*" read-only="true" /> 97 <tx:method name="*" propagation="REQUIRED" /> 98 </tx:attributes> 99 </tx:advice>100 101 <!-- AOP 事务 -->102 <aop:config proxy-target-class="true">103 <aop:pointcut id="serviceMethod" expression="execution(* com.lyyzoo..*Service.*(..))"/>104 <aop:advisor pointcut-ref="serviceMethod" advice-ref="transactionManagerAdvice"/>105 </aop:config>106 107 <!-- 扫描注解 -->108 <context:component-scan base-package="com.lyyzoo" />109 110 </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等内置方法。
lyyzoo-starter-web自然跟web相关,在com.lyyzoo.web包下,BaseController作为controller类的父类,主要封装了返回结果集等信息。还有web相关配置,如视图解析器等内容:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 3 xmlns="http://www.springframework.org/schema/beans" 4 xmlns:beans="http://www.springframework.org/schema/beans" 5 xmlns:tx="http://www.springframework.org/schema/tx" 6 xmlns:aop="http://www.springframework.org/schema/aop" 7 xmlns:context="http://www.springframework.org/schema/context" 8 xmlns:mvc="http://www.springframework.org/schema/mvc" 9 xmlns:task="http://www.springframework.org/schema/task"10 xmlns:util="http://www.springframework.org/schema/util"11 xmlns:jee="http://www.springframework.org/schema/jee"12 xmlns:jdbc="http://www.springframework.org/schema/jdbc"13 xmlns:tool="http://www.springframework.org/schema/tool"14 xmlns:dwr="http://www.directwebremoting.org/schema/spring-dwr"15 xsi:schemaLocation="16 http://www.springframework.org/schema/beans/spring-beans.xsd17 http://www.springframework.org/schema/context/spring-context.xsd18 http://www.springframework.org/schema/aop/spring-aop.xsd19 http://www.springframework.org/schema/tx/spring-tx.xsd20 http://www.springframework.org/schema/util/spring-util.xsd21 http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd22 http://www.springframework.org/schema/task/spring-task-3.2.xsd23 http://www.springframework.org/schema/jee/spring-jee.xsd24 http://www.springframework.org/schema/jdbc/spring-jdbc.xsd25 http://www.springframework.org/schema/tool/spring-tool.xsd26 http://www.directwebremoting.org/schema/spring-dwr-3.0.xsd"27 >28 29 <description>Spring Web</description>30 31 <!-- 加载config.properties -->32 <context:property-placeholder location="classpath*:/config/*.properties" file-encoding="UTF-8" />33 34 <!-- 扫描Controller以及ControllerAdvice -->35 <context:component-scan base-package="com.lyyzoo" use-default-filters="false">36 <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>37 <context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/>38 </context:component-scan>39 40 <!-- 静态资源映射 -->41 <mvc:resources location="/static/" mapping="/static/**"/>42 43 <!-- 容器默认的DefaultServletHandler处理 所有静态内容与无RequestMapping处理的URL--> 44 <mvc:default-servlet-handler />45 46 <!-- 支持@Controller注解 -->47 <mvc:annotation-driven />48 49 <!-- 视图解析器 -->50 <bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">51 <property name="prefix" value="/WEB-INF/view"/>52 <property name="suffix" value=".jsp"/>53 </bean>54 55 </beans>
类结构图参考《底层类结构.vsd》
在开始开发一个系统之前,首先需要做的就是根据需求分析设计系统的实体对象以及对应的数据库表结构,这是开发的基础。
根据前面的需求分析设计的功能模块,实体对象可以分为5个模块,分别是系统模块(system)、基础模块(base)、采购模块(purchase)、销售模块(sale)、库存模块(stock)。下面是实体清单:
有了清单之后,利用PowerDesigner进行数据库物理模型设计。由于拥有对数据库的完全控制权,所以不对表设置约束,所有的约束在程序代码中进行控制。下面列出各个实体的属性即对应的表,具体可参考《数据库物理模型.pdm》。物理模型设计完成后,创建名为gpss的数据库,然后创建各个表。
数据库模型:
需求分析做完了,技术没问题,底层架构也设计好了,数据库设计好了,前面的所有准备工作做完了,下面就要进行燃气管进销存系统的编码实现了。首先要做的工作就是创建工程,项目名拟为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:
1 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 2 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 "> 3 <modelVersion>4.0.0</modelVersion> 4 <parent> 5 <groupId>com.lyyzoo</groupId> 6 <artifactId>lyyzoo</artifactId> 7 <version>1.0-SNAPSHOT</version> 8 </parent> 9 <groupId>com.lyyzoo.gpss</groupId>10 <artifactId>lyyzoo-gpss</artifactId>11 <name>lyyzoo :: gpss</name>12 <packaging>pom</packaging>13 14 <modules>15 <module>lyyzoo-gpss-base</module>16 <module>lyyzoo-gpss-web</module>17 </modules>18 19 <profiles>20 <!-- 开发环境 -->21 <profile>22 <id>dev</id>23 <activation>24 <property>25 <name>env</name>26 <value>dev</value>27 </property>28 </activation>29 </profile>30 <!-- 线上环境 -->31 <profile>32 <id>online</id>33 <activation>34 <property>35 <name>env</name>36 <value>online</value>37 </property>38 </activation>39 </profile>40 </profiles>41 <build>42 <plugins>43 <plugin>44 <groupId>com.juvenxu.portable-config-maven-plugin</groupId>45 <artifactId>portable-config-maven-plugin</artifactId>46 <version>1.1.5</version>47 <executions>48 <execution>49 <goals>50 <goal>replace-package</goal>51 </goals>52 </execution>53 </executions>54 <configuration>55 <portableConfig>src/main/resources/portable/config-${env}.xml</portableConfig>56 </configuration>57 </plugin>58 </plugins>59 </build>60 61 </project>
lyyzoo-gpss-base主要是dao层、service层、model层的集成,所以需要依赖于底层lyyzoo-starter-jpa、lyyzoo-starter-web。
lyyzoo-gpss-base > pom.xml:
1 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 2 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 "> 3 <modelVersion>4.0.0</modelVersion> 4 <parent> 5 <groupId>com.lyyzoo.gpss</groupId> 6 <artifactId>lyyzoo-gpss</artifactId> 7 <version>1.0-SNAPSHOT</version> 8 </parent> 9 <artifactId>lyyzoo-gpss-base</artifactId>10 <name>lyyzoo :: gpss :: base</name>11 <packaging>jar</packaging>12 13 <dependencies>14 <dependency>15 <groupId>com.lyyzoo</groupId>16 <artifactId>lyyzoo-starter-jpa</artifactId>17 </dependency>18 <dependency>19 <groupId>com.lyyzoo</groupId>20 <artifactId>lyyzoo-starter-web</artifactId>21 </dependency>22 </dependencies>23 24 </project>
lyyzoo-gpss-web是web相关,是controller层所在。依赖于lyyzoo-gpss-base、lyyzoo-starter-base等。
lyyzoo-gpss-web > pom.xml:
1 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 2 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 "> 3 <modelVersion>4.0.0</modelVersion> 4 <parent> 5 <groupId>com.lyyzoo.gpss</groupId> 6 <artifactId>lyyzoo-gpss</artifactId> 7 <version>1.0-SNAPSHOT</version> 8 </parent> 9 <artifactId>lyyzoo-gpss-web</artifactId>10 <name>lyyzoo :: gpss :: web</name>11 <packaging>war</packaging>12 13 <dependencies>14 <dependency>15 <groupId>com.lyyzoo.gpss</groupId>16 <artifactId>lyyzoo-gpss-base</artifactId>17 <version>${project.version}</version>18 </dependency>19 <dependency>20 <groupId>com.lyyzoo</groupId>21 <artifactId>lyyzoo-starter-base</artifactId>22 </dependency>23 <dependency>24 <groupId>com.lyyzoo</groupId>25 <artifactId>lyyzoo-starter-jpa</artifactId>26 </dependency>27 <dependency>28 <groupId>com.lyyzoo</groupId>29 <artifactId>lyyzoo-starter-web</artifactId>30 </dependency>31 <dependency>32 <groupId>com.lyyzoo</groupId>33 <artifactId>lyyzoo-starter-test</artifactId>34 </dependency>35 36 37 </dependencies>38 39 40 <build>41 <finalName>gpss</finalName>42 <outputDirectory>src/main/webapp/WEB-INF/classes</outputDirectory>43 </build>44 45 </project>
工程建好后,首要要做的就是系统的配置工作了,如web.xml,这应该算是web项目的起点了。进入lyyzoo-gpss-web/src/main/webapp/WEB-INF/web.xml,进行web的配置,主要的一些配置有加载系统的配置文件、Spring、字符过滤器、SpringMVC等配置。
一些基础的配置如下:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <web-app xmlns="http://java.sun.com/xml/ns/javaee" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 5 " 6 version="3.0"> 7 8 <display-name>lyyzoo :: gpss</display-name> 9 10 <!-- 加载配置文件 -->11 <context-param>12 <param-name>contextConfigLocation</param-name>13 <param-value>classpath*:/spring/spring-base*.xml</param-value>14 </context-param>15 16 <!-- Spring -->17 <listener>18 <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>19 </listener>20 21 <!-- 编码过滤器 -->22 <filter>23 <filter-name>encodingFilter</filter-name>24 <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>25 <init-param>26 <param-name>encoding</param-name>27 <param-value>UTF-8</param-value>28 </init-param>29 <init-param>30 <param-name>forceEncoding</param-name>31 <param-value>true</param-value>32 </init-param>33 </filter>34 <filter-mapping>35 <filter-name>encodingFilter</filter-name>36 <url-pattern>/*</url-pattern>37 </filter-mapping>38 39 <!-- 访问控制 -->40 <filter>41 <filter-name>VisitFilter</filter-name>42 <filter-class>com.lyyzoo.gpss.filter.VisitFilter</filter-class>43 </filter>44 <filter-mapping>45 <filter-name>VisitFilter</filter-name>46 <url-pattern>/admin/*</url-pattern>47 </filter-mapping>48 49 <!-- Spring MVC -->50 <servlet>51 <servlet-name>SpringMVC</servlet-name>52 <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>53 <init-param>54 <param-name>contextConfigLocation</param-name>55 <param-value>classpath*:/spring/spring-web*.xml</param-value>56 </init-param>57 <load-on-startup>1</load-on-startup>58 </servlet>59 <servlet-mapping>60 <servlet-name>SpringMVC</servlet-name>61 <url-pattern>/</url-pattern>62 </servlet-mapping>63 64 <!-- 错误页面 -->65 <error-page>66 <error-code>404</error-code>67 <location>/error/404</location>68 </error-page>69 <error-page>70 <error-code>500</error-code>71 <location>/error/500</location>72 </error-page>73 <error-page>74 <exception-type>java.lang.Throwable</exception-type>75 <location>/error/500</location>76 </error-page>77 78 <!-- 首页 -->79 <welcome-file-list>80 <welcome-file>/</welcome-file>81 </welcome-file-list>82 83 </web-app>
接着,配置系统将会用到的一些属性,如JDBC驱动、数据库用户名和密码等。在lyyzoo-gpss-web/src/main/resources/config下,创建config.properties配置文件,这个配置文件中的属性将会被底层spring配置的文件所引用。
比如JDBC的属性:
1 #################################### 2 # DATABASE 3 #################################### 4 # local_db 5 jdbc.driver=net.sf.log4jdbc.DriverSpy 6 jdbc.url=jdbc:log4jdbc:mysql://localhost:3306/gpss?useUnicode=true&characterEncoding=utf-8&autoReconnect=true&failOverReadOnly=false 7 jdbc.username=root 8 jdbc.password=root 9 10 # 初始化连接11 c3p0.initialPoolSize=512 # 连接池保留最小连接数13 c3p0.minPoolSize=514 # 连接池保留最大连接数15 c3p0.maxPoolSize=1516 # 最大空闲时间17 c3p0.maxIdleTime=60018 19 #hibernate20 hibernate.dialect=org.hibernate.dialect.MySQL5Dialect21 hibernate.show.sql=false22 hibernate.hbm2ddl.auto=update
但是上面的配置只是本机的一个开发环境,如果我将项目发布到生产环境,那就至少需要重新修改数据库地址、用户名和密码。这样是比较麻烦的,所以,在lyyzoo-gpss-web/src/main/portable下创建两个xml文件,分别为开发环境和生产环境的:config-dev.xml和config-online.xml。
config-online.xml:
1 <?xml version="1.0" encoding="utf-8" ?> 2 3 <portable-config> 4 <config-file path="WEB-INF/classes/config/config.properties"> 5 6 <!-- JDBC --> 7 <replace key="jdbc.driver"><![CDATA[com.mysql.jdbc.Driver]]></replace> 8 <replace key="jdbc.url"><![CDATA[jdbc:mysql://192.168.1.91:30112/fff2f025c2b04?useUnicode=true&characterEncoding=utf-8]]></replace> 9 <replace key="jdbc.username">a6564a1169d94</replace>10 <replace key="jdbc.password">d3e6d1aea5e04</replace>11 12 <!-- hibernate -->13 <replace key="hibernate.show.sql">false</replace>14 <replace key="hibernate.hbm2ddl.auto">none</replace>15 16 <!-- debug -->17 <replace key="app.debug">false</replace>18 <replace key="app.env">online</replace>19 <replace key="logback.level">INFO</replace>20 <replace key="jdbc.resultsettable">ERROR</replace>21 22 23 </config-file>24 </portable-config>
然后配置一个“不同环境打包”的maven插件——“portable-config-maven-plugin”,通过该插件,就可以在打包的时候加上需要打包的环境,例如指定online环境,在打包时就会将config-online.xml中的属性替换到config.properties里,这样一来就不必我们手动去替换了。配置好之后,我们在打包时可以使用命令[mvn clean package –Denv=online]打包线上环境的war包。
maven环境配置,在lyyzoo-gpss > pom.xml中配置两个环境:
1 <profiles> 2 <!-- 开发环境 --> 3 <profile> 4 <id>dev</id> 5 <activation> 6 <property> 7 <name>env</name> 8 <value>dev</value> 9 </property>10 </activation>11 </profile>12 <!-- 线上环境 -->13 <profile>14 <id>online</id>15 <activation>16 <property>17 <name>env</name>18 <value>online</value>19 </property>20 </activation>21 </profile>22 </profiles>
不同环境打包插件(portable-config-maven-plugin)的配置:
1 <build> 2 <plugins> 3 <plugin> 4 <groupId>com.juvenxu.portable-config-maven-plugin</groupId> 5 <artifactId>portable-config-maven-plugin</artifactId> 6 <version>1.1.5</version> 7 <executions> 8 <execution> 9 <goals>10 <goal>replace-package</goal>11 </goals>12 </execution>13 </executions>14 <configuration>15 <portableConfig>src/main/resources/portable/config-${env}.xml</portableConfig>16 </configuration>17 </plugin>18 </plugins>19 </build>
工程建好后,创建包的结构。按照一般的分层方式,分为dao层、entity层、service层,同时,每层下按模块划分为system、base、purchase、sale、stock。然后在entity下根据表设计创建实体类。
lyyzoo-gpss-base 目录结构:
然后是lyyzoo-gpss-web模块,该模块主要是controller层,以及静态资源文件、jsp文件等。com.lyyzoo.gpss.web作为controller层的包,同样,在web下按系统模块划分。
lyyzoo-gpss-web 目录结构:
lyyzoo-gpss-web/src/main/webapp/static作为静态文件的根目录,static/lib目录作为三方类库的根目录,如ExtJs、jQuery、其它的插件等。static/css是系统css文件的根目录;static/img是图片的根目录;static/js是系统js文件根目录,/js下同样按模块划分。
静态资源文件目录结构:
jsp文件不能直接让用户访问,需要放到/WEB-INF下,与配置的spring视图解析器相对应,所有的jsp文件放到/WEB-INF/view目录下,view目录下按模块划分,index.jsp是系统的登录页面。/WEB-INF/layout/目录下,将jsp中需要引入的一些资源等做了整合,如ExtJs的文件、meta描述信息、taglib等,整合后,jsp中如果需要引入整合jsp即可,可减少很多重复的工作。
taglib.jsp中引入了标签和设置了资源的路径:
1 <%@ page contentType="text/html;charset=UTF-8" language="java" %> 2 3 <%-- 引入标签 --%> 4 <%@taglib prefix="c" uri="" %> 5 <%@taglib prefix="fn" uri="" %> 6 <%@taglib prefix="fmt" uri="" %> 7 <%@taglib prefix="sf" uri="" %> 8 9 <%-- 资源路径 --%>10 <c:set var="CTX" value="${pageContext.request.contextPath}" />11 <c:set var="STATIC_CTX_URL" value="${CTX}/static" />12 <c:set var="LIB" value="${STATIC_CTX_URL}/lib" />13 <c:set var="JS" value="${STATIC_CTX_URL}/js"/>14 <c:set var="CSS" value="${STATIC_CTX_URL}/css"/>15 <c:set var="IMG" value="${STATIC_CTX_URL}/img"/>
meta.jsp中主要设置了一些meta描述信息和ICO图标:
1 <%@ page contentType="text/html;charset=UTF-8" language="java" %> 2 <%@ include file="/WEB-INF/layout/taglib.jsp" %> 3 4 <meta charset="utf-8"> 5 <meta http-equiv="X-UA-Compatible" content="IE=9,chrome=1"> 6 7 <meta name="description" content=""> 8 <meta name="author" content=""> 9 <meta name="renderer" content="webkit">10 <%-- 图标 --%>11 <link type="image/x-icon" href="${IMG}/favicon.ico" rel="icon">
extjs-neptune.jsp则引入了ExtJs相关的css和js文件,以及jQuery等:
1 <%@ page contentType="text/html;charset=UTF-8" language="java" %> 2 <%@ include file="/WEB-INF/layout/taglib.jsp" %> 3 4 <link rel="stylesheet" type="text/css" href="${LIB}/ext/4.2.2/theme/ext-theme-neptune/ext-theme-neptune-all.css?1.1.11"/> 5 <link rel="stylesheet" type="text/css" href="${LIB}/ext/4.2.2/icons/icon.css?1.1.11"/> 6 7 <script type="text/javascript" src="${LIB}/ext/4.2.2/ext-all.js?1.1.11"></script> 8 <script type="text/javascript" src="${LIB}/ext/4.2.2/locale/ext-lang-zh_CN.js?1.1.11"></script> 9 <script type="text/javascript" src="${LIB}/jquery/2.1.1/jquery.js?1.1.11"></script>10 <script type="text/javascript" src="${JS}/Global.js?1.1.11"></script>11 12 <script type="text/javascript">13 window.CTX = "${CTX}";14 window.STATIC_CTX_URL = "${STATIC_CTX_URL}";15 window.LIB = "${LIB}";16 window.JS = "${JS}";17 window.CSS = "${CSS}";18 window.IMG = "${IMG}";19 </script>
WEB-INF目录结构:
首先创建一个BaseController,BaseController继承底层的BaseController,增加了HttpSession,以及获取当前登录用户的方法,这样其它的controller继承该BaseController后,就可以非常方便的获得当前session和登录用户了。
BaseController代码如下:
1 package com.lyyzoo.gpss.web; 2 3 import com.lyyzoo.gpss.entity.system.User; 4 import org.springframework.beans.factory.annotation.Autowired; 5 6 import javax.servlet.http.HttpSession; 7 8 /** 9 *10 * <p>11 *12 * @author bojiangzhou13 * @date 2017-04-0214 */15 public class BaseController extends com.lyyzoo.web.BaseController {16 17 @Autowired18 protected HttpSession session;19 20 public User getCurrentUser(){21 return (User) session.getAttribute("currentUser");22 }23 24 public Long getCurrentUserId(){25 return getCurrentUser().getId();26 }27 28 public String getCurrentUserAccount(){29 return getCurrentUser().getAccount();30 }31 32 }
创建HomeController作为登录和主页的处理器。主要包含的方法有访问登录页面,访问登录后的主页,以及登录处理等。Controller需要加上@Controller标注该类为controller,使用@RequestMapping()支持访问rest形式的地址访问。HomeController中注入UserService,用于处理用户登录相关的业务。
用户进入登录界面,jsp页面以的形式请求验证码,验证码使用工具类生成,以流的形式输出,生成的验证码保存到session中。用户输入登录账号、密码和验证码登录系统。首先前台会检测输入是否为空等,传到后台,从session中取出验证码判断验证码是否正确,不正确则刷新验证码并且需要用户重新输入验证码。验证码通过后,使用登录账号和密码查找数据库,如果有,则将该用户保存到session中,跳转到管理页面,登录成功。否则提示用户名或密码错误。
HomeController代码如下:
1 package com.lyyzoo.gpss.web; 2 3 import com.lyyzoo.gpss.entity.system.User; 4 import com.lyyzoo.gpss.service.system.UserService; 5 import com.lyyzoo.gpss.util.VCodeGenerator; 6 import com.lyyzoo.util.Cryptos; 7 import com.lyyzoo.util.Strings; 8 import org.springframework.beans.BeanUtils; 9 import org.springframework.beans.factory.annotation.Autowired; 10 import org.springframework.stereotype.Controller; 11 import org.springframework.web.bind.annotation.PathVariable; 12 import org.springframework.web.bind.annotation.RequestMapping; 13 import org.springframework.web.bind.annotation.RequestMethod; 14 15 import javax.imageio.ImageIO; 16 import javax.servlet.http.HttpServletResponse; 17 import javax.servlet.http.HttpSession; 18 import java.awt.image.BufferedImage; 19 import java.io.IOException; 20 21 /** 22 * <p> 23 * 24 * @author bojiangzhou 25 * @date 2017-03-29 26 */ 27 @Controller 28 @RequestMapping("") 29 public class HomeController extends BaseController { 30 31 @Autowired 32 private UserService userService; 33 34 /** 35 * 到首页/登录页面 36 */ 37 @RequestMapping(value = {"", "/", "/index", "/login"}) 38 public String index(){ 39 return "/index"; 40 } 41 42 /** 43 * 管理员主页 44 */ 45 @RequestMapping("/admin/home") 46 public String toHome(){ 47 return "/home/home"; 48 } 49 50 /** 51 * 登录 52 */ 53 @RequestMapping(value = "/login", method = RequestMethod.POST) 54 public String login(String account, String password, String vcode, HttpSession session){ 55 String redirect = REDIRECT("/login"); 56 //基本验证 57 if(Strings.isNullOrEmpty(account)){ 58 session.setAttribute("errorMsg", "账号必须填写!"); 59 return redirect; 60 } 61 if(Strings.isNullOrEmpty(password)){ 62 session.setAttribute("errorMsg", "密码必须填写!"); 63 return redirect; 64 } 65 if(Strings.isNullOrEmpty(vcode)){ 66 session.setAttribute("errorMsg", "验证码必须填写!"); 67 return redirect; 68 } 69 //验证码 70 String sessionVcode = (String) session.getAttribute("vcode"); 71 if(!vcode.equalsIgnoreCase(sessionVcode)){ 72 session.setAttribute("errorMsg", "验证码错误!"); 73 return redirect; 74 } 75 //验证用户名和密码 76 password = Cryptos.encryptMd5(password); 77 User loginUser = userService.login(account, password); 78 if(loginUser == null){ 79 session.setAttribute("errorMsg", "账号或密码错误!"); 80 return redirect; 81 } 82 if(loginUser.getIsLocked() == User.IsLocked.YES){ 83 session.setAttribute("errorMsg", "账号已锁定,不能登录!"); 84 return redirect; 85 } 86 87 //保存到session的时候清除密码 88 User currentUser = new User(); 89 BeanUtils.copyProperties(loginUser, currentUser); 90 currentUser.setPassword(null); 91 92 //登录成功 93 session.setAttribute("currentUser", currentUser); 94 95 return REDIRECT("/admin/home"); 96 } 97 98 /** 99 * 获取验证码100 */101 @RequestMapping("/vcode")102 public void getVCode(HttpSession session, HttpServletResponse response) throws IOException {103 //创建验证码生成器对象104 VCodeGenerator vcGenerator = new VCodeGenerator();105 //生成验证码106 String vcode = vcGenerator.generatorVCode();107 //将验证码保存在session域中,以便判断验证码是否正确108 session.setAttribute("vcode", vcode);109 //生成验证码图片110 BufferedImage vImg = vcGenerator.generatorRotateVCodeImage(vcode, true);111 //输出图像112 ImageIO.write(vImg, "gif", response.getOutputStream());113 }114 115 /**116 * 退出系统117 */118 @RequestMapping("/logoff")119 public String logoff(HttpSession session){120 session.invalidate();121 return REDIRECT("/");122 }123 124 @RequestMapping("/function")125 public String function(){126 return "/home/function";127 }128 129 @RequestMapping("/welcome")130 public String welcome(){131 return "/home/welcome";132 }133 134 /**135 * 错误页面136 * @param code137 * @return138 */139 @RequestMapping("/error/{code}")140 public String error(@PathVariable String code) {141 return "/error/" + code;142 }143 144 145 146 }
UserService中根据用户名和密码获取用户:
1 package com.lyyzoo.gpss.service.system; 2 3 @Service 4 public class UserService extends BaseService<User> { 5 @Autowired 6 private UserDao userDao; 7 /** 8 * 获取登录用户 9 */10 public User login(String account, String password){11 Map<String, Object> filter = new HashMap<>();12 filter.put("account", account);13 filter.put("password", password);14 filter.put("state", Applications.Flag.YES);15 16 User loginUser = get(filter);17 return loginUser;18 }19 }
시스템 개발이 완료되면 먼저 로그인부터 시작하여 각 모듈, 각 기능, 각 프로세스를 전체적으로 로컬에서 테스트해야 합니다. 자세히 테스트됩니다.
첫 번째 테스트에서는 사용자가 로그인하지 않은 경우 주소 표시줄에 직접 접속 주소를 입력하여 로그인 페이지로 점프하는지 확인합니다. 그런 다음 최소한 각 역할에 해당하는 계정이 정상적으로 로그인되었는지 테스트해 보세요. 로그인 후 각 역할이 소유한 메뉴가 정상적으로 표시되는지 확인하세요.
다른 모듈을 테스트하려면 각 역할에 해당하는 계정을 사용하여 시스템에 로그인하고 해당 기능을 테스트하십시오. 예를 들어, 관리자가 시스템에 들어가 기본 데이터, 제품 정보, 창고 정보 등을 입력합니다. 구매 관리자는 공급업체 정보와 구매 주문서를 입력하고 검토를 위해 제출합니다. 영업 관리자는 고객 정보를 입력하고 판매 주문을 입력한 후 검토를 위해 제출합니다. 재고 관리자가 구매 주문을 검토하고, 검토가 통과되면 재고가 증가하고, 판매 주문이 검토를 통과하면 재고가 감소합니다. 재고 정보를 확인하고 해당 작업을 수행하여 재고 금액이 올바른지 확인하세요. 테스트 결과는 시스템 테스트 스크린샷에서 확인할 수 있습니다.
시스템 내결함성 테스트는 주로 잘못된 데이터 유형과 범위를 벗어난 값을 입력하여 비정상적인 조건에서 시스템의 동작을 테스트합니다. 이와 관련하여 시스템은 더 나은 작업을 수행합니다. 사용자가 불법적인 데이터를 입력하면 사용자에게 올바른 데이터를 입력하도록 즉시 알려줍니다. 첫째, 사용자가 입력한 데이터의 적법성과 입력해야 하는지 여부는 데이터가 백엔드로 전송된 후 데이터가 저장되기 전에 코드에서 판단됩니다. 데이터베이스에. 시스템에서 사용하는 Jdbc는 SQL 주입 및 기타 문제를 어느 정도 방지할 수도 있습니다. 시스템에서 예측할 수 없는 예외가 발생하는 경우 기술자가 적시에 시스템을 유지 관리할 수 있도록 사용자에게 친숙한 인터페이스가 표시됩니다.
전반적으로 전체 테스트 과정은 순조롭게 진행되었습니다. 몇 가지 사소한 문제가 있었지만 즉시 수정되었습니다. 모든 기능이 구현되었으며 시스템은 기본적인 구매, 판매 및 재고 프로세스를 충족할 수 있으며 향후 확장이 가능합니다.
Mopo Cloud를 사용하여 프로젝트를 배포합니다. Mopo Cloud는 특정 한도 내에서 사용하기 쉽고 무료입니다. 먼저 Mobo Cloud에 gpss라는 Java 애플리케이션을 생성한 다음 mysql 서비스를 생성하고 이를 Java 애플리케이션에 바인딩한 후 데이터베이스 연결을 구성 파일에 복사합니다. 로컬 GPS 데이터베이스를 내보내고 생성된 mysql 애플리케이션으로 가져옵니다. 그런 다음 IDEA에서 mvn clean package –Denv=online 명령을 사용하여 온라인 환경용 war 패키지를 패키징하고 Mobo Cloud에 war 패키지를 게시합니다. 프로젝트를 시작한 다음 액세스하고 테스트하면 모든 것이 정상입니다. ext의 호환성 문제가 잘 해결되지 않았기 때문에, 구글 크롬을 이용하여 보실 것을 권장합니다. 나중에 Alibaba Cloud와 같은 클라우드에 배포하는 방법을 알아보겠습니다.
이번 가스관 구매, 판매, 재고 시스템을 단계별로 설계하고 완성함으로써 소프트웨어의 아키텍처, 설계, 프레임워크, 코딩 및 다양한 도구의 사용에 더욱 능숙해졌고, 나는 소프트웨어 개발 프로세스에 익숙해졌습니다. 이 시스템은 대학 4년 동안 배운 지식의 산물입니다. 논문 제안을 받고, 제안을 이해하고, 관련 정보를 컨설팅하고, 수요 분석을 수행하고, 기능 모듈을 설계하고, 데이터베이스를 설계하는 과정을 거쳐 나의 업무 경험을 결합합니다. 인턴십과 회사 건축 디자인은 자체적인 하위 레이어를 구축합니다. 시스템 개발은 이러한 기본 기반으로 수행됩니다.
약 한 달 간의 졸업 프로젝트 끝에 저는 소프트웨어 개발의 모든 측면에서 관련 지식을 습득하고 전체 프로세스에 익숙해졌으며 대학 4년 동안 지식 수준을 테스트했습니다. 분명히 아직 많은 단점이 있습니다. 예를 들어, 이 시스템에서는 SSH 프레임워크를 사용하지만 프레임워크의 원리 구현에 대해서는 아직 명확하지 않은 부분이 많습니다. 개인적으로 저는 학습할 때 무슨 일이 일어나고 왜 일어나는지 알아야 한다고 믿습니다. 특히 기술의 경우 능력을 향상시키기 위해서는 그 기본 원리를 이해해야 합니다. 이는 향후 작업을 통해 점차적으로 개선될 예정입니다.
대부분입니다. 이제부터 저는 직장에서 공부할 예정입니다.
학교를 그만두고 일하러 가서 돈을 찾을 수 있어서 매우 기쁘고, 내 인생에서 가장 편안한 시간은 대학 시절일지도 모르기 때문에 매우 슬프다.
저는 우리 학교를 매우 좋아합니다 - 진윤산 기슭에 위치하고 아름다운 환경과 아름다운 여성들이 있는 남서대학교, 하하!
마지막으로 시스템 개발 관련 문서를 공유합니다: 가스관 장비 구매, 판매 및 재고 시스템
압축된 패키지의 디렉토리는 다음과 같습니다.
위 내용은 졸업작품 구매, 판매, 재고관리 시스템 - 기초공사부터 시작의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!