IDEA+SSM+Maven實現商品管理系統(超詳細SSM整合專案)
IDEA+SSM+Maven實現商品管理系統(超詳細SSM整合專案)
Hello,大家好,本週博主為大家帶來一個SSM整合的一個小專案,該專案是一個階段性的跨越,從servlet過渡到SSM,內容詳細,包教包會~
什麼是SSM?
SSM(Spring+SpringMVC+MyBatis)框架集由Spring、MyBatis兩個開源框架整合而成(SpringMVC是Spring中的部分內容)。常作為資料來源較簡單的web專案的框架。
Spring
Spring就像是整個專案中裝配bean的大工廠,在配置檔案中可以指定使用特定的引數去呼叫實體類的構造方法來例項化物件。也可以稱之為專案中的粘合劑。
Spring的核心思想是IoC(控制反轉),即不再需要程式設計師去顯式地 new
一個物件,而是讓Spring框架幫你來完成這一切。
SpringMVC
SpringMVC在專案中攔截使用者請求,它的核心Servlet即DispatcherServlet承擔中介或是前臺這樣的職責,將使用者請求通過HandlerMapping去匹配Controller,Controller就是具體對應請求所執行的操作。SpringMVC相當於SSH框架中struts。
mybatis
mybatis是對jdbc的封裝,它讓資料庫底層操作變的透明。mybatis的操作都是圍繞一個sqlSessionFactory例項展開的。mybatis通過配置檔案關聯到各實體類的Mapper檔案,Mapper檔案中配置了每個類對資料庫所需進行的sql語句對映。在每次與資料庫互動時,通過sqlSessionFactory拿到一個sqlSession,再執行sql命令。
頁面傳送請求給控制器,控制器呼叫業務層處理邏輯,邏輯層向持久層傳送請求,持久層與資料庫互動,後將結果返回給業務層,業務層將處理邏輯傳送給控制器,控制器再呼叫檢視展現資料。 [1]
摘自百度百科
為什麼要用SSM?
首先之前編寫JavaWeb專案是基於servlet實現,編寫過於繁瑣,建立物件過於頻繁,
使用SSM框架後,spring控制service層,利用spring容器託管物件,
springmvc用於控制器Controller層,主要用於呼叫service層,轉發或重定向頁面
mybatis基於mapper介面和xml檔案來實現對資料的CRUD操作
用的人多,用的企業多!!!
使用SSM框架編寫Web專案的優點
簡化程式碼,統一風格,分工明確,大大提高了編寫專案的效率,提高程式的可擴充套件性與可維護性,可複用
專案簡介
商品管理系統
使用者註冊,登入,添加了防跳牆功能,即未登入不可訪問商品列表
商品的增刪改查,多條件,分頁(採用前4後3形式)
技術棧
- 開發工具:IDEA
- Java環境:jdk1.8
- 伺服器:Tomcat8.0
- 後端:JavaEE , Spring , SpringMVC, Mybatis
- 前端:bootstrap+jsp
- 日誌輸出:log4j
- 管理工具:Maven
資料表準備
user表
CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '使用者id', `username` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '使用者名稱', `password` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '使用者密碼', PRIMARY KEY (`id`) )
goods表
CREATE TABLE `goods` ( `order_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '商品id', `buyer_name` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '買家姓名', `buy_count` int(11) DEFAULT NULL COMMENT '購買商品的數量', `buyer_phone` varchar(11) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '買家電話', `goods_name` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '商品名稱', `goods_price` decimal(6,2) DEFAULT NULL COMMENT '商品價格', `sum_price` decimal(10,2) DEFAULT NULL COMMENT '總價', `buyer_address` varchar(256) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '買家地址', PRIMARY KEY (`order_id`) )
效果圖
專案結構
原始碼結構
配置檔案結構
前端結構
依賴pom
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId> <artifactId>SSM-GoodsManagerSystem</artifactId> <version>1.0-SNAPSHOT</version> <!-- 依賴: junit. 資料庫驅動,連線池,servlet,jsp,mybatis,mybatis-spring,spring--> <dependencies> <!--Junit--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> <!--資料庫驅動--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.47</version> </dependency> <!-- 資料庫連線池: c3p0連線池 --> <dependency> <groupId>com.mchange</groupId> <artifactId>c3p0</artifactId> <version>0.9.5.2</version> </dependency> <!--Servlet - JSP --> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> </dependency> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>2.2</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <!--Mybatis--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.4</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>2.0.4</version> </dependency> <!--Spring--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.1.9.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.1.9.RELEASE</version> </dependency> <!-- Lombok--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.12</version> </dependency> <!--字元或數字驗證--> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.9</version> </dependency> <!-- log4j日誌輸出 --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> </dependencies> <!--靜態資源匯出--> <build> <resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>false</filtering> </resource> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>false</filtering> </resource> </resources> </build> </project>
核心配置檔案
database.properties
jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/ssmbuild?useSSL=true&useUnicode=true&characterEncoding=utf8 jdbc.username=root jdbc.password=111111
log4j.properties
#//???????INFO?DEBUG? ???? log4j.rootLogger=infoA,errorA,stdout,DEBUGA #???spring???????? log4j.category.org.springframework = WARN #?????? log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target=System.out log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.Threshold = debug log4j.appender.stdout.layout.ConversionPattern=%d %-5p %c{1}:%L - %m%n #??error????? log4j.logger.errorA=error log4j.appender.errorA=org.apache.log4j.DailyRollingFileAppender log4j.appender.errorA.layout=org.apache.log4j.PatternLayout log4j.appender.errorA.layout.ConversionPattern=%d{yyyy-MM-dd-HH-mm} [%t] [%c] [%p] - %m%n log4j.appender.errorA.datePattern=yyyy-MM-dd'.log' log4j.appender.errorA.Threshold = error log4j.appender.errorA.append=true log4j.appender.error.File=d:/log/error.log #??DEBUG??????? log4j.logger.DEBUGA=DEBUG log4j.appender.DEBUGA=org.apache.log4j.DailyRollingFileAppender log4j.appender.DEBUGA.layout=org.apache.log4j.PatternLayout log4j.appender.DEBUGA.layout.ConversionPattern=%d{yyyy-MM-dd-HH-mm} [%t] [%c] [%p] - %m%n log4j.appender.DEBUGA.datePattern=yyyy-MM-dd'.log' log4j.appender.DEBUGA.Threshold = DEBUG log4j.appender.DEBUGA.append=true log4j.appender.DEBUGA.File=d:/log/debug_log.log #??sql?? log4j.logger.com.ibatis=DEBUG log4j.logger.java.sql.ResultSet=INFO log4j.logger.com.ibatis.common.jdbc.SimpleDataSource=DEBUG log4j.logger.com.ibatis.common.jdbc.ScriptRunner=DEBUG log4j.logger.com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate=DEBUG log4j.logger.java.sql.Connection=DEBUG log4j.logger.java.sql.Statement=DEBUG log4j.logger.java.sql.PreparedStatement=DEBUG
mabatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <settings> <setting name="logImpl" value="STDOUT_LOGGING"/> </settings> <typeAliases> <package name="com.wanshi.bean"/> </typeAliases> <mappers> <mapper resource="com/wanshi/mapper/UserInfoMapper.xml"/> <mapper resource="com/wanshi/mapper/GoodsMapper.xml"/> </mappers> </configuration>
spring-dao.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- 配置整合mybatis --> <!-- 1.關聯資料庫檔案 --> <context:property-placeholder location="classpath:database.properties"/> <context:property-placeholder location="classpath:log4j.properties"/> <!-- 2.資料庫連線池 --> <!--資料庫連線池 dbcp 半自動化操作 不能自動連線 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}"/> <!-- c3p0連線池的私有屬性 --> <property name="maxPoolSize" value="30"/> <property name="minPoolSize" value="10"/> <!-- 關閉連線後不自動commit --> <property name="autoCommitOnClose" value="false"/> <!--獲取連線超時時間 --> <property name="checkoutTimeout" value="10000"/> <!-- 當獲取連線失敗重試次數 --> <property name="acquireRetryAttempts" value="2"/> </bean> <!-- 3.配置SqlSessionFactory物件 --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <!-- 注入資料庫連線池 --> <property name="dataSource" ref="dataSource"/> <!-- 配置MyBaties全域性配置檔案:mybatis-config.xml --> <property name="configLocation" value="classpath:mybatis-config.xml"/> </bean> <!-- 4.配置掃描Dao介面包,動態實現Dao介面注入到spring容器中 --> <!--解釋 :http://www.cnblogs.com/jpfss/p/7799806.html--> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <!-- 注入sqlSessionFactory --> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/> <!-- 給出需要掃描Dao介面包 --> <property name="basePackage" value="com.wanshi.mapper"/> </bean> </beans>
spring-service.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- 掃描service相關的bean --> <context:component-scan base-package="com.wanshi.service" /> <!--BookServiceImpl注入到IOC容器中--> <bean id="UserInfoServiceImpl" class="com.wanshi.service.impl.UserInfoServiceImpl"> <property name="userInfoMapper" ref="userInfoMapper"/> </bean> <bean id="GoodsServiceImpl" class="com.wanshi.service.impl.GoodsServiceImpl"> <property name="goodsMapper" ref="goodsMapper"/> </bean> <!-- 配置事務管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <!-- 注入資料庫連線池 --> <property name="dataSource" ref="dataSource" /> </bean> </beans>
spring-mvc.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- 1.註解驅動--> <mvc:annotation-driven/> <!-- 2.靜態資源過濾--> <mvc:default-servlet-handler/> <!-- 3.掃描包:controller--> <context:component-scan base-package="com.wanshi.controller"/> <!-- 4.檢視解析器--> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/"/> <property name="suffix" value=".jsp"/> </bean> <mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/**"/> <bean id="loginInterceptor" class="com.wanshi.interceptor.LoginInterceptor"/> </mvc:interceptor> </mvc:interceptors> </beans>
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <import resource="classpath:spring-dao.xml"/> <import resource="classpath:spring-service.xml"/> <import resource="classpath:spring-mvc.xml"/> </beans>
核心原始碼
****
UserController
package com.wanshi.controller; import com.wanshi.bean.UserInfo; import com.wanshi.service.UserInfoService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import javax.servlet.http.HttpSession; @Controller @RequestMapping("/user") public class UserController { @Autowired @Qualifier("UserInfoServiceImpl") private UserInfoService userInfoService; @RequestMapping("/register") public String register() { return "register"; } @RequestMapping("/registerPost") public String registerPost(UserInfo userInfo){ userInfoService.save(userInfo); return "login"; } @RequestMapping("/loginPost") public String loginPost(HttpSession session,UserInfo userInfo){ UserInfo u1 = userInfoService.get(userInfo); session.setAttribute("user", u1); if (u1 != null) { return "redirect:/goods/list"; } return "register"; } }
GoodsController
package com.wanshi.controller; import com.wanshi.bean.Goods; import com.wanshi.bean.Page; import com.wanshi.service.GoodsService; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import java.util.List; @Controller @RequestMapping("/goods") public class GoodsController { @Autowired @Qualifier("GoodsServiceImpl") private GoodsService goodsService; private static final Integer PAGE_SIZE = 2; @RequestMapping("/list") public String list(String pageNumb, String buyerName, Model model) { Integer pageNum = 1; if (pageNumb != null && !pageNumb.equals("")) { pageNum = Integer.valueOf(pageNumb); } Page<Goods> pager = goodsService.list(pageNum, PAGE_SIZE, buyerName); model.addAttribute("pager", pager); model.addAttribute("buyerName", buyerName); return "goods/list"; } @RequestMapping("/add") public String add(){ return "goods/add"; } @RequestMapping("/addGoods") public String addGoods(Goods goods){ goodsService.save(goods); return "redirect:/goods/list"; } @RequestMapping("/edit/{orderId}") public String edit(@PathVariable("orderId") Integer orderId, Model model) { Goods goods = goodsService.get(orderId); model.addAttribute("goods", goods); return "goods/edit"; } @RequestMapping("/editPost") public String editPost(Goods goods) { goodsService.update(goods); return "redirect:/goods/list"; } @RequestMapping("/del/{orderId}") public String del(@PathVariable("orderId") Integer orderId) { goodsService.delete(orderId); return "redirect:/goods/list"; } }
LoginInterceptor
package com.wanshi.interceptor; import org.springframework.web.servlet.HandlerInterceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class LoginInterceptor implements HandlerInterceptor { public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { //1.對登入,註冊,風格直接放行 //獲取請求的uri地址 String uri = request.getRequestURI(); if (uri.contains("login") || uri.contains("register")) { return true; } //2.進行session驗證 Object user = request.getSession().getAttribute("user"); if (user == null) { request.getRequestDispatcher("/WEB-INF/jsp/login.jsp") .forward(request, response); return false; } return true; } }
Page分頁類
package com.wanshi.bean; import java.util.ArrayList; import java.util.List; /** * 該類的使用方法必須嚴格按照一下流程 * 1 計算得到 總記錄數 rowCount * 2 使用帶參構造方法初始化,例如 Page page1 = new Page(3, 5, 57 ); * 3 設定當前頁記錄 page1.setList(list1 ); * * * @author Administrator * * @param <T> */ public class Page<T> { /** * 當前頁碼前的頁碼數 */ private static final int BeforePageNumbCount = 4; /** * 當前頁碼後的頁碼數 */ private static final int AfterPageNumbCount = 3; /** * 當前頁碼 */ private int currPage; /** * 總記錄數 */ private int rowCount; /** * 每頁記錄數 * 該引數就是 limit arg1,arg2 中的第2個引數 arg2 */ private int pageSize; /** * 總頁數 */ private int pageCount; /** * 前1頁頁碼 */ private int prevPageNumb; /** * 後一頁頁碼 */ private int nextPageNumb; /** * 當前頁的第1個條記錄的索引 * 該變數就是 limit arg1,arg2 的第一個引數 arg1 */ private int currPageFirstRowIndex; /** * 當前頁記錄列表 */ private List<T> list; /** * 頁碼列表 , 即可顯示的頁碼 */ private List<Integer> pageButtonNumbs ; /** * 初始化,不考慮 列表記錄數 * * @param _currPage * @param rowCount */ public Page(int _currPage, int _pageSize, int _rowCount){ this.pageSize = _pageSize; this.rowCount = _rowCount; // 計算總頁數 this.pageCount = this.rowCount / this.pageSize; if(this.rowCount% this.pageSize !=0 || this.rowCount == 0){ this.pageCount ++ ; } // 修正當前頁 this.currPage = _currPage ; if(this.currPage< 1 ){ this.currPage = 1; } if(this.currPage > this.pageCount ){ this.currPage = this.pageCount; } // 計算當前頁第一條記錄的索引 this.currPageFirstRowIndex = (this.currPage-1)* this.pageSize ; // 計算並修正 前一頁 和 後一頁 this.prevPageNumb = this.currPage - 1; this.nextPageNumb = this.currPage + 1; if(this.prevPageNumb<1){ this.prevPageNumb = 1; } if(this.prevPageNumb>1 && this.prevPageNumb >= this.pageCount){ this.prevPageNumb = this.pageCount-1; } if(this.nextPageNumb <= 1 ){ this.nextPageNumb = 2; } if(this.nextPageNumb >1 && this.nextPageNumb > this.pageCount){ this.nextPageNumb = this.pageCount; } // 計算 頁碼按鈕 列表 this.pageButtonNumbs = new ArrayList(); for( int i = this.currPage -4 ; i <= this.currPage+3 ;i++){ if(i<1 || i> this.pageCount ){ continue; } this.pageButtonNumbs.add(i); } } public List<T> getList() { return list; } public void setList(List<T> list) { this.list = list; } public int getCurrPage() { return currPage; } public int getRowCount() { return rowCount; } public int getPageSize() { return pageSize; } public int getPageCount() { return pageCount; } public int getPrevPageNumb() { return prevPageNumb; } public int getNextPageNumb() { return nextPageNumb; } public List<Integer> getPageButtonNumbs() { return pageButtonNumbs; } public int getCurrPageFirstRowIndex() { return currPageFirstRowIndex; } }
結語
本專案採用SSM框架編寫Web專案,是一個進階,從servlet進階至SSM,本SSM整合一定要熟記於心,
SSM的重要程度是不可言喻的,到這裡,我們才算是真正的步入了後臺開發的門,讀者一定要把SSM整合啃透,因為SSM很重要,所以說必須學會並熟練使用,動手實踐,實踐出真理!!!
都看到這裡了,確定不點贊麼~專案原始碼已上傳,需要的小夥伴可以去下載
- Android 自定義View - 柱狀波形圖 wave view
- ArcGIS製圖技巧:製圖入門與點、線、面狀符號製作
- Android技術分享|【Android踩坑】懷疑人生,主執行緒修改UI也會崩潰?
- 資料分表Mybatis Plus動態表名最優方案的探索
- 個人開源專案如何上傳maven中央倉庫
- 遊戲創作者能夠為玩家創造出快樂的體驗,這或許就是做遊戲的魅力吧!
- 用Python自動生成 圖文並茂的資料分析 報告
- 軟體測試之測試代表使用者
- 分散式前修課:Zookeeper鎖實現方式
- Python 資料分析師的基本修養
- 設計模式之介面卡模式
- 如何做好企業數字化轉型?這10份靠譜案例收藏了(附下載)
- 效能提升400倍丨外匯掉期估值計算優化案例
- 如何面向物件程式設計?程式設計師:我也要先有“物件”啊
- 技術分享| 融合排程系統中的電子圍欄功能說明
- #yyds乾貨盤點# leetcode演算法題:環形連結串列 II
- 網站建設流程
- Java池化技術你瞭解多少?
- 如何實時計算日累計逐單資金流
- JAVA面試解析之Spring