前言:本文从零开始详细叙述SSM框架的搭建和DEMO构建过程,并作出博主自己对于SSM框架的理解。本人能力有限,叙述难免会有错误和疏漏,还请各位读者包容指正。至于说为什么是“从零开始”,是因为学校课程要求用SSM开发一个网页,而本人在此之前基本没有接触过JAVA,也从来没有开发过网页。在摸索的途中踩了许多坑,在网上找到的教程都不够完美,故撰此文以供本人日后不时之需,也供广大入门者参考之用。为了便于读者理解,本文所提供之DEMO是根据本人近期一大作业(实现一个卖甜点的网上商城)大幅简化而来,只涉及最基本的各层传参、数据库查询、结果显示功能。 本文假定读者已安装IntelliJ IDEA、JDK、JRE、Tomcat、MySQL等外部依赖并正确配置环境变量。
本项目工程文件请点此下载,提取密码为"yeig"
【IntelliJ IDEA】
IntelliJ IDEA 是JetBrains公司推出的一款Java IDE。本项目使用IntelliJ IDEA Ultimate构建,在校学生凭教育邮箱可领取JetBrains Product Pack for Students。
【Maven】
Maven是基于项目对象模型(POM project object model),可以通过一小段描述信息(配置)来管理项目的构建,报告和文档的软件项目管理工具。在本项目中,Maven的作用主要体现在方便地向"pom.xml"添加一段段的代码来管理项目的jar包。
【SSM框架】
SSM是Spring+SpringMVC+MyBatis的缩写,是标准的MVC模式,将整个系统划分为:
[持久层]:DAO、Mapper层
DAO(Data Access Object),意为“数据访问对象”,是一个面向对象的数据库接口。在本项目中,DAO是用于存储从数据库中取得信息的一个类,其属性包含数据库表中的各列,并提供一系列"get"、"set"方法。
Mapper,在本项目中主要维护[服务层]<-->[持久层]<-->[数据库]之间的映射关系。
[服务层]:Service层
服务层主要为控制层提供所需的服务,服务层实质上调用持久层的方法来实现与数据库的交互。
[控制层]:Controller层
控制层在本项目中主要控制网页的跳转和前后端之间参数的传递。通过一系列"@RequestMapping"注解,来为每类URL执行特定的控制流程。
[视图层]:View层
视图层主要指提供给用户的可视化界面,例如各种".html"、".jsp"页面,负责将结果显示给用户。
启动IntelliJ IDEA,如下图所示新建一个Maven webapp项目,注意勾选"Create from archetype"选项。
GroupId在这里应该是可以随意填写的。本项目的DEMO是一个卖蛋糕的网上商城,因此制品ID就叫做CAKESHOP好了。
点击下一步后出现以下界面,本项目使用内置Maven创建,如果此前没有创建过Maven工程,请确认下图中的settings.xml是否存在,若不存在,需要自己导入配置文件。
一切确认完成后,生成项目,第一次创建项目时会下载一些组件(如下图所示),请耐心等待。
下载完成后,项目的目录结构应该如下图所示。
接上,我们手动创建一系列目录和(空)文件,最终效果如下所示。
接下来将pom.xml中的代码替换为下面的代码。pom.xml的作用是告诉Maven需要引入哪些jar包。在这里推荐一个网站http://mvnrepository.com/ 可以在此检索所需jar包的版本和对应的xml代码。替换代码后,IntelliJ IDEA需要联网下载所需的jar包。
4.0.0
CAKESHOP
CAKESHOP
1.0-SNAPSHOT
war
CAKESHOP Maven Webapp
UTF-8
1.7
1.7
junit
junit
4.11
test
javax
javaee-api
7.0
junit
junit
4.12
javax.servlet
jsp-api
2.0
provided
jstl
jstl
1.2
javax
javaee-api
7.0
org.springframework
spring-core
4.2.5.RELEASE
org.springframework
spring-web
4.2.5.RELEASE
org.springframework
spring-oxm
4.2.5.RELEASE
org.springframework
spring-tx
4.2.5.RELEASE
org.springframework
spring-jdbc
4.2.5.RELEASE
org.springframework
spring-webmvc
4.2.5.RELEASE
org.springframework
spring-context
4.2.5.RELEASE
org.springframework
spring-context-support
4.2.5.RELEASE
org.springframework
spring-aop
4.2.5.RELEASE
org.springframework
spring-test
4.2.5.RELEASE
org.mybatis
mybatis
3.4.2
org.mybatis
mybatis-spring
1.3.0
mysql
mysql-connector-java
5.1.25
commons-dbcp
commons-dbcp
1.2.2
log4j
log4j
1.2.17
org.slf4j
slf4j-api
1.7.18
org.slf4j
slf4j-log4j12
1.7.18
org.codehaus.jackson
jackson-mapper-asl
1.9.13
com.fasterxml.jackson.core
jackson-core
2.8.0
com.fasterxml.jackson.core
jackson-databind
2.8.0
org.jdom
jdom2
2.0.5
org.apache.httpcomponents
httpcore
4.4.5
org.apache.httpcomponents
fluent-hc
4.5.2
commons-beanutils
commons-beanutils
1.9.3
commons-fileupload
commons-fileupload
1.3.1
commons-io
commons-io
2.4
commons-codec
commons-codec
1.9
junit
junit
4.0
CAKESHOP
src/main/resources
**/*.properties
**/*.xml
**/*.tld
**/*.jsp
true
src/main/java
**/*.properties
**/*.xml
**/*.tld
true
maven-clean-plugin
3.0.0
maven-resources-plugin
3.0.2
maven-compiler-plugin
3.7.0
maven-surefire-plugin
2.20.1
maven-war-plugin
3.2.0
maven-install-plugin
2.5.2
maven-deploy-plugin
2.8.2
替换applicationContext.xml代码如下
替换jdbc.properties代码如下
#本项目使用的MySQL版本为5.5.60,使用的mysql-connector-java版本为5.1.25,如果MySQL版本为8.0或以上,请在pom.xml中修改mysql-connector-java版本为8.0.11
# 并将下面的com.mysql.jdbc.Driver替换为"com.mysql.cj.jdbc.Driver"
driver=com.mysql.jdbc.Driver
#注意:下面的eshop应该替换为数据库名
url=jdbc:mysql://localhost:3306/eshop?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
#替换为您的用户名
username=root
#替换为您的密码
password=123456789
initSize=30
maxActive=0
maxIdle=50
minIdle=20
maxWait=60000
timeOut=10000
替换log4j.properties代码如下
log4j.rootLogger=ALL,CONSOLE,FILE
###################
# Console Appender
###################
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
#log4j.appender.CONSOLE.Threshold=INFO
log4j.appender.CONSOLE.Target=System.out
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
#log4j.appender.CONSOLE.layout.ConversionPattern=[start]%d{DATE}[DATE]%n%p[PRIORITY]%n%x[NDC]%n%t[THREAD] n%c[CATEGORY]%n%m[MESSAGE]%n%n
#####################
# File Appender
#####################
log4j.appender.FILE=org.apache.log4j.FileAppender
#log4j.appender.FILE.Threshold=ERROR
log4j.appender.FILE.File=E\:\\file.html
log4j.appender.FILE.Append=false
log4j.appender.FILE.layout=org.apache.log4j.HTMLLayout
log4j.appender.FILE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
替换mybatis-config.xml代码如下
替换SpringMVC.xml代码如下
text/html;charset=UTF-8
text/html;charset=UTF-8
替换web.xml代码如下
CAKESHOP
contextConfigLocation
classpath:applicationContext.xml
log4jConfigLocation
classpath:log4j.properties
encodingFilter
org.springframework.web.filter.CharacterEncodingFilter
encoding
UTF-8
encodingFilter
/*
org.springframework.web.context.ContextLoaderListener
org.springframework.web.util.IntrospectorCleanupListener
SpringMVC
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
classpath:SpringMVC.xml
1
true
SpringMVC
*.html
index.jsp
15
部署Tomcat
点击界面右上角"Add Configuration"按钮
在弹出页面点击左上角的"+"号
如下图,选择"Local"
如下图进行配置后,点击"Deployment"按钮
点击"+"号
选择"Artifact"
如下图选择并确定
在这里可以配置网站的后缀名(可选),这里为了个性化,配置为"CAKESHOP",这样在项目部署后,输入"http://localhost:8080/CAKESHOP/"即可访问网站首页。
如下图选择运行配置,再点击绿色三角部署网页。
等待十几秒后,系统会自动弹出网站首页如下。至此SSM框架的搭建基本完成。
(本DEMO在jsp代码使用了forEach标签,请确保您已正确配置JSTL标签库,若没有,请访问下面的链接下载
http://tomcat.apache.org/download-taglibs.cgi)
首先按照下图新建(空)文件和目录
WebController.java提供流程控制,通过匹配不同的URL,选择不同的方法处理网页请求,并控制不同的视图跳转,其代码如下所示。Controller层直接调用Service层中的方法,在本项目中,WebController类直接调用WebService接口提供的方法。
package com.CAKESHOP.controller;
import com.CAKESHOP.dao.Product;
import com.CAKESHOP.service.WebService;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import java.util.List;
@Controller
public class WebController {
@Autowired//此注解使得接口"WebService"得以实例化
WebService webService;
@RequestMapping(value = "products.html")//此注解指定后缀中以"products.html"为开头的访问提交此段代码处理,下面依此类推
public ModelAndView products(@Param(value = "c_id") Integer c_id) {//默认界面,按照商品名组织商品
if (c_id == null) {
c_id = -1;
}
ModelAndView modelAndView = new ModelAndView();
List products = webService.queryAllProducts();
for (Product product : products) {
product.setImgPath("images/" + Integer.toString(product.getID()) + ".jpg");
}
//向要跳转的页面中以"products"的名字传入参数"products",以下依此类推
modelAndView.addObject("products", products);
modelAndView.addObject("c_id", c_id);
//指定要跳转的视图为"products"视图,框架会自动匹配后缀名,以下依此类推
modelAndView.setViewName("products");
return modelAndView;
}
@RequestMapping(value = "products_price_ascending")//按照价格升序查询产品
public ModelAndView products_price_ascending(@Param(value = "c_id") Integer c_id) {//"@Param"注解使得此段代码可以获取URL中传入的参数
if (c_id == null) {
c_id = -1;
}
ModelAndView modelAndView = new ModelAndView();
List products = webService.queryProductsPriceAscending();
for (Product product : products) {
product.setImgPath("images/" + Integer.toString(product.getID()) + ".jpg");
}
modelAndView.addObject("products", products);
modelAndView.addObject("c_id", c_id);
modelAndView.setViewName("products");
return modelAndView;
}
@RequestMapping(value = "products_search")
public ModelAndView products_search(@Param(value = "c_id") Integer c_id, @Param(value = "searchKey") String searchKey) {//模糊搜索
if (c_id == null) {
c_id = -1;
}
ModelAndView modelAndView = new ModelAndView();
List products = webService.queryProductsSearch(searchKey);
for (Product product : products) {
product.setImgPath("images/" + Integer.toString(product.getID()) + ".jpg");
}
modelAndView.addObject("products", products);
modelAndView.addObject("c_id", c_id);
modelAndView.setViewName("products");
return modelAndView;
}
}
Product.java在DAO层中,其属性是根据数据库对应表的列决定的。DAO在数据库与mapper层之间,在本项目中,WebMapper.xml与Product.java构成联系。一般来说,数据库中一个表对应DAO中的一个类,数据库表中的一列对应DAO类中的一个属性,其代码如下所示。
package com.CAKESHOP.dao;
public class Product {
public int ID = 0;//商品ID
private String name = "";//商品名
private int num = 0;//商品剩余库存
private double prize = 0;//原价
private String category = "";//商品类别
private String flavour = "";//商品口味
private String weight = "";//商品重量
private String color = "";//商品颜色
private String detail = "";//商品描述
public int getID() {
return this.ID;
}
public void setID(int input) {
this.ID = input;
}
public String getName() {
return this.name;
}
public void setName(String input) {
this.name = input;
}
public int getNum() {
return this.num;
}
public void setNum(int input) {
this.num = input;
}
public double getPrize() {
return this.prize;
}
public void setPrize(double input) {
this.prize = input;
}
public String getCategory() {
return this.category;
}
public void setCategory(String input) {
this.category = input;
}
public String getFlavour() {
return this.flavour;
}
public void setFlavour(String input) {
this.flavour = input;
}
public String getWeight() {
return this.weight;
}
public void setWeight(String input) {
this.weight = input;
}
public String getColor() {
return this.color;
}
public void setColor(String input) {
this.color = input;
}
public String getDetail() {
return this.detail;
}
public void setDetail(String input) {
this.detail = input;
}
public String getImgPath() {
return this.imgPath;
}
public void setImgPath(String input) {
this.imgPath = input;
}
public double getCurrentPrice() {
return this.currentPrice;
}
public void setCurrentPrice(double input) {
this.currentPrice = input;
}
}
WebMapper.java为WebService.java提供方法,WebMapper接口中声明的方法在WebMapper.xml中实现。WebMapper.java代码如下所示。
package com.CAKESHOP.mapper;
import com.CAKESHOP.dao.Product;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface WebMapper {
List selectAllProduct();
List selectProductsPriceAscending();
//将"String"类型的变量"searchKey"以"searchKey"为参数名传入到WebMapper.xml中
List selectProductsSearch(@Param(value = "searchKey") String searchKey);
}
数据库中product表的结构如下所示。
WebMapper.xml实现WebMapper.java中声明的方法,主要是一些SQL语句,其代码如下所示。
WebService.java接口为WebController.java声明一系列方法,这些方法随后会在WebServiceImpl.java中实现。WebService.java代码如下所示。
package com.CAKESHOP.service;
import com.CAKESHOP.dao.Product;
import java.util.List;
public interface WebService {
List queryProductsPriceAscending();
List queryProductsSearch(String searchKey);
List queryAllProducts();
}
WebServiceImpl.java通过调用WebMapper类中提供的方法来实现WebService.java声明的一系列方法,其代码如下所示。
package com.CAKESHOP.service.implement;
import com.CAKESHOP.dao.Product;
import com.CAKESHOP.mapper.WebMapper;
import com.CAKESHOP.service.WebService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class WebServiceImpl implements WebService {
@Autowired
WebMapper webMapper;
@Override
public List queryProductsPriceAscending() {
return webMapper.selectProductsPriceAscending();
}
@Override
public List queryAllProducts() {
return webMapper.selectAllProduct();
}
@Override
public List queryProductsSearch(String searchKey) {
return webMapper.selectProductsSearch(searchKey);
}
}
至此,DEMO的核心代码已经完成,接下来是构建前端。本项目的前端模板来源于网络,经过大面积重构后使得其可以自动布局。本项目主要有两个页面:主页和产品页面。主页主要是提供一个跳转到产品页面的按钮,我们真正实现的功能是产品页面的几个简单检索功能。为了节约篇幅,在这里仅贴出products.jsp的代码,本项目的完整代码和资源文件已在文章开头给出。
products.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="width" uri="http://www.springframework.org/tags/form" %>
<%@page pageEncoding="utf-8" contentType="text/html;charset=utf-8" %>
Products
按照上面的方法配置完项目后,DEMO就构建完成了。
还是像文章最开始说到的,点击右上角的绿色三角进行部署。成功后首页如下图所示。
点击"SHOP NOW",跳转到商品浏览页面,如下图所示。默认显示顺序是按照商品名增序进行排列。
接着我们测试“按价格升序进行排序”功能,点击左侧的“价格 升序”按钮,结果如下图所示,验证成功。
最后测试“模糊搜索”功能,鼠标移到屏幕右上角的放大镜上,在弹出的输入框输入 关键字"HONEY",点击“搜索”按钮进行检索,注意,按回车确认是无效的,只有点击“搜索”按钮才有效。
检索结果如下图所示。
本文至此结束。