您的位置:首页 > 编程语言 > Java开发

Java Web实战08-Spring、Spring MVC和Hibernate实现收银机系统(XML版本)

2016-07-15 22:14 573 查看
前面参加一个公司的活动,做了一份收银机系统的作业,当时时间紧,花费一天时间用Swing界面做的,比较简单。代码在GitHub:https://github.com/yefengzhichen/twTask。最近正好学习了Spring,以及了解了Html和JSP,于是就将此作业改写成了Spring、Spring MVC、Hibernate、Html和JSP结合的版本。

一、需求简介

商店的收银机系统,会根据购买商品和商店的打折活动进行打折。已知商品信息包含:名称,数量单位,单价,类别和条形码(伪)。以下是单个商品对象的结构:

barcode: 'ITEM000000', name: '可口可乐', unit: '瓶', category: '食品', subCategory: '碳酸饮料', price: 3.00

实现功能:

1、输入商品条形码列表,输出小票详细信息的功能。

输入例子:Item0002,Item0010-10。逗号分隔商品,“-”分隔条形码和数量或者重量。

输出为:

` *<没钱赚商店>购物清单* 名称:apple,数量:10.0kg,单价:13.00(元),小计:130.00(元),优惠:10.00(元) 名称:milk,数量:1.0box,单价:3.50(元),小计:3.50(元)
单品满100减10块商品: 商品:apple,原价:130.0(元),优惠:10.0(元)

总计:123.50(元) 节省:10.00(元)

2、增加打折商品的功能,输入需要打折的商品条形码。
除外,为了练习Hibernate相关,增加了以下功能:
3、注册功能,输入注册信息保存到数据库。
4、登录功能,验证用户是否有效,有效则进入收银机系统。
5、动态添加商品信息功能
主界面展示如下:



二、实现详细过程

开发环境搭建以及Maven工程构建和本系列之前的一样,在此略过。

2.1 JAR包引入

整个项目中,使用的JAR基本都是最新的,直接到Maven Repository上搜索复制的。主要用到的是:Spring 4和Hibernate 5。详细JAR见下面的pom.xml内容:

<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/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion>
<groupId>com.yefeng.spring</groupId>
<artifactId>cashapp</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>cashapp Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.0.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.0.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-beans -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.3.0.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-expression -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>4.3.0.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.3.0.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.3.0.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.0.RELEASE</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-core -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.2.1.Final</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-annotations <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-annotations</artifactId>
<version>3.5.6-Final</version> </dependency> -->
<!-- https://mvnrepository.com/artifact/c3p0/c3p0 -->
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>6.0.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-orm -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>4.3.1.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.jboss.spec.javax.transaction/jboss-transaction-api_1.1_spec -->
<dependency>
<groupId>org.jboss.spec.javax.transaction</groupId>
<artifactId>jboss-transaction-api_1.1_spec</artifactId>
<version>1.0.1.Final</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-tx -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>4.3.1.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.9</version>
</dependency>
<!-- https://mvnrepository.com/artifact/jstl/jstl -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-test -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.3.0.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-lang/commons-lang -->
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.21</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.hibernate.common/hibernate-commons-annotations -->
<dependency>
<groupId>org.hibernate.common</groupId>
<artifactId>hibernate-commons-annotations</artifactId>
<version>5.0.1.Final</version>
</dependency>
</dependencies>
<build>
<finalName>cashapp</finalName>
</build>
</project>


2.2配置web.xml和各种组件bean

因为将bean配置到两个xml文件root-context.xml、cashapp-context.xml中,web.xml中配置很简单,配置分发器和监听器,以及两个文件的路径以及映射即可。其中,<param-value>的路径默认从根路径webapp下查找,因此当配置在类路径下时,需要加classpath前缀。两个context文件位置放到webapp下或者类路径下都是可以的。
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" id="schedule-console" version="3.0">
<display-name>Archetype Created Web Application</display-name>

<!-- 根配置文件路径,配置除web组件以外的bean,后端的数据层和中间层-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:root-context.xml</param-value>
</context-param>
<!--加载上面的根配置文件监听器  -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 配置分发器,加载web组件的bean,如控制器、视图解析器 -->
<servlet>
<servlet-name>cashapp</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/config/cashapp-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- 处理器映射 -->
<servlet-mapping>
<servlet-name>cashapp</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

</web-app>
cashapp-context.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"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd 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-4.3.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd"> <!-- 静态资源路径配置,配置后,静态资源将不用分发器处理即可获得,此项目中未使用 -->
<mvc:resources mapping="/static/**" location="/WEB-INF/static/" />
<!-- mvc配置注解驱动 -->
<mvc:annotation-driven/>
<!-- 启动自动扫面组件 -->
<context:component-scan base-package="com.yefeng.cashapp.web"/>
<!-- 视图处理器,自动添加前缀后缀 -->
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>


root-context.xml,配置了数据库属性,以及C3P0数据源,HIbernate事务管理器,并定义了相应的事务属性。虽然此书的数据库操作都很简单,并没有多个表一起修改的操作,但为了后面扩展,因此定义事务。
<?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:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd 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-4.3.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd"> <!-- 启动切面自动代理 -->
<aop:aspectj-autoproxy proxy-target-class="true" />
<!-- 读取数据源配置 -->
<context:property-placeholder location="classpath:mysql.properties" />
<!-- 自动扫面DAO和Service层的组件 -->
<context:component-scan base-package="com.yefeng.cashapp.dao"></context:component-scan>
<context:component-scan base-package="com.yefeng.cashapp.service"></context:component-scan>
<!-- 数据源bean, -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="${user}"></property>
<property name="password" value="${password}"></property>
<property name="driverClass" value="${driverClass}"></property>
<property name="jdbcUrl" value="${jdbcUrl}"></property>
<property name="initialPoolSize" value="${initPoolSize}"></property>
<property name="maxPoolSize" value="${maxPoolSize}"></property>
</bean>
<!--配置Hibernate sessionFactory-->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="configLocation" value="classpath:hibernate.cfg.xml"></property>
<property name="mappingLocations">
<list>
<value>classpath:com/yefeng/cashapp/model/User.hbm.xml</value>
<value>classpath:com/yefeng/cashapp/model/Product.hbm.xml</value>
</list>
</property>
</bean>
<!--配置Hibernate事务管理器 -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<!--配置事务切面属性 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="get*" read-only="true" />
<tx:method name="*" />
</tx:attributes>
</tx:advice>
<!--配置切点 -->
<aop:config>
<aop:pointcut id="daoPointcut"
expression="execution(* com.yefeng.cashapp.dao.*.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="daoPointcut" />
</aop:config>
</beans>


数据库连接文件mysql.properties内容:
user=root
password=
#com.mysql.cj.jdbc.Driver
driverClass=com.mysql.jdbc.Driver
jdbcUrl=jdbc:mysql://localhost:3306/cashapp?serverTimezone=UTC

initPoolSize=5
maxPoolSize=10


HIbernate配置文件,和之前的配置一样:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect
</property>
<property name="hibernate.show_sql">true</property>
<property name="hibernate.format_sql">true</property>
<property name="hibernate.temp.use_jdbc_metadata_defaults">false</property>
<property name="hibernate.hbm2ddl.auto">update</property>
</session-factory>
</hibernate-configuration>


到此,所有的配置已经完成,里面涉及的bean将在下面说明。

2.3 Model层

定义一个User类,对应数据库中user表,保存用户名、密码以及描述信息:
package com.yefeng.cashapp.model;

public class User {
private String name;
private String password;
private String description;

public User() {
super();
}

public User(String name, String password, String description) {
super();
this.name = name;
this.password = password;
this.description = description;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

public String getDescription() {
return description;
}

public void setDescription(String description) {
this.description = description;
}




商品信息Product类:
package com.yefeng.cashapp.model;

/**
* @author yefengzhichen
* 2016年7月10日
*/
public class Product {
// 名称,数量单位,单价,类别和条形码(伪)
private String barcode;
private String name;
private String unit;
private String category;
private String subCategory;
private Double price;
private boolean isDiscount;

public Product() {
}

public Product(String barcode, String name, String unit, String category, String subCategory, Double price) {
this.barcode = barcode;
this.name = name;
this.unit = unit;
this.category = category;
this.subCategory = subCategory;
this.price = price;
}

public Product(String barcode, String name, String unit, String category, String subCategory, Double price,
boolean isDiscount) {
super();
this.barcode = barcode;
this.name = name;
this.unit = unit;
this.category = category;
this.subCategory = subCategory;
this.price = price;
this.isDiscount = isDiscount;
}

public String getBarcode() {
return barcode;
}

public void setBarcode(String barcode) {
this.barcode = barcode;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getUnit() {
return unit;
}

public void setUnit(String unit) {
this.unit = unit;
}

public String getCategory() {
return category;
}

public void setCategory(String category) {
this.category = category;
}

public String getSubCategory() {
return subCategory;
}

public void setSubCategory(String subCategory) {
this.subCategory = subCategory;
}

public Double getPrice() {
return price;
}

public void setPrice(Double price) {
this.price = price;
}

public boolean isDiscount() {
return isDiscount;
}

public void setDiscount(boolean isDiscount) {
this.isDiscount = isDiscount;
}

@Override
public String toString() {
return "Product [barcode=" + barcode + ", name=" + name + ", unit=" + unit + ", category=" + category
+ ", subCategory=" + subCategory + ", price=" + price + "]";
}

}


利用IDE自动生成相应的Hibernate映射文件:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2016-7-10 20:28:23 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
<class name="com.yefeng.cashapp.model.User" table="USER">
<id name="name" type="java.lang.String">
<column name="NAME" />
<generator class="assigned" />
</id>
<property name="password" type="java.lang.String">
<column name="PASSWORD" />
</property>
<property name="description" type="java.lang.String">
<column name="DESCRIPTION" />
</property>
</class>
</hibernate-mapping>


<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2016-7-12 20:25:34 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
<class name="com.yefeng.cashapp.model.Product" table="PRODUCT">
<id name="barcode" type="java.lang.String">
<column name="BARCODE" />
<generator class="assigned" />
</id>
<property name="name" type="java.lang.String">
<column name="NAME" />
</property>
<property name="unit" type="java.lang.String">
<column name="UNIT" />
</property>
<property name="category" type="java.lang.String">
<column name="CATEGORY" />
</property>
<property name="subCategory" type="java.lang.String">
<column name="SUBCATEGORY" />
</property>
<property name="price" type="java.lang.Double">
<column name="PRICE" />
</property>
<property name="isDiscount" type="boolean" access="field">
<column name="ISDISCOUNT" />
</property>
</class>
</hibernate-mapping>


2.4 DAO层

对以上的两个model类,分别实现对应的DAO层,推荐使用接口编程,因此先定义接口UserDao:
package com.yefeng.cashapp.dao;

import com.yefeng.cashapp.model.User;

public interface UserDao {
public void save(User user);
public boolean isValid(User user);
public void updatePassword(User user);
public User get(String name);
}


ProductDao:
package com.yefeng.cashapp.dao;

import java.util.List;
import com.yefeng.cashapp.model.Product;

public interface ProductDao {
public void save(Product product);
public void update(Product product);
public Product getByBarcode(String barcode);
public boolean contains(Product product);
public List<Product> getAll();
public void setDiscount(String barcode);
}


对应的实现UserDaoImpl:
package com.yefeng.cashapp.dao;

import java.util.List;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.query.Query;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import com.yefeng.cashapp.model.User;

@Repository(value="userDao")
public class UserDaoImpl implements UserDao {
@Autowired
private SessionFactory sessionFactory;

public Session getSession() {
return sessionFactory.getCurrentSession();
}

@Override
public void save(User user) {
getSession().save(user);
}

@Override
public boolean isValid(User user) {
String name = user.getName();
String hql = "select password from User where name = ?";
List<String> result = getSession().createQuery(hql).setParameter(0, name).getResultList();
String realPassword = result.get(0);
if (user.getPassword().equals(realPassword)) {
return true;
}
return false;
}

@Override
public void updatePassword(User user) {
String name = user.getName();
String password = user.getPassword();
//		String hql = "update User u set u.password = ? where u.name = ?";
//		getSession().createQuery(hql).setParameter(0, password).setParameter(1, name);
//		推荐下面的命名参数方式
String hql2 = "update User u set u.password=:password where u.name=:name";
Query query2 = getSession().createQuery(hql2);
query2.setParameter("password", password);
query2.setParameter("name", name);
query2.executeUpdate();
}

@Override
public User get(String name) {
String hql = "select u from User u where name = ?";
List<User> result = getSession().createQuery(hql).setParameter(0, name).getResultList();
return result.get(0);
}
}


对应的ProductDaoImpl:
package com.yefeng.cashapp.dao;

import java.util.List;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.query.Query;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.yefeng.cashapp.model.Product;

@Repository(value = "productDao")
public class ProductDaoImpl implements ProductDao {

@Autowired
private SessionFactory sessionFactory;

public Session getSession() {
return sessionFactory.getCurrentSession();
}

@Override
public void save(Product product) {
if (getSession().contains(product) == false) {
getSession().save(product);
}
}

@Override
public void update(Product product) {
String barcode = product.getBarcode();
String hql = "delete from Product where barcode = ?";
getSession().createQuery(hql).setParameter(0, barcode).executeUpdate();
getSession().save(product);
}

@Override
public Product getByBarcode(String barcode) {
String hql = "select p from Product p where barcode = ?";
List<Product> result = getSession().createQuery(hql).setParameter(0, barcode).getResultList();
return result.get(0);
}

@Override
public boolean contains(Product product) {
String barcode = product.getBarcode();
String hql = "select p from Product p where barcode = ?";
List<Product> result = getSession().createQuery(hql).setParameter(0, barcode).getResultList();
return result.size() > 0;
}

@Override
public List<Product> getAll() {
String hql = "select p from Product p";
List<Product> result = getSession().createQuery(hql).getResultList();
return result;
}

@Override
public void setDiscount(String barcode) {
String hql = "update Product p set p.isDiscount=true where p.barcode=:barcode";
Query query = getSession().createQuery(hql);
query.setParameter("barcode", barcode);
query.executeUpdate();
}

}


2.5 Service层

Service层主要实现商品价格清单功能,需要使用DAO进行处理计算,接口ProcessService只有一个方法:
package com.yefeng.cashapp.service;

public interface ProcessService {
public String calculateAll(String inputString);
}


ProcessServiceImpl:

package com.yefeng.cashapp.service;

import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.yefeng.cashapp.dao.ProductDao;
import com.yefeng.cashapp.model.Product;

/**
* @author yefengzhichen
* 2016年7月15日
*/
@Repository(value = "processService")
public class ProcessServiceImpl implements ProcessService {

@Autowired
private ProductDao productDao;

public String calculateAll(String inputString){
Map<String, Double> map = parseInput(inputString);
return calculatePrice(map);
}
//解析条形码输入,输入中包含数量,进行分割
public Map<String, Double> parseInput(String inputString) {
String[] input = inputString.split(",");
Map<String, Double> buy = new HashMap<>();
for (String str : input) {
String[] content = str.split("-");
double num = 0.0;
if (content.length == 1) {
num = 1.0;
} else if (content.length == 2) {
num = Double.parseDouble(content[1]);
}
String key = content[0];
if (buy.containsKey(key)) {
num += buy.get(key);
buy.put(key, num);
} else {
buy.put(key, num);
}
}
return buy;
}
//计算总的价格、以及实现满100减10的优惠,最后返回一个小票的字符串
public String calculatePrice(Map<String, Double> buy) {
String result;
List<Product> productList = productDao.getAll();
String detail = "";

StringBuffer detailPrice = new StringBuffer("` *<没钱赚商店>购物清单*");
StringBuffer discountPrice = new StringBuffer("");
StringBuffer tatalPrice = new StringBuffer("");
double totalSum = 0.0;
double discountSum = 0.0;
// 小数位数
DecimalFormat df = new DecimalFormat("######0.00");
for (Map.Entry<String, Double> entry : buy.entrySet()) {
String barcode = entry.getKey();
Product product = productDao.getByBarcode(barcode);
double value = entry.getValue();

double price = product.getPrice();
String name = product.getName();
String unit = product.getUnit();
boolean isDiscount = product.isDiscount();
// String sub = product.getSubCategory();
detailPrice.append(" 名称:" + name + ",数量:" + value + "" + unit + ",单价:" + df.format(price) + "(元)");
double subTotal = value * price;
if (isDiscount && subTotal >= 100.0) {
double dis = (int) subTotal / 100 * 10;
totalSum += subTotal;
discountSum += dis;
detailPrice.append(",小计:" + df.format(subTotal) + "(元),优惠:" + df.format(dis) + "(元) ");
if (discountPrice.length() < 1) {
discountPrice.append("单品满100减10块商品:");
}
discountPrice.append(" 商品:" + name + ",原价:" + subTotal + "(元),优惠:" + dis + "(元) ");
} else {
totalSum += subTotal;
detailPrice.append(",小计:" + df.format(subTotal) + "(元) ");
}
}
tatalPrice.append("总计:" + df.format(totalSum - discountSum) + "(元)");
if (discountPrice.length() > 1) {
tatalPrice.append(" 节省:" + df.format(discountSum) + "(元)");
}
result = detailPrice.toString() + "\n" + discountPrice.toString() + "\n" + tatalPrice.toString();
return result;
}

}


