前言:本文从零开始详细叙述SSM框架的搭建和DEMO构建过程,并作出博主自己对于SSM框架的理解。本人能力有限,叙述难免会有错误和疏漏,还请各位读者包容指正。至于说为什么是“从零开始”,是因为学校课程要求用SSM开发一个网页,而本人在此之前基本没有接触过JAVA,也从来没有开发过网页。在摸索的途中踩了许多坑,在网上找到的教程都不够完美,故撰此文以供本人日后不时之需,也供广大入门者参考之用。为了便于读者理解,本文所提供之DEMO是根据本人近期一大作业(实现一个卖甜点的网上商城)大幅简化而来,只涉及最基本的各层传参、数据库查询、结果显示功能。 本文假定读者已安装IntelliJ IDEA、JDK、JRE、Tomcat、MySQL等外部依赖并正确配置环境变量。
0.基础知识
【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"页面,负责将结果显示给用户。
1.工程创建
启动IntelliJ IDEA,如下图所示新建一个Maven webapp项目,注意勾选"Create from archetype"选项。
GroupId在这里应该是可以随意填写的。本项目的DEMO是一个卖蛋糕的网上商城,因此制品ID就叫做CAKESHOP好了。
点击下一步后出现以下界面,本项目使用内置Maven创建,如果此前没有创建过Maven工程,请确认下图中的settings.xml是否存在,若不存在,需要自己导入配置文件。
一切确认完成后,生成项目,第一次创建项目时会下载一些组件(如下图所示),请耐心等待。
下载完成后,项目的目录结构应该如下图所示。
2.搭建SSM框架
接上,我们手动创建一系列目录和(空)文件,最终效果如下所示。
接下来将pom.xml中的代码替换为下面的代码。pom.xml的作用是告诉Maven需要引入哪些jar包。在这里推荐一个网站http://mvnrepository.com/ 可以在此检索所需jar包的版本和对应的xml代码。替换代码后,IntelliJ IDEA需要联网下载所需的jar包。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
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>CAKESHOP</groupId>
<artifactId>CAKESHOP</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>CAKESHOP Maven Webapp</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!-- java ee -->
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
</dependency>
<!-- 单元测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
<!-- 添加jstl依赖 -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
</dependency>
<!-- 添加spring核心依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-oxm</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
<!-- 添加mybatis依赖 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.2</version>
</dependency>
<!-- 添加mybatis/spring整合包依赖 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.0</version>
</dependency>
<!--添加mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.25</version>
</dependency>
<!-- 添加数据库连接池依赖 -->
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.2.2</version>
</dependency>
<!-- 添加日志相关jar包 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.18</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.18</version>
</dependency>
<!-- log end -->
<!-- 映入JSON -->
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.13</version>
</dependency>
<!-- <dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.4</version>
<classifier>jdk15</classifier>
</dependency>-->
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.8.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>org.jdom</groupId>
<artifactId>jdom2</artifactId>
<version>2.0.5</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
<version>4.4.5</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>fluent-hc</artifactId>
<version>4.5.2</version>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.3</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.9</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.0</version>
</dependency>
</dependencies>
<build>
<finalName>CAKESHOP</finalName>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
<include>**/*.tld</include>
<include>**/*.jsp</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
<include>**/*.tld</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.0.0</version>
</plugin>
<!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.20.1</version>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.0</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
替换applicationContext.xml代码如下
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:task="http://www.springframework.org/schema/task"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd">
<context:property-placeholder location="classpath:jdbc.properties"/>
<!-- data source -->
<!-- 配置数据源 -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</bean>
<!-- transaction manager -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- enable component scanning -->
<context:component-scan base-package="com.CAKESHOP.*"/>
<!-- enable autowire -->
<context:annotation-config/>
<!-- enable transaction demarcation with annotations -->
<tx:annotation-driven/>
<!--定时任务的开启 以及多线程及线程池配置-->
<task:annotation-driven scheduler="myScheduler"/>
<task:scheduler id="myScheduler" pool-size="5"/><!--线程池配置方式-->
<!-- mybatis SqlSessionFactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<!-- according to the actual situation add more properties -->
<property name="typeAliasesPackage" value="com.vo"/>
</bean>
<!-- mybatis mapper(automatic scan configuration files -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- according to the actual situation add more properties -->
<property name="basePackage" value="com.CAKESHOP.mapper"/>
</bean>
</beans>
替换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代码如下
<?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>
</configuration>
替换SpringMVC.xml代码如下
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<!-- 自动扫描 @Controller-->
<context:component-scan base-package="com.CAKESHOP.controller"/>
<!--避免IE执行AJAX时,返回JSON出现下载文件 -->
<bean id="mappingJacksonHttpMessageConverter"
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/html;charset=UTF-8</value>
</list>
</property>
</bean>
<!-- 启动SpringMVC的注解功能,完成请求和注解POJO的映射 -->
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="mappingJacksonHttpMessageConverter"/> <!-- JSON转换器 -->
</list>
</property>
</bean>
<!-- 启动Spring MVC的注解功能,完成请求和注解POJO的映射,解决@ResponseBody乱码问题, 需要在annotation-
driven之前,否则乱码问题同样无法解决 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/html;charset=UTF-8</value>
</list>
</property>
</bean>
</list>
</property>
</bean>
<!-- 定义跳转的文件的前后缀 ,视图模式配置 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!-- 文件上传配置 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 默认编码 -->
<property name="defaultEncoding" value="UTF-8"/>
<!-- 上传文件大小限制为31M,31*1024*1024 -->
<property name="maxUploadSize" value="32505856"/>
<!-- 内存中的最大值 -->
<property name="maxInMemorySize" value="4096"/>
</bean>
</beans>
替换web.xml代码如下
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<display-name>CAKESHOP</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>classpath:log4j.properties</param-value>
</context-param>
<!-- 编码过滤器 -->
<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>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- spring监听器 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 防止spring内存溢出监听器,比如quartz -->
<listener>
<listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
</listener>
<!-- spring mvc servlet-->
<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:SpringMVC.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<async-supported>true</async-supported>
</servlet>
<servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<!-- 配置成"*.html"以匹配所有后缀名为html的请求 -->
<!-- 这里我遇到了一个奇怪的地方:如果我将url-pattern设置成/匹配所有请求,就无法加载样式 -->
<url-pattern>*.html</url-pattern>
</servlet-mapping>
<!-- 设置欢迎页面 -->
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<!-- session配置 -->
<session-config>
<session-timeout>15</session-timeout>
</session-config>
</web-app>
部署Tomcat
点击界面右上角"Add Configuration"按钮
在弹出页面点击左上角的"+"号
如下图,选择"Local"
如下图进行配置后,点击"Deployment"按钮
点击"+"号
选择"Artifact"
如下图选择并确定
在这里可以配置网站的后缀名(可选),这里为了个性化,配置为"CAKESHOP",这样在项目部署后,输入"http://localhost:8080/CAKESHOP/"即可访问网站首页。
如下图选择运行配置,再点击绿色三角部署网页。
等待十几秒后,系统会自动弹出网站首页如下。至此SSM框架的搭建基本完成。
3.构建DEMO
(本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<Product> 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<Product> 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<Product> 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<Product> selectAllProduct();
List<Product> selectProductsPriceAscending();
//将"String"类型的变量"searchKey"以"searchKey"为参数名传入到WebMapper.xml中
List<Product> selectProductsSearch(@Param(value = "searchKey") String searchKey);
}
数据库中product表的结构如下所示。
WebMapper.xml实现WebMapper.java中声明的方法,主要是一些SQL语句,其代码如下所示。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.CAKESHOP.mapper.WebMapper">
<!-- 下面的三对select标签中,"id"与"WebMapper.java"中的方法一一对应,"resultMap"与最后"resultMap"标签中的"id"呈多对一映射关系 -->
<!-- 下面的SQL语句实现按照价格升序查找商品 -->
<select id="selectProductsPriceAscending" resultMap="ProductMap">
select * from product order by prize asc
</select>
<!-- 下面的SQL语句实现按照商品名升序查找商品(产品的默认显示方式) -->
<select id="selectAllProduct" resultMap="ProductMap">
select * from product order by name asc
</select>
<!-- 下面的SQL语句实现关键字查找商品 -->
<select id="selectProductsSearch" resultMap="ProductMap">
select *
from product
where name like"%${searchKey}%";--在这里引用WebMapper.java中传入的参数"searchKey"
</select>
<!-- 下面的SQL语句实现数据库信息向Product类的传输(即数据库——>DAO层) -->
<resultMap id="ProductMap" type="com.CAKESHOP.dao.Product">
<!-- 下面"result"标签中,"column"与数据库表中的列名对应,"property"与DAO层定义的类中的属性对应(在这里指"Product.java"),一般取同名 -->
<id column="ID" property="ID" jdbcType="INTEGER"/>
<result column="ID" property="ID" jdbcType="INTEGER"/>
<result column="name" property="name" jdbcType="VARCHAR"/>
<result column="num" property="num" jdbcType="INTEGER"/>
<result column="prize" property="prize" jdbcType="DOUBLE"/>
<result column="category" property="category" jdbcType="VARCHAR"/>
<result column="flavour" property="flavour" jdbcType="VARCHAR"/>
<result column="weight" property="weight" jdbcType="VARCHAR"/>
<result column="color" property="color" jdbcType="VARCHAR"/>
<result column="detail" property="detail" jdbcType="VARCHAR"/>
</resultMap>
</mapper>
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<Product> queryProductsPriceAscending();
List<Product> queryProductsSearch(String searchKey);
List<Product> 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<Product> queryProductsPriceAscending() {
return webMapper.selectProductsPriceAscending();
}
@Override
public List<Product> queryAllProducts() {
return webMapper.selectAllProduct();
}
@Override
public List<Product> 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" %>
<!DOCTYPE html>
<html>
<head>
<title>Products</title>
<!-- Custom Theme files -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta name="keywords" content=""/>
<script type="application/x-javascript"> addEventListener("load", function () {
setTimeout(hideURLbar, 0);
}, false);
function hideURLbar() {
window.scrollTo(0, 1);
} </script>
<!-- //Custom Theme files -->
<link href="css/bootstrap.css" type="text/css" rel="stylesheet" media="all">
<link href="css/style.css" type="text/css" rel="stylesheet" media="all">
<link href="css/form.css" rel="stylesheet" type="text/css" media="all"/>
<!-- js -->
<script src="js/jquery.min.js"></script>
<script type="text/javascript" src="js/bootstrap-3.1.1.min.js"></script>
<!-- //js -->
<!-- cart -->
<script src="js/simpleCart.min.js"></script>
<!-- cart -->
<!-- the jScrollPane script -->
<script type="text/javascript" src="js/jquery.jscrollpane.min.js"></script>
<script type="text/javascript" id="sourcecode">
$(function () {
$('.scroll-pane').jScrollPane();
});
</script>
<!-- //the jScrollPane script -->
<script type="text/javascript" src="js/jquery.mousewheel.js"></script>
<!-- the mousewheel plugin -->
</head>
<body>
<!--header-->
<div class="header">
<div class="container">
<nav class="navbar navbar-default" role="navigation">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse"
data-target="#bs-example-navbar-collapse-1">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<h1 class="navbar-brand"><a href="WEB-INF/jsp/index.html">CAKESHOP</a></h1>
</div>
<!--navbar-header-->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li><a href="WEB-INF/jsp/index.html" class="active">Home</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Order<b class="caret"></b></a>
<ul class="dropdown-menu multi-column columns-4">
<div class="row">
<div class="col-sm-3">
<h4>TransNo</h4>
<ul class="multi-column-dropdown">
<li><a class="list" href="products.html">10123</a></li>
<li><a class="list" href="products.html">20123</a></li>
<li><a class="list" href="products.html">38901</a></li>
<li><a class="list" href="products.html">47899</a></li>
<li><a class="list" href="products.html">54452</a></li>
<li><a class="list" href="products.html">61212</a></li>
</ul>
</div>
<div class="col-sm-3">
<h4>Carrier</h4>
<ul class="multi-column-dropdown">
<li><a class="list" href="products.html">顺丰配送</a></li>
<li><a class="list" href="products.html">本店配送</a></li>
<li><a class="list" href="products.html">上门提取</a></li>
<li><a class="list" href="products.html">德邦物流</a></li>
</ul>
</div>
<div class="col-sm-3">
<h4>TransState</h4>
<ul class="multi-column-dropdown">
<li><a class="list" href="products.html">未评价</a></li>
<li><a class="list" href="products.html">未收货</a></li>
<li><a class="list" href="products.html">未发货</a></li>
<li><a class="list" href="products.html">未付款</a></li>
<li><a class="list" href="products.html">未评价</a></li>
<li><a class="list" href="products.html">未付款</a></li>
</ul>
</div>
</div>
</ul>
</li>
<li class="dropdown grid">
<a href="#" class="dropdown-toggle list1" data-toggle="dropdown">Wedding<b
class="caret"></b></a>
<ul class="dropdown-menu multi-column columns-4">
<div class="row">
<div class="col-sm-3">
<h4>By Relation</h4>
<ul class="multi-column-dropdown">
<li><a class="list" href="products.html">Friend</a></li>
<li><a class="list" href="products.html">Lover</a></li>
<li><a class="list" href="products.html">Sister</a></li>
<li><a class="list" href="products.html">Brother</a></li>
<li><a class="list" href="products.html">Kids</a></li>
<li><a class="list" href="products.html">Parents</a></li>
</ul>
</div>
<div class="col-sm-3">
<h4>By Flavour</h4>
<ul class="multi-column-dropdown">
<li><a class="list" href="products.html">Chocolate</a></li>
<li><a class="list" href="products.html">Mixed Fruit</a></li>
<li><a class="list" href="products.html">Butterscotch</a></li>
<li><a class="list" href="products.html">Strawberry</a></li>
<li><a class="list" href="products.html">Vanilla</a></li>
<li><a class="list" href="products.html">Eggless Cakes</a></li>
</ul>
</div>
<div class="col-sm-3">
<h4>By Theme</h4>
<ul class="multi-column-dropdown">
<li><a class="list" href="products.html">Heart shaped</a></li>
<li><a class="list" href="products.html">Cartoon Cakes</a></li>
<li><a class="list" href="products.html">2-3 Tier Cakes</a></li>
<li><a class="list" href="products.html">Square shape</a></li>
<li><a class="list" href="products.html">Round shape</a></li>
<li><a class="list" href="products.html">Photo cakes</a></li>
</ul>
</div>
<div class="col-sm-3">
<h4>Weight</h4>
<ul class="multi-column-dropdown">
<li><a class="list" href="products.html">1 kG</a></li>
<li><a class="list" href="products.html">1.5 kG</a></li>
<li><a class="list" href="products.html">2 kG</a></li>
<li><a class="list" href="products.html">3 kG</a></li>
<li><a class="list" href="products.html">4 kG</a></li>
<li><a class="list" href="products.html">Large</a></li>
</ul>
</div>
</div>
</ul>
</li>
<li class="dropdown grid">
<a href="#" class="dropdown-toggle list1" data-toggle="dropdown">Special Offers <b
class="caret"></b></a>
<ul class="dropdown-menu multi-column columns-4">
<div class="row">
<div class="col-sm-3">
<h4>By Relation</h4>
<ul class="multi-column-dropdown">
<li><a class="list" href="products.html">Friend</a></li>
<li><a class="list" href="products.html">Lover</a></li>
<li><a class="list" href="products.html">Sister</a></li>
<li><a class="list" href="products.html">Brother</a></li>
<li><a class="list" href="products.html">Kids</a></li>
<li><a class="list" href="products.html">Parents</a></li>
</ul>
</div>
<div class="col-sm-3">
<h4>By Flavour</h4>
<ul class="multi-column-dropdown">
<li><a class="list" href="products.html">Chocolate</a></li>
<li><a class="list" href="products.html">Mixed Fruit</a></li>
<li><a class="list" href="products.html">Butterscotch</a></li>
<li><a class="list" href="products.html">Strawberry</a></li>
<li><a class="list" href="products.html">Vanilla</a></li>
<li><a class="list" href="products.html">Eggless Cakes</a></li>
</ul>
</div>
<div class="col-sm-3">
<h4>By Theme</h4>
<ul class="multi-column-dropdown">
<li><a class="list" href="products.html">Heart shaped</a></li>
<li><a class="list" href="products.html">Cartoon Cakes</a></li>
<li><a class="list" href="products.html">2-3 Tier Cakes</a></li>
<li><a class="list" href="products.html">Square shape</a></li>
<li><a class="list" href="products.html">Round shape</a></li>
<li><a class="list" href="products.html">Photo cakes</a></li>
</ul>
</div>
<div class="col-sm-3">
<h4>Weight</h4>
<ul class="multi-column-dropdown">
<li><a class="list" href="products.html">1 kG</a></li>
<li><a class="list" href="products.html">1.5 kG</a></li>
<li><a class="list" href="products.html">2 kG</a></li>
<li><a class="list" href="products.html">3 kG</a></li>
<li><a class="list" href="products.html">4 kG</a></li>
<li><a class="list" href="products.html">Large</a></li>
</ul>
</div>
</div>
</ul>
</li>
<li class="dropdown grid">
<a href="#" class="dropdown-toggle list1" data-toggle="dropdown">Store<b class="caret"></b></a>
<ul class="dropdown-menu multi-column columns-3">
<div class="row">
<div class="col-sm-4">
<h4>By Relation</h4>
<ul class="multi-column-dropdown">
<li><a class="list" href="products.html">Friend</a></li>
<li><a class="list" href="products.html">Lover</a></li>
<li><a class="list" href="products.html">Sister</a></li>
<li><a class="list" href="products.html">Brother</a></li>
<li><a class="list" href="products.html">Kids</a></li>
<li><a class="list" href="products.html">Parents</a></li>
</ul>
</div>
<div class="col-sm-4">
<h4>By Flavour</h4>
<ul class="multi-column-dropdown">
<li><a class="list" href="products.html">Chocolate</a></li>
<li><a class="list" href="products.html">Mixed Fruit</a></li>
<li><a class="list" href="products.html">Butterscotch</a></li>
<li><a class="list" href="products.html">Strawberry</a></li>
<li><a class="list" href="products.html">Vanilla</a></li>
<li><a class="list" href="products.html">Eggless Cakes</a></li>
</ul>
</div>
<div class="col-sm-4">
<h4>Specials</h4>
<ul class="multi-column-dropdown">
<li><a class="list" href="products.html">Ice cream cake</a></li>
<li><a class="list" href="products.html">Swiss roll</a></li>
<li><a class="list" href="products.html">Ruske kape</a></li>
<li><a class="list" href="products.html">Cupcakes</a></li>
<li><a class="list" href="products.html">Muffin</a></li>
<li><a class="list" href="products.html">Merveilleux</a></li>
</ul>
</div>
</div>
</ul>
</li>
</ul>
<!--/.navbar-collapse-->
</div>
<!--//navbar-header-->
</nav>
<div class="header-info">
<div class="header-right search-box">
<a href="#"><span class="glyphicon glyphicon-search" aria-hidden="true"></span></a>
<div class="search">
<form class="navbar-form">
<input type="text" id="searchKey" name="searchKey" class="form-control">
<button type="button" class="btn btn-default" aria-label="Left Align"
onclick="location.href = 'products_search.html?c_id='+'${requestScope.c_id}'+'&searchKey='+document.getElementById('searchKey').value">
搜索
</button>
</form>
</div>
</div>
<div class="header-right login">
<a href="#"><span class="glyphicon glyphicon-user" aria-hidden="true"></span></a>
<div id="loginBox">
<form id="loginForm">
<fieldset id="body">
<fieldset>
<label for="email">Email Address</label>
<input type="text" name="email" id="email">
</fieldset>
<fieldset>
<label for="password">Password</label>
<input type="password" name="password" id="password">
</fieldset>
<input type="submit" id="login" value="Sign in">
<label for="checkbox"><input type="checkbox" id="checkbox"> <i>Remember me</i></label>
</fieldset>
<p>New User ? <a class="sign" href="WEB-INF/jsp/account.html">Sign Up</a> <span><a href="#">Forgot your password?</a></span>
</p>
</form>
</div>
</div>
<div class="header-right cart">
<a href="#"><span class="glyphicon glyphicon-shopping-cart" aria-hidden="true"></span></a>
<div class="cart-box">
<h4><a href="WEB-INF/jsp/checkout.html">
<span class="simpleCart_total"> ¥0.00 </span> (<span id="simpleCart_quantity"
class="simpleCart_quantity"> 0 </span>)
</a></h4>
<p><a href="javascript:;" class="simpleCart_empty">Empty cart</a></p>
<div class="clearfix"></div>
</div>
</div>
<div class="clearfix"></div>
</div>
<div class="clearfix"></div>
</div>
</div>
<!--//header-->
<!--products-->
<div class="products">
<div class="container">
<h2>Our Products</h2>
<div class="col-md-9 product-model-sec">
<!-- 依次显示每一个商品 -->
<c:forEach items="${requestScope.products}" var="product">
<!-- 下面是显示单个商品的代码块 -->
<div class="product-grid">
<a href="WEB-INF/jsp/single.html?c_id=${requestScope.c_id }&p_id=${product.ID }">
<div class="more-product"><span> </span></div>
<div class="product-img b-link-stripe b-animate-go thickbox">
<!-- 固定商品图片的大小,否则会引起布局混乱 -->
<br>
<img src="${product.imgPath}" height="150" width="200">
<div class="b-wrapper">
<h4 class="b-animate b-from-left b-delay03">
<button>浏览详情</button>
</h4>
</div>
</div>
</a>
<div class="product-info simpleCart_shelfItem">
<div class="product-info-cust prt_name">
<h4>${product.name}</h4>
<span class="item_price">¥${product.prize }</span>
<input name="numOfProducts" id=${product.ID } value=1 type="text" style="width:30px;"/>
<!-- 下面的代码实现url传参 -->
<input type="button" class="item_add items" value="购买"
onclick="location.href = 'payment.html?c_id='+'${requestScope.c_id}'+'&p_id='+'${product.ID }'+'&num='+document.getElementById(${product.ID }).value">
<!-- 上面的代码实现url传参 -->
<div class="clearfix"></div>
</div>
</div>
</div>
<!-- 上面是显示单个商品的代码块 -->
</c:forEach>
</div>
<div class="col-md-3 rsidebar span_1_of_left">
<section class="sky-form">
<h4><span class="glyphicon glyphicon-minus" aria-hidden="true"></span>ORDER BY</h4>
<div class="row row1 scroll-pane">
<div class="col col-4">
<a href="products_price_ascending.html?c_id=${requestScope.c_id}" class="checkbox"><input
type="checkbox"
\name="checkbox"
checked=""><i></i>价格 升序</a>
<a href="products_price_descending.html?c_id=${requestScope.c_id}" class="checkbox"><input
type="checkbox"
name="checkbox"
checked=""><i></i>价格 降序</a>
<a href="products_sales_ascending.html?c_id=${requestScope.c_id}" class="checkbox"><input
type="checkbox"
name="checkbox"
checked=""><i></i>销量 升序</a>
<a href="products_sales_descending.html?c_id=${requestScope.c_id}" class="checkbox"><input
type="checkbox"
name="checkbox"
checked=""><i></i>销量 降序</a>
<a href="products_popularity_ascending.html?c_id=${requestScope.c_id}" class="checkbox"><input
type="checkbox"
name="checkbox"
checked=""><i></i>人气 升序</a>
<a href="products_popularity_descending.html?c_id=${requestScope.c_id}" class="checkbox"><input
type="checkbox"
name="checkbox"
checked=""><i></i>人气 降序</a>
</div>
</div>
</section>
<section class="sky-form">
<h4><span class="glyphicon glyphicon-minus" aria-hidden="true"></span>CATEGORIES</h4>
<div class="row row1 scroll-pane">
<div class="col col-4">
<a href="products_regular_cakes.html?c_id=${requestScope.c_id}" class="checkbox"><input
type="checkbox"
\name="checkbox"
checked=""><i></i>Regular Cakes</a>
<a href="products_special_cakes.html?c_id=${requestScope.c_id}" class="checkbox"><input
type="checkbox"
\name="checkbox"
checked=""><i></i>Special Cakes</a>
<a href="products_eggless_cakes.html?c_id=${requestScope.c_id}" class="checkbox"><input
type="checkbox"
\name="checkbox"
checked=""><i></i>Eggless Cakes</a>
<a href="products_2to3_tier_cakes.html?c_id=${requestScope.c_id}" class="checkbox"><input
type="checkbox"
\name="checkbox"
checked=""><i></i>2-3 Tier Cakes</a>
</div>
</div>
</section>
<section class="sky-form">
<h4><span class="glyphicon glyphicon-minus" aria-hidden="true"></span>DISCOUNTS</h4>
<div class="row row1 scroll-pane">
<div class="col col-4">
<label class="checkbox"><input type="checkbox" name="checkbox" checked=""><i></i>Upto - 10% (20)</label>
</div>
<div class="col col-4">
<label class="checkbox"><input type="checkbox" name="checkbox"><i></i>70% - 60%</label>
<label class="checkbox"><input type="checkbox" name="checkbox"><i></i>50% - 40%</label>
<label class="checkbox"><input type="checkbox" name="checkbox"><i></i>30% - 20%</label>
<label class="checkbox"><input type="checkbox" name="checkbox"><i></i>10% - 5%</label>
<label class="checkbox"><input type="checkbox" name="checkbox"><i></i>30% - 20%</label>
<label class="checkbox"><input type="checkbox" name="checkbox"><i></i>10% - 5%</label>
<label class="checkbox"><input type="checkbox" name="checkbox"><i></i>Other</label>
</div>
</div>
</section>
<section class="sky-form">
<h4><span class="glyphicon glyphicon-minus" aria-hidden="true"></span>Price</h4>
<ul class="dropdown-menu1">
<li><a href="">
<div id="slider-range"></div>
<input type="text" id="amount"
style="border: 0; font-weight: NORMAL; font-family: 'Dosis-Regular';"/>
</a></li>
</ul>
</section>
<script type="text/javascript" src="js/jquery-ui.min.js"></script>
<link rel="stylesheet" type="text/css" href="css/jquery-ui.css">
<script type='text/javascript'>//<![CDATA[
$(window).load(function () {
$("#slider-range").slider({
range: true,
min: 0,
max: 100000,
values: [500, 100000],
slide: function (event, ui) {
$("#amount").val("$" + ui.values[0] + " - $" + ui.values[1]);
}
});
$("#amount").val("$" + $("#slider-range").slider("values", 0) + " - $" + $("#slider-range").slider("values", 1));
});//]]>
</script>
<!---->
<section class="sky-form">
<h4><span class="glyphicon glyphicon-minus" aria-hidden="true"></span>By Flavour</h4>
<div class="row row1 scroll-pane">
<div class="col col-4">
<a href="products_by_flavour.html?c_id=${requestScope.c_id}&flavour=Chocolate" class="checkbox"><input
type="checkbox"
\name="checkbox"
checked=""><i></i>Chocolate</a>
<a href="products_by_flavour.html?c_id=${requestScope.c_id}&flavour=Butterscotch"
class="checkbox"><input type="checkbox"
\name="checkbox"
checked=""><i></i>Butterscotch</a>
<a href="products_by_flavour.html?c_id=${requestScope.c_id}&flavour=Strawberry"
class="checkbox"><input type="checkbox"
\name="checkbox"
checked=""><i></i>Strawberry</a>
<a href="products_by_flavour.html?c_id=${requestScope.c_id}&flavour=Black+Forest"
class="checkbox"><input type="checkbox"
\name="checkbox"
checked=""><i></i>Black Forest</a>
<a href="products_by_flavour.html?c_id=${requestScope.c_id}&flavour=Mixed+Fruit"
class="checkbox"><input type="checkbox"
\name="checkbox"
checked=""><i></i>Mixed Fruit</a>
<a href="products_by_flavour.html?c_id=${requestScope.c_id}&flavour=Honey"
class="checkbox"><input type="checkbox"
\name="checkbox"
checked=""><i></i>Honey</a>
</div>
</div>
</section>
<section class="sky-form">
<h4><span class="glyphicon glyphicon-minus" aria-hidden="true"></span>Weight</h4>
<div class="row row1 scroll-pane">
<div class="col col-4">
<a href="products_by_weight.html?c_id=${requestScope.c_id}&weight=Half+KG"
class="checkbox"><input type="checkbox"
\name="checkbox"
checked=""><i></i>Half KG</a>
<a href="products_by_weight.html?c_id=${requestScope.c_id}&weight=One+KG"
class="checkbox"><input type="checkbox"
\name="checkbox"
checked=""><i></i>One KG</a>
<a href="products_by_weight.html?c_id=${requestScope.c_id}&weight=One+KG"
class="checkbox"><input type="checkbox"
\name="checkbox"
checked=""><i></i>Two KG</a>
<a href="products_by_weight.html?c_id=${requestScope.c_id}&weight=More" class="checkbox"><input
type="checkbox"
\name="checkbox"
checked=""><i></i>More</a>
</div>
</div>
</section>
<section class="sky-form">
<h4><span class="glyphicon glyphicon-minus" aria-hidden="true"></span>Color</h4>
<div class="row row1 scroll-pane">
<div class="col col-4">
<a href="products_by_color.html?c_id=${requestScope.c_id}&color=White" class="checkbox"><input
type="checkbox"
\name="checkbox"
checked=""><i></i>White</a>
<a href="products_by_color.html?c_id=${requestScope.c_id}&color=Pink" class="checkbox"><input
type="checkbox"
\name="checkbox"
checked=""><i></i>Pink</a>
<a href="products_by_color.html?c_id=${requestScope.c_id}&color=Gold" class="checkbox"><input
type="checkbox"
\name="checkbox"
checked=""><i></i>Gold</a>
<a href="products_by_color.html?c_id=${requestScope.c_id}&color=Silver" class="checkbox"><input
type="checkbox"
\name="checkbox"
checked=""><i></i>Silver</a>
</div>
</div>
</section>
</div>
<div class="clearfix"></div>
</div>
</div>
<!--//products-->
<!--footer-->
<div class="footer">
<div class="container">
<div class="footer-grids">
<div class="col-md-2 footer-grid">
<h4>company</h4>
<ul>
<li><a href="products.html">products</a></li>
<li><a href="#">Work Here</a></li>
<li><a href="#">Team</a></li>
<li><a href="#">Happenings</a></li>
<li><a href="#">Dealer Locator</a></li>
</ul>
</div>
<div class="col-md-2 footer-grid">
<h4>service</h4>
<ul>
<li><a href="#">Support</a></li>
<li><a href="#">FAQ</a></li>
<li><a href="#">Warranty</a></li>
<li><a href="WEB-INF/jsp/contact.html">Contact Us</a></li>
</ul>
</div>
<div class="col-md-3 footer-grid">
<h4>order & returns</h4>
<ul>
<li><a href="#">Order Status</a></li>
<li><a href="#">Shipping Policy</a></li>
<li><a href="#">Return Policy</a></li>
<li><a href="#">Digital Gift Card</a></li>
</ul>
</div>
<div class="col-md-2 footer-grid">
<h4>legal</h4>
<ul>
<li><a href="#">Privacy</a></li>
<li><a href="#">Terms and Conditions</a></li>
<li><a href="#">Social Responsibility</a></li>
</ul>
</div>
<div class="col-md-3 footer-grid icons">
<h4>Connect with Us</h4>
<ul>
<li><a href="#"><img src="images/i1.png" alt=""/>Follow us on Facebook</a></li>
<li><a href="#"><img src="images/i2.png" alt=""/>Follow us on Twitter</a></li>
<li><a href="#"><img src="images/i3.png" alt=""/>Follow us on Google-plus</a></li>
<li><a href="#"><img src="images/i4.png" alt=""/>Follow us on Pinterest</a></li>
</ul>
</div>
<div class="clearfix"></div>
</div>
</div>
</div>
<!--//footer-->
<div class="footer-bottom">
<div class="container">
<p>Copyright © 2018.CAKESHOP.[转载请注明出处] <a href="https://my.csdn.net/qq897107499"
target="_blank"
title="访问DEMO作者主页">访问DEMO作者主页</a> - The template was collected from
<a href="http://www.cssmoban.com/" title="网页模板" target="_blank">网页模板</a></p>
</div>
</div>
</body>
</html>
按照上面的方法配置完项目后,DEMO就构建完成了。
4.运行测试
还是像文章最开始说到的,点击右上角的绿色三角进行部署。成功后首页如下图所示。
点击"SHOP NOW",跳转到商品浏览页面,如下图所示。默认显示顺序是按照商品名增序进行排列。
接着我们测试“按价格升序进行排序”功能,点击左侧的“价格 升序”按钮,结果如下图所示,验证成功。
最后测试“模糊搜索”功能,鼠标移到屏幕右上角的放大镜上,在弹出的输入框输入 关键字"HONEY",点击“搜索”按钮进行检索,注意,按回车确认是无效的,只有点击“搜索”按钮才有效。
检索结果如下图所示。
本文至此结束。