1. 程式人生 > >一個SSM(Spring+SpringMVC+Mybatis)+jQuery EasyUI開發的ERP系統

一個SSM(Spring+SpringMVC+Mybatis)+jQuery EasyUI開發的ERP系統

生產管理ERP系統

這是一個生產管理ERP系統。依託科技計劃重點專案“裝備物聯及生產管理系統研發”,專案研發裝備物聯以及生產管理的系統,主要包括:計劃進度、裝置管理、工藝監控、物料監控、人員監控、質量監控、系統管理7大模組。專案原始碼共享在github上面:http://github.com/megagao/production_ms

專案技術架構(Spring+SpringMVC+Mybatis)

  • Maven
  • Spring(IOC DI AOP 宣告式事務處理)
  • SpringMVC(支援Restful風格)
  • Hibernate Validator(引數校驗)
  • Mybatis(最少配置方案)
  • shiro許可權控制,結合ajax實現了非同步認證與非同步授權,同時實現了細粒度的許可權動態分配(到按鈕級別);添加了shiro session過期的登入跳轉
  • jQuery EasyUI開發前端頁面,利用jQuery檔案上傳外掛實現拖拽上傳的效果並對檔案型別、大小、數量進行控制;利用search-box實現查詢功能
  • Druid(資料來源配置 sql防注入 sql效能監控)
  • 統一的異常處理
  • JSP JSTL JavaScript
  • kindeditor富文字編輯器,處理圖片上傳和富文字編輯

系統架構

資料庫設計(詳見sql檔案)

軟體執行截圖

  • 登入介面

登入可使用賬號:22,密碼:22的超級管理員登入,若密碼輸錯,下次登入需輸入驗證碼。

  • 執行介面

超級管理員可顯示系統管理模組進行系統許可權分配與管理,其他角色可檢視除系統管理外的剩餘模組的資訊(包括下載附件、檢視圖片等),但是隻能維護該角色對應許可權內的資訊。
左邊功能搜尋欄可進行功能模糊查詢。

  • 圖片上傳

圖片上傳的配置請檢視文件尾部的註釋,圖片大小要求不能超過1M,支援jpg、png等多種格式的圖片,上傳成功後可在相應的展示欄進行回顯。

  • 檔案上傳

檔案上傳使用了一個開源的jQuery檔案上傳外掛,可以在common.js裡面修改上傳檔案的引數,包括上傳個數,支援的檔案型別等,配置資訊如下:

1
2
3
4
5
6
url:"file/upload",
maxFileCount: 5,                //上傳檔案個數(多個時修改此處
   returnType: 'json',              //服務返回資料
   allowedTypes: 'doc,docx,excel,sql,txt,ppt,pdf',  //允許上傳的檔案式
   showDone: false,                     //是否顯示"Done"(完成)按鈕
   showDelete: true,                  //是否顯示"Delete"(刪除)按鈕

檔案上傳的介面如下:

  • 富文字編輯

本系統採用了開源的KindEditor富文字編輯器,它是一套線上HTML編輯器,主要用於讓使用者在網站上獲得所見即所得編輯效果。KindEditor把傳統的多行文字輸入框(textarea)替換為視覺化的富文字輸入框。

KindEditor主要特點

  • 快速:體積小,載入速度快
  • 開源:開放原始碼,高水平,高品質
  • 底層:內建自定義 DOM 類庫,精確操作 DOM
  • 擴充套件:基於外掛的設計,所有功能都是外掛,可根據需求增減功能
  • 風格:修改編輯器風格非常容易,只需修改一個 CSS 檔案
  • 相容:支援大部分主流瀏覽器,比如 IE、Firefox、Safari、Chrome、Opera

  • 關聯資訊

關聯物件的資訊,點選以彈窗的形式顯示,若具有該模組對應的修改許可權,則也可在此進行資訊維護。

  • search-box查詢

可以在右上角的search-box選擇查詢條件,輸入關鍵字進行對應資訊的模糊查詢。

  • session過期跳轉登入