2.6 Controller层

首先是首页控制器,直接返回home.jsp。
package com.yefeng.cashapp.web;

import static org.springframework.web.bind.annotation.RequestMethod.*;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping(value="/")
public class HomeController {

@RequestMapping(method=GET)
public String home(){
return "home";
}
}


Usercontroller,定义了用户注册、登录验证相关的处理:
package com.yefeng.cashapp.web;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
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 org.springframework.web.bind.annotation.RequestMethod;

import com.yefeng.cashapp.dao.ProductDao;
import com.yefeng.cashapp.dao.UserDao;
import com.yefeng.cashapp.model.Product;
import com.yefeng.cashapp.model.User;

/**
* @author yefengzhichen
* 2016年7月15日
*/
@Controller
@RequestMapping(value = "/user")
public class UserController {
@Autowired
private UserDao userDao;
@Autowired
private ProductDao productDao;

@RequestMapping(value = "/register", method = RequestMethod.GET)
public String showRegisterForm() {
return "registerForm";
}

@RequestMapping(value = "/register", method = RequestMethod.POST)
public String processRegister(User user) {
userDao.save(user);
return "redirect:/user/" + user.getName();
}

@RequestMapping(value = "/login", method = RequestMethod.GET)
public String showLogin(User user, Model model) {
return "login";
}

@RequestMapping(value = "/login", method = RequestMethod.POST)
public String processLogin(User user, Model model) {
boolean valid = userDao.isValid(user);
if (!valid) {
return "redirect:/user/login";
}
/*List<Product> productList = productDao.getAll();
model.addAttribute(productList);
String discountList = "";
for (int i = 0; i < productList.size(); ++i) {
Product product = productList.get(i);
if (product.isDiscount()) {
discountList += product.getBarcode();
if (i != productList.size()) {
discountList += ", ";
}
}
}
String detail = "The input product barcode is null";
model.addAttribute(discountList);
model.addAttribute(detail);*/
return "redirect:/start";
}

@RequestMapping(value = "/{name}", method = RequestMethod.GET)
public String showBloggerProfile(@PathVariable String name, Model model) {
User user = userDao.get(name);
model.addAttribute(user);
return "profile";
}
}


