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

前面参加一个公司的活动,做了一份收银机系统的作业,当时时间紧,花费一天时间用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>


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值