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

来源:互联网 发布:苹果还是外星人 程序员 编辑:程序博客网 时间:2024/04/29 16:48

前面参加一个公司的活动,做了一份收银机系统的作业,当时时间紧,花费一天时间用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.xsdhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsdhttp://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.xsdhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsdhttp://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=rootpassword=#com.mysql.cj.jdbc.Driver driverClass=com.mysql.jdbc.DriverjdbcUrl=jdbc:mysql://localhost:3306/cashapp?serverTimezone=UTC  initPoolSize=5maxPoolSize=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;}@Overridepublic 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 {@Autowiredprivate SessionFactory sessionFactory;public Session getSession() {return sessionFactory.getCurrentSession();}@Overridepublic void save(User user) {getSession().save(user);}@Overridepublic 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;}@Overridepublic 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();}@Overridepublic 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 {@Autowiredprivate SessionFactory sessionFactory;public Session getSession() {return sessionFactory.getCurrentSession();}@Overridepublic void save(Product product) {if (getSession().contains(product) == false) {getSession().save(product);}}@Overridepublic 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);}@Overridepublic 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);}@Overridepublic 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;}@Overridepublic List<Product> getAll() {String hql = "select p from Product p";List<Product> result = getSession().createQuery(hql).getResultList();return result;}@Overridepublic 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 {@Autowiredprivate 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 {@Autowiredprivate UserDao userDao;@Autowiredprivate 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 {@Autowiredprivate UserDao userDao;@Autowiredprivate ProductDao productDao;@Autowiredprivate 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:outvalue="${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>


0 0