ProcessController,处理需要里面的增加商品信息、增加打折商品、计算价格等处理:
package com.yefeng.cashapp.web;

import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.yefeng.cashapp.dao.ProductDao;
import com.yefeng.cashapp.dao.UserDao;
import com.yefeng.cashapp.model.Product;
import com.yefeng.cashapp.service.ProcessService;

/**
* @author yefengzhichen
* 2016年7月15日
*/
@Controller
@RequestMapping(value = "/start")
public class ProcessController {

@Autowired
private UserDao userDao;
@Autowired
private ProductDao productDao;
@Autowired
private ProcessService processService;

@RequestMapping(method = RequestMethod.GET)
public String shopApp(Model model) {
addModelAttribute(model);
String detail = "The input product barcode is null";
model.addAttribute("detail", detail);
return "start";
}

// Item0010,apple,kg,fruit,fresh fruit,13.00
@RequestMapping(value = "/inputProduct", method = RequestMethod.POST)
public String addProduct(String inputProduct, Model model) {
String[] proStr = inputProduct.split(";");
for (String pro : proStr) {
String[] list = pro.split(",");
String barcode = list[0];
String name = list[1];
String unit = list[2];
String category = list[3];
String subCategory = list[4];
Double price = Double.parseDouble(list[5]);
Product product = new Product(barcode, name, unit, category, subCategory, price);
productDao.save(product);
}
addModelAttribute(model);
return "start";
}

@RequestMapping(value = "/inputDiscount", method = RequestMethod.POST)
public String addDiscount(String inputDiscount, Model model) {
String[] barcodes = inputDiscount.split(",");
for (String barcode : barcodes) {
productDao.setDiscount(barcode);
}
addModelAttribute(model);
return "start";
}

@RequestMapping(value = "/inputBarcode", method = RequestMethod.POST)
public String inputItem(String inputBarcode, Model model) {
String detail = processService.calculateAll(inputBarcode);
model.addAttribute("datail", detail);
addModelAttribute(model);
return "start";
}

public void addModelAttribute(Model model) {
List<Product> productList = productDao.getAll();
model.addAttribute("productList", productList);
String discountList = "";
for (int i = 0; i < productList.size(); ++i) {
Product product = productList.get(i);
if (product.isDiscount()) {
if (discountList.length() == 0) {
discountList += product.getBarcode();
} else {
discountList += (", " + product.getBarcode());
}
}
}
model.addAttribute("discountList", discountList);
}

}