使用者登入後,會建立相應的session,系統預設過期時間為10分鐘,若需更改,可在applicationContext-shiro.xml配置檔案中,更改如下配置。

<!-- 會話管理器 -->
   <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
       <!-- session的失效時長,單位毫秒 ,這裡設定為10分鐘-->
       <property name="globalSessionTimeout" value="600000"/>
       <!-- 刪除失效的session -->
       <property name="deleteInvalidSessions" value="true"/>
       <!-- 指定本系統sessionId, 預設為: JSESSIONID 問題: 與Servlet容器名衝突, 如Jetty, Tomcat等預設JSESSIONID,
       	當跳出shiro Servlet時如Error-page容器會為JSESSIONID重新分配值導致登入會話丟失! -->
       <property name="sessionIdCookie" ref="sessionIdCookie"/>
   </bean>

若session過期,則應跳轉登入介面重新登入。系統採用的方式是設定一個sessionfilter,如下:

public class SessionFilter implements Filter {

    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException,
            ServletException {

        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        if (!SecurityUtils.getSubject().isAuthenticated()) {
            //判斷session裡是否有使用者資訊,且是否為ajax請求,如果是ajax請求響應頭會有,x-requested-with
            if (request.getHeader("x-requested-with") != null
                    && request.getHeader("x-requested-with").equalsIgnoreCase("XMLHttpRequest")) {
                response.setHeader("session-status", "timeout");//在響應頭設定session狀態
            }
        }
        filterChain.doFilter(request, servletResponse);
    }

    @Override
    public void destroy() {
        // TODO Auto-generated method stub
    }

    @Override
    public void init(FilterConfig arg0) throws ServletException {
        // TODO Auto-generated method stub
    }
}

並在web.xml中配置該filter。當session過期時, 在響應頭設定session狀態為timeout,然後採用全域性的ajax事件對session狀態進行判斷,跳轉到登入頁面。該事件定義在common.js中,如下:

//全域性ajax事件,處理session過期跳轉登入
$.ajaxSetup({
	complete:function(XMLHttpRequest,sessionStatus){
		var sessionstatus = XMLHttpRequest.getResponseHeader("session-status");
		if(sessionstatus=="timeout"){
		     $.messager.alert('提示資訊', "登入超時!請重新登入!", 'info',function(){
		         window.location.href = 'login';
		     });
		} 
    }
});

關於這部分的詳細內容請參考我的一篇部落格:利用filter和全域性ajax事件實現shiro session過期登入跳轉

  • 動態許可權控制

本系統採用經典的許可權模型,即RBAC(Role-Based Access Control )基於角色的訪問控制,即使用者通過角色與許可權進行關聯。模型用到5張表:使用者表、角色表、許可權表、使用者角色表、角色許可權表。簡單地說,一個使用者擁有若干角色,每一個角色擁有若干許可權。這樣,就構造成“使用者-角色-許可權”的授權模型。在這種模型中,使用者與角色之間,角色與許可權之間,一般者是多對多的關係。

該模型可簡化表示為下圖:

本系統基於RBAC許可權模型,採用shiro框架進行許可權控制。只有角色為超級管理員的使用者才能進行系統的許可權管理,許可權級別細化到選單選項。

注:

匯入專案到STS

感謝一位韓國道友給我發的郵件,介紹了將production_ssm匯入到STS中,並將詳細過程與注意事項完整記錄了下來。非常感謝他的文件,也為STS的使用提供了參考。
參見:匯入production_ssm到STS

檔案上傳配置

在本地建立上傳圖片和檔案的資料夾,如我的存放路徑是在D:\upload\temp\img,D:\upload\temp\file資料夾下,然後修改tomcat的配置檔案server.xml,新增虛擬路徑,將對圖片和檔案的請求url對映到本機硬碟的相應路徑,如下:

<Host name="localhost"  appBase="webapps"
           unpackWARs="true" autoDeploy="true">
       <!-- SingleSignOn valve, share authentication between web applications
            Documentation at: /docs/config/valve.html -->
       <!--
       <Valve className="org.apache.catalina.authenticator.SingleSignOn" />
       -->

       <!-- Access log processes all example.
            Documentation at: /docs/config/valve.html
            Note: The pattern used is equivalent to using pattern="common" -->
       <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
              prefix="localhost_access_log" suffix=".txt"
              pattern="%h %l %u %t &quot;%r&quot; %s %b" />

       <!-- 在Host標籤下新增下面兩行,配置虛擬路徑到你本機的資料夾 -->
       <Context path="/pic" docBase="D:\upload\temp\img" crossContext="true" trusted="true" reloadable="true"/>
       <Context path="/file" docBase="D:\upload\temp\file" crossContext="true" trusted="true" reloadable="true"/>
</Host>

idea classpath配置

idea引入專案後,resources目錄在eclipse中是在classpath下的,而在idea中變成在classpath外,導致專案無法識別配置檔案。解決辦法是把resources資料夾加入到classpath中,請參照此博文操作:eclipse與idea中classpath配置路徑不同導致遷移專案時的FileNotFoundException問題

Mybatis逆向工程

系統使用了Mybatis的逆向工程,依據資料庫表自動生成domain和mapper(注:自動生成的程式碼都是針對單表,若需多表整合,則要手動修改實現),其中,針對每個資料庫表,都會生成兩個封裝物件,可以認為example物件是對其相應的ORM對映物件查詢條件的封裝。逆向工程的實現–Mybatis Generator的程式碼託管在https://github.com/mybatis/generator,程式碼down下來後,配置generatorConfig.xml檔案,如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
  PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
  "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">

<generatorConfiguration>
	<context id="testTables" targetRuntime="MyBatis3">

		<commentGenerator>
			<!-- 是否去除自動生成的註釋 true:是 : false:否 -->
			<property name="suppressAllComments" value="true" />
		</commentGenerator>

		<!--資料庫連線的資訊:驅動類、連線地址、使用者名稱、密碼 -->
		<jdbcConnection driverClass="com.mysql.jdbc.Driver"
			connectionURL="jdbc:mysql://localhost:3306/production_ms" userId="root"
			password="root">
		</jdbcConnection>

		<!-- 預設false,把JDBC DECIMAL 和 NUMERIC 型別解析為 Integer,為 true時把JDBC DECIMAL 和 
			NUMERIC 型別解析為java.math.BigDecimal -->
		<javaTypeResolver>
			<property name="forceBigDecimals" value="false" />
		</javaTypeResolver>

		<!-- targetProject:生成PO類的位置 -->
		<javaModelGenerator targetPackage="org.hqu.production_ms.domain"
			targetProject=".\src">
			<!-- enableSubPackages:是否讓schema作為包的字尾 -->
			<property name="enableSubPackages" value="false" />
			<!-- 從資料庫返回的值被清理前後的空格 -->
			<property name="trimStrings" value="true" />
		</javaModelGenerator>

        <!-- targetProject:mapper對映檔案生成的位置 -->
		<sqlMapGenerator targetPackage="org.hqu.production_ms.mapper" 
			targetProject=".\src">
			<!-- enableSubPackages:是否讓schema作為包的字尾 -->
			<property name="enableSubPackages" value="false" />
		</sqlMapGenerator>

		<!-- targetPackage:mapper介面生成的位置 -->
		<javaClientGenerator type="XMLMAPPER"
			targetPackage="org.hqu.production_ms.mapper" 
			targetProject=".\src">
			<!-- enableSubPackages:是否讓schema作為包的字尾 -->
			<property name="enableSubPackages" value="false" />
		</javaClientGenerator>

		<!-- 指定資料庫表 -->
		<table schema="" tableName="unqualify_apply"></table>

	</context>
</generatorConfiguration>

修改完成後,執行main方法即可。需要注意的是,若要重新生成,則需把已經生成的檔案刪除,因為它不會自己覆蓋,導致檔案混亂。

本文轉自:https://github.com/megagao/production_ssm