2.7 View层

在介绍之前,先浏览一下目录结构如下:



home.jsp,简单的定义两个链接,分别是注册和登录:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ page session="false"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Blog for people who follows your heart</title>
</head>
<body>
<h1 align="center">Welcome to cashapp</h1>
<div align="center">
<a style="font-size:16px;" href="<c:url value="/user/login" />">Login</a>
<a style="font-size:16px;" href="<c:url value="/user/register" />">Register</a>
</div>
</body>
</html>


RegisterForm,定义注册界面:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ page session="false"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>cashapp</title>
</head>
<body>
<h1 align="center">Register</h1>
<div align="center">
<form action="/cashapp/user/register" method="post">
<!-- real :action="/cashapp/user/register" -->
UserName: <input type="text" name="name" /> <br/>
PassWord: <input type="password" name="password" /> <br/>
Description: <input type="text" name="description" /> <br/>
<input type="submit" value="Register">
</form>
</div>>
</body>
</html>


profile.jsp,显示注册成功的界面,显示名称和介绍:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ page session="false"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Blog for people who follows your heart</title>
</head>
<body>
<h4 align="center">Welcome to cashapp</h4>
<div align="center">
Your name: <c:out value="${user.name}"></c:out> <br>
Your description: <c:out value="${user.description}"></c:out>
</div>
</body>
</html>


start.jsp,收银机系统的主界面,大多数功能处理在此处:

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ page session="false"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>cashapp</title>
</head>
<body>
<h1 align="center">A brief web cashapp</h1>

<p style="FONT-SIZE: 16px" align="center">
Product information list: <br>
</p>
<!-- 商品信息表格输出 -->
<table align="center" border="2">
<tr>
<td width="100">barcode</td>
<td width="100">name</td>
<td width="100">unit</td>
<td width="100">category</td>
<td width="140">subCategory</td>
<td width="100">price</td>
</tr>
<c:forEach items="${productList}" var="product">
<tr>
<td width="100"><c:out value="${product.barcode}" /></td>
<td width="100"><c:out value="${product.name}" /></td>
<td width="100"><c:out value="${product.unit}" /></td>
<td width="100"><c:out value="${product.category}" /></td>
<td width="140"><c:out value="${product.subCategory}" /></td>
<td width="100"><c:out value="${product.price}" /></td>
</tr>
</c:forEach>
</table>
<!-- 输入购买的商品条形码 -->
<div align="center">
<br> Input product barcode list(Example:Item0002,Item0010-10): <br>
<form action="/cashapp/start/inputBarcode" method="post" id="inputBarcode">
<textarea name="inputBarcode" cols="100" rows="1"></textarea> <br>
<input type="submit" value="InputBarcode">
</form>
</div>
<!-- 输出商品价格详细清单 -->
<div align="center">
<br> Output product price details: <br>
<textarea rows="6" cols="100"><c:out value="${datail}"></c:out> </textarea>
</div>
<!-- 输入要增加商品信息/cashapp/start/inputProduct  Item0010,apple,kg,fruit,fresh fruit,13.00-->
<div align="center">
<br> Input product information list(Example:Item0010,apple,kg,fruit,fresh fruit,13.00): <br>
<form action="/cashapp/start/inputProduct" method="post" id="inputProduct">
<textarea name="inputProduct" cols="100" rows="2"></textarea> <br>
<input type="submit" value="inputProduct">
</form>
</div>
<!-- 已经保存的打折商品条形码列表 -->
<div align="center">
<br> Discount information list: <br>
<textarea rows="2" cols="100"><c:out
value="${discountList}"></c:out> </textarea>
</div>
<!-- 输入要增加的打折商品条形码-->
<div align="center">
<br> Input discount product list(Example:Item0002,Item0010): <br>
<form action="/cashapp/start/inputDiscount" method="post" id="inputDiscount">
<textarea name="inputDiscount" cols="100" rows="1"></textarea> <br>
<input type="submit" value="InputDiscount">
</form>
</div>

</body>
</html>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: