mapengpeng1999@163.com Spring和SpringMVC整合及买书程序

Spring与SpringMVC整合

目前Spring和SPringMVC已经很好的在一起工作了,需要整合吗?需要,框架和流水线生产一样,需要分工明细:
- 业务层和数据访问层交给SpringIOC容器
- 控制层交给SpringMVC的IOC容器
也就是说整合之后,会存在两个IOC容器。
SpringIOC和SpringMVCIOC容器会调用默认无参构造器,默认使用全类名反射完成注解(dao,service,controller)的实例化
Spring在整合SpringMVC的时候需要有两个配置文件,两个IOC容器,但是要注意两个配置文件需要扫描的注解不同,
一个只负责扫描Spring,一个只负责扫描SpringMVC,要区别开来,不然会导致扫描两次的。
新建个动态WEB工程,new个conf类资源文件夹,用来存放Spring的配置文件(命名为applicationContext.xml),
在WEB-INF目录下new个SpringMVC的配置文件(和Spring的配置文件是一样的,命名为SpringMVC-servlet.xml)
这两个IOC容器要在服务器启动时加载,所以在web.xml文件中配置。
先配SpringIOC的,ContextConfigLocation
再配SpringMVCIOC的,DispatcherServlet
再加个HiddenHttpMethodFilter过滤器配置,将post请求转换为put或delete请求,REST FUL风格

web.xml文件中配置:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  <display-name>SpringMVC03</display-name><!-- SpringMVC03项目名 -->
  <welcome-file-list><!-- 配置欢迎界面 -->
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
  
 <!-- Spring IOC容器在Tomcat启动时就会被加载 -->
	<context-param><!-- 上下文参数 -->
		<param-name>contextConfigLocation</param-name>
		<!-- contextConfigLocation上下文配置文件的路径 -->
		<param-value>classpath:applicationContext.xml</param-value>
		<!-- 在类路径下classpath:applicationContext.xml -->
	</context-param>
	<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
	
<!-- SpringMVC IOC容器在Tomcat启动时就会加载 -->
	<servlet>
		<servlet-name>SpringMVC</servlet-name>
		<!-- 使用默认配置,在WEB-INF目录下SpringMVC-servlet.xml -->
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
		<!-- 在服务器启动时加载 -->
	</servlet>
	<servlet-mapping>
		<servlet-name>SpringMVC</servlet-name>
		<url-pattern>/</url-pattern>
		<!-- 处理所有请求 -->
	</servlet-mapping>
	
	<!-- HiddenHttpMethodFilter过滤器将post请求转换为put或delete请求,REST FUL风格 -->
	<filter>
	<filter-name>HiddenHttpMethodFilter</filter-name>
	<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>HiddenHttpMethodFilter</filter-name>
		<url-pattern>/*</url-pattern>
		<!-- 过滤所有请求 -->
	</filter-mapping>
</web-app>


SpringMVC的配置文件(要注意命名约定规范)
<?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"
	xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.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.0.xsd">

	<!-- 配置自动扫描的包  SpringMVC只掃描 Controller註解和ControllerAdvice註解-->
	<context:component-scan base-package="com.wanbangee" use-default-filters="false">
		<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
		<context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/>
	</context:component-scan>
	
	<!-- 配置视图解析器 -->
	<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix" value="/jsp/"></property>
		<property name="suffix" value=".jsp"></property>
	</bean>
	
<!-- 处理静态资源 : SpringMVC会认为所有的请求都是静态资源,所以会导致正常经过请求处理器的请求出现404-->
	<mvc:default-servlet-handler/>
	
	<!-- 万能的配置 : 表示请求先找静态资源,如果没有静态资源则找正常的请求处理器 -->
	<mvc:annotation-driven></mvc:annotation-driven>
</beans>



Spring的配置文件
<?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:tx="http://www.springframework.org/schema/tx"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="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.0.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">

<!-- 配置自动扫描的包 -->
	<context:component-scan base-package="com.wanbangee">
		<!-- Spring不扫描Controller 和  ControllerAdvice注解 -->
		<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
		<context:exclude-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/>
	</context:component-scan>

	<!-- 引入外部属性文件 -->
	<context:property-placeholder location="classpath:db.properties"/>
	<!-- 配置连接池 -->
	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
		<property name="driverClass" value="${mysql.driver}"></property>
		<property name="jdbcUrl" value="${mysql.url}"></property>
		<property name="user" value="${mysql.user}"></property>
		<property name="password" value="${mysql.password}"></property>
		<property name="maxPoolSize" value="${mysql.maxSize}"></property>
		<property name="initialPoolSize" value="${mysql.initSize}"></property>
	</bean>
	
	<!-- JdbcTemplate -->
	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	
	<!-- 配置事务管理器 -->
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	<!-- 
		启用事务注解 
			- 默认情况下,事务注解会使用IOC容器中名称为transactionManager的bean,如果不存在,则保存
			- 我们也可以配置事务注解使用IOC容器中bean的名称
				- transaction-manager : 配置具体的事务管理器的bean名称
			- 约定大于配置大于编码
	-->
	<tx:annotation-driven/>
</beans>

整合Spring和SpringMVC的时候出现的问题

控制层,业务层,数据访问层即被SpringIOC容器管理,又被SpringMVCIOC容器管理,
没有达到明细分工的要求。解决方案:配置只扫描和不扫描。
<!-- 配置自動掃描的包 Spring不掃描 Controller註解和ControllerAdvice异常处理器註解-->
	<context:component-scan base-package="com.wanbangee">
		<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
		<context:exclude-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/>
	</context:component-scan>
<!-- 配置自動掃描的包  SpringMVC只掃描 Controller註解和ControllerAdvice註解-->
	<context:component-scan base-package="com.wanbangee" use-default-filters="false">
		<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
		<context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/>
	</context:component-scan>

整合Spring和SpringMVC的解决方案

现在分开两个IOC容器之后,会考虑到,Controller中是否能够自动装配Service,
因为Controller是在SpringMVC的IOC容器中,而Service在SpringIOC容器中,
在实际情况中SpringIOC容器和SpringMVCIOC容器是一个包含关系,如下图:

在这里插入图片描述

也就是说,SpringMVC可以获取SpringIOC容器中的bean,反之,Spring不能获取SpringMVCIOC容器中的bean。
就是在业务实现层不能自动装配控制层对象,只能在控制层自动装配业务实现层对象。

SpringMVC对比Struts2

1.入口不同,SpringMVC用的是Servlet,Struts2用的是Filter(过滤器)
2.速度不同,SpringMVC会比Struts2执行速度更快,效率更高。Struts2好多拦截器,Struts2每完成一个功能就是一个拦截器。
3.设计理念不同,Struts2是基于类的设计(一个类对应一个映射地址),
SpringMVC是基于方法的(一个方法对应一个映射地址)
4.SpringMVC更加简洁,比如请求参数接收的时候
5.SpringMVC支持JSR303验证,而且处理Ajax请求更加方便
6.在传统的JavaEE开发中,Struts2的优势在于,提供了强大的标签库,能够将值栈中(域对象中)的信息快速输出到页面,
当然这些标签库只能在JSP使用。JSP是后端语言,传统JAVAEE使用的技术,JS是前端语言。

买书程序

在这里插入图片描述

买书程序,开发全程使用Ajax
以后开发前端全用HTML,HTML不能传递session域,不能将用户信息放到session域那样是没有意义的,
把用户信息放到redis缓存中,浏览器用cooki存个hard头信息,头信息每次向后端请求时把头信息传递到后端去。

先设计原型界面,要实现哪些接口,界面要调用后端,就写一个接口,从上到下一个个接口实现。
CREATE DATABASE ssbuybooks;
CREATE TABLE account(
	acc_id INT PRIMARY KEY AUTO_INCREMENT,
	acc_name VARCHAR(20),
	acc_pass VARCHAR(20),
	acc_balance DOUBLE,
	acc_pic VARCHAR(100)
);

CREATE TABLE book_info(
	book_no INT PRIMARY KEY AUTO_INCREMENT,
	book_name VARCHAR(20),
	book_price DOUBLE,
	stock_id INT
);

CREATE TABLE book_stock(
	stock_id INT PRIMARY KEY AUTO_INCREMENT,
	book_no INT,
	stock_num INT
);

CREATE TABLE book_car(
	car_id INT PRIMARY KEY AUTO_INCREMENT,
	book_no INT,
	book_name VARCHAR(20),
	book_price DOUBLE,
	book_num INT,
	total_price DOUBLE,
	acc_id INT
);  //数据冗余了
db.properties(数据库的外部属性文件)
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/ssbuybooks
user=root
password=3306
maxSize=10
initSize=5

实体类

package com.wanbangee.entrties;

public class Account {

	private Integer accId;
	private String accName;
	private String accPass;
	private Double accBalance;
	private String accPic;
	public Integer getAccId() {
		return accId;
	}
	public void setAccId(Integer accId) {
		this.accId = accId;
	}
	public String getAccName() {
		return accName;
	}
	public void setAccName(String accName) {
		this.accName = accName;
	}
	public String getAccPass() {
		return accPass;
	}
	public void setAccPass(String accPass) {
		this.accPass = accPass;
	}
	public Double getAccBalance() {
		return accBalance;
	}
	public void setAccBalance(Double accBalance) {
		this.accBalance = accBalance;
	}
	public String getAccPic() {
		return accPic;
	}
	public void setAccPic(String accPic) {
		this.accPic = accPic;
	}

}
package com.wanbangee.entrties;

public class BookStock {

	private Integer stockId;
	private Integer bookNo;
	private Integer stockNum;
	public Integer getStockId() {
		return stockId;
	}
	public void setStockId(Integer stockId) {
		this.stockId = stockId;
	}
	public Integer getBookNo() {
		return bookNo;
	}
	public void setBookNo(Integer bookNo) {
		this.bookNo = bookNo;
	}
	public Integer getStockNum() {
		return stockNum;
	}
	public void setStockNum(Integer stockNum) {
		this.stockNum = stockNum;
	}
	
}
package com.wanbangee.entrties;

public class BookInfo {

	private Integer bookNo;
	private String bookName;
	private Double bookPrice;
	private Integer stockId;
	private BookStock bookStock;//引用库存表
	public Integer getBookNo() {
		return bookNo;
	}
	public void setBookNo(Integer bookNo) {
		this.bookNo = bookNo;
	}
	public String getBookName() {
		return bookName;
	}
	public void setBookName(String bookName) {
		this.bookName = bookName;
	}
	public Double getBookPrice() {
		return bookPrice;
	}
	public void setBookPrice(Double bookPrice) {
		this.bookPrice = bookPrice;
	}
	public Integer getStockId() {
		return stockId;
	}
	public void setStockId(Integer stockId) {
		this.stockId = stockId;
	}
	public BookStock getBookStock() {
		return bookStock;
	}
	public void setBookStock(BookStock bookStock) {
		this.bookStock = bookStock;
	}
	
}
package com.wanbangee.entrties;

public class BookCar {

	private Integer carId;
	private Integer bookNo;
	private String bookName;
	private Double bookPrice;
	private Integer bookNum;
	private Double totalPrice;
	private Integer accId;
	public Integer getCarId() {
		return carId;
	}
	public void setCarId(Integer carId) {
		this.carId = carId;
	}
	public Integer getBookNo() {
		return bookNo;
	}
	public void setBookNo(Integer bookNo) {
		this.bookNo = bookNo;
	}
	public String getBookName() {
		return bookName;
	}
	public void setBookName(String bookName) {
		this.bookName = bookName;
	}
	public Double getBookPrice() {
		return bookPrice;
	}
	public void setBookPrice(Double bookPrice) {
		this.bookPrice = bookPrice;
	}
	public Integer getBookNum() {
		return bookNum;
	}
	public void setBookNum(Integer bookNum) {
		this.bookNum = bookNum;
	}
	public Double getTotalPrice() {
		return totalPrice;
	}
	public void setTotalPrice(Double totalPrice) {
		this.totalPrice = totalPrice;
	}
	public Integer getAccId() {
		return accId;
	}
	public void setAccId(Integer accId) {
		this.accId = accId;
	}
	
}

DAO

package com.wanbangee.dao;

import com.wanbangee.entrties.Account;

public interface AccountDao {
	/**
	 * 登录,根据用户名和密码查询用户信息
	 * @param accName
	 * @param accPass
	 * @return
	 */
	public Account selectAccountByAccNameAndAccPass(String accName,String accPass);
	/**
	 * 根据用户名及密码查询数据笔数,来判断是否登录成功,查询到一笔数据表示登入成功
	 * 这是JdbcTemplate的一个缺陷,查询成功一定要返回查询的数据笔数
	 * @param accName
	 * @param accPass
	 * @return
	 */
	public int selectCountByAccNameAndAccPass(String accName,String accPass);
	/**
	 * 查询账户余额,根据账户ID
	 * @param accId
	 * @return
	 */
	public double selectAccBalanceByAccId(Integer accId);
	/**
	 * 修改账户余额,根据账户ID
	 * 买书减钱,买一本书减少一本书的钱,买多本书减少多本书的钱
	 * 充值加钱,和买书减少账户余额一样,只是传递的money参数不同,充值是加钱
	 * @param accId
	 * @param money
	 * @return
	 */
	public int updateAccBalanceByAccId(Integer accId,Double money);
}
package com.wanbangee.dao;

import com.wanbangee.entrties.BookStock;

public interface BookStockDao {
	/**
	 * 查询图书库存信息,根据库存ID
	 * @param stockId
	 * @return
	 */
	public BookStock selectBookStockByStockId(Integer stockId);
	/**
	 * 查询图书库存,根据图书ID
	 * @param bookNo
	 * @return
	 */
	public int selectStockNumByBookNo(Integer bookNo);
	/**
	 * 减少图书库存,根据图书ID,买一本书库存减一,也可以根据图书号购买多本书
	 * @param bookNo
	 * @return
	 */
	public void updateStockNumByBookNo(Integer bookNo,Integer bookNum);
}
package com.wanbangee.dao;

import java.util.List;

import com.wanbangee.entrties.BookInfo;

public interface BookInfoDao {
	/**
	 * 查询图书单价,根据图书号
	 * @param bookNo
	 * @return
	 */
	public double selectBookPriceByBookNo(Integer bookNo);
	/**
	 * 查询所有图书信息,并分页显示
	 * @param pageSize
	 * @param pageCurrent
	 * @return
	 */
	public List<BookInfo> selectBookInfo(Integer pageSize,Integer pageCurrent);
	/**
	 * 查询数据笔数,便于后面做分页操作
	 * @return
	 */
	public int selectCount();
}
package com.wanbangee.dao;

import java.util.List;

import com.wanbangee.entrties.BookCar;

public interface BookCarDao {
	/**
	 * 加入购物车,谁的购物车,买了哪本书,购物车数量默认为1
	 * 加入购物车,就是往这个表中插入一笔数据,先查询到图书一些信息再插入到这个表中
	 * 加入购物车-购物车中不存在该本图书
	 * @param accId
	 * @param bookNo
	 * @return
	 */
	public int insertBookCar(Integer accId,Integer bookNo);
	/**
	 * 	同一个图书多次加入到购物车时修改图书的数量 和 总价
	 * 加入购物车-已经存在该本图书
	 * @param accId
	 * @param bookNo
	 * @return
	 */
	public int updateBookCarByAccIdAndBookNo(Integer accId,Integer bookNo);
	/**
	 * 	查询当前登录人购物车中是否有对应编号的图书
	 * 判断该用户购物车中是否存在该图书
	 * @param accId
	 * @param bookNo
	 * @return
	 */
	public int selectCountByAccIdAndBookNo(Integer accId,Integer bookNo);
	
	/**
	 * 	根据用户ID查询购物车数据信息
	 * @param accId
	 * @return
	 */
	public List<BookCar> selectBookCarByAccId(Integer accId);
	
	/**
	 * 	 修改购物车中图书数量和总价
	 * @param carId
	 * @param bookNum
	 * @return
	 */
	public int updateBookCarByBookNumAndTotoalPrice(Integer carId,Integer bookNum);
	
	/**
	 * 	删除购物车
	 * @param carId
	 * @return
	 */
	public int deleteBookCar(Integer carId);
}

DAOIMP

package com.wanbangee.dao.imp;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;

import com.wanbangee.dao.AccountDao;
import com.wanbangee.entrties.Account;
@Repository
public class AccountDaoImp implements AccountDao {
	@Autowired
	private JdbcTemplate jdbcTemplate;
//根据用户名和密码查询用户信息
	@Override
	public Account selectAccountByAccNameAndAccPass(String accName, String accPass) {
		String sql = "select acc_id,acc_name,acc_balance,acc_pic from account where acc_name = ? and acc_pass = ?";
		RowMapper<Account> rowMapper = new BeanPropertyRowMapper<>(Account.class);
		return this.jdbcTemplate.queryForObject(sql, rowMapper,accName,accPass);
	}
//根据用户名及密码查询数据笔数
	@Override
	public int selectCountByAccNameAndAccPass(String accName, String accPass) {
		String sql = "select count(*) from account where acc_name = ? and acc_pass = ?";
		return this.jdbcTemplate.queryForObject(sql, Integer.class,accName,accPass);
	}
//查询账户余额
	@Override
	public double selectAccBalanceByAccId(Integer accId) {
		String sql = "select acc_balance from account where acc_id = ?";
		return this.jdbcTemplate.queryForObject(sql, Double.class,accId);
	}
//修改账户余额,买书减钱,充值加钱
	@Override
	public int updateAccBalanceByAccId(Integer accId, Double money) {
		String sql = "update account set acc_balance = acc_balance + ? where acc_id = ?";
		 return this.jdbcTemplate.update(sql,money,accId);
	}
//JdbcTemplate的update方法返回的是int类型,表示影响的数据笔数,增删改都会影响数据,如果增删改操作影响的数据笔数是0笔,说明操作失败了
}
package com.wanbangee.dao.imp;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;

import com.wanbangee.dao.BookStockDao;
import com.wanbangee.entrties.Account;
import com.wanbangee.entrties.BookStock;
@Repository
public class BookStockDaoImp implements BookStockDao {
	@Autowired
	private JdbcTemplate jdbcTemplate;
//查询图书库存信息,根据库存ID
	@Override
	public BookStock selectBookStockByStockId(Integer stockId) {
		String sql = "select stock_id,stock_num,book_no from book_stock where stock_id = ?";
		RowMapper<BookStock> rowMapper = new BeanPropertyRowMapper<>(BookStock.class);
		return this.jdbcTemplate.queryForObject(sql, rowMapper,stockId);
	}
//查询图书库存,根据图书ID
	@Override
	public int selectStockNumByBookNo(Integer bookNo) {
		String sql = "select stock_num from book_stock where book_no = ?";
		return this.jdbcTemplate.queryForObject(sql, Integer.class,bookNo);
	}
//减少图书库存,根据图书ID	
	@Override
	public void updateStockNumByBookNo(Integer bookNo,Integer bookNum) {
		String sql = "update book_stock set stock_num = stock_num - ? where book_no = ?";
		this.jdbcTemplate.update(sql,bookNum,bookNo);
	}

}
package com.wanbangee.dao.imp;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;

import com.wanbangee.dao.BookInfoDao;
import com.wanbangee.entrties.BookInfo;
import com.wanbangee.entrties.BookStock;
@Repository
public class BookInfoDaoImp implements BookInfoDao {
	@Autowired
	private JdbcTemplate jdbcTemplate;
//查询图书单价,根据图书号
	@Override
	public double selectBookPriceByBookNo(Integer bookNo) {
		String sql = "select book_price from book_info where book_no = ?";
		return this.jdbcTemplate.queryForObject(sql, Double.class,bookNo);
	}
//查询所有图书信息,并分页显示
	@Override
	public List<BookInfo> selectBookInfo(Integer pageSize, Integer pageCurrent) {
		String sql = "select book_no,book_price,book_name,stock_id from book_info limit ?,?";
		RowMapper<BookInfo> rowMapper = new BeanPropertyRowMapper<>(BookInfo.class);
		return this.jdbcTemplate.query(sql, rowMapper,(pageCurrent-1)*pageSize,pageSize);
		//图书列表查询要显示图书库存,
		//这里只有库存ID,stock_id,没有库存数据,还好图书表实体类引用了库存表,在库存表做个查询库存信息
	}
//查询数据笔数,便于后面做分页操作
	@Override
	public int selectCount() {
		String sql = "select count(*) from book_info";
		return this.jdbcTemplate.queryForObject(sql, Integer.class);
	}

}
package com.wanbangee.dao.imp;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;

import com.wanbangee.dao.BookCarDao;
import com.wanbangee.entrties.BookCar;
@Repository
public class BookCarDaoImp implements BookCarDao {
	@Autowired
	private JdbcTemplate jdbcTemplate;
//加入购物车-购物车中不存在该本图书
	@Override
	public int insertBookCar(Integer accId, Integer bookNo) {
		//book_num加入购物车的图书数量默认为1,total_price总价,因为只购买一本书所以总价total_price为图书单价book_price
		String sql = "insert into book_car(book_no,book_name,book_price,book_num,total_price,acc_id) select book_no,book_name,book_price,1,book_price,?"
				+ " from book_info where book_no = ?";
		//将查询的结果作为插入的数据
		return this.jdbcTemplate.update(sql,accId,bookNo);
	}
//判断该用户购物车中是否存在该图书
	@Override   //判断这本书有没有在这个人的购物车中
	public int selectCountByAccIdAndBookNo(Integer accId, Integer bookNo) {
		String sql = "select count(car_id) from book_car where acc_id = ? and book_no = ?";
		return this.jdbcTemplate.queryForObject(sql, Integer.class,accId,bookNo);
	}
//加入购物车-已经存在该本图书
	@Override  //一次加购一本书,总价就加上这本书的单价
	public int updateBookCarByAccIdAndBookNo(Integer accId, Integer bookNo) {
		String sql = "update  book_car set book_num = book_num + 1 ,total_price = total_price+book_price where acc_id = ? and book_no = ?";
		return this.jdbcTemplate.update(sql,accId,bookNo);
	}
//根据用户ID查询购物车数据信息
	@Override
	public List<BookCar> selectBookCarByAccId(Integer accId) {
		String sql = "select car_id,book_no,book_name,book_price,book_num,total_price from book_car where acc_id = ?";
		RowMapper<BookCar> rowMapper = new BeanPropertyRowMapper<>(BookCar.class);
		return this.jdbcTemplate.query(sql, rowMapper,accId);
	}
// 修改购物车中图书数量和总价
	@Override  //total_price = ?*book_price
	public int updateBookCarByBookNumAndTotoalPrice(Integer carId, Integer bookNum) {
		String sql = "update book_car set book_num = ? , total_price = "+bookNum+"*book_price where car_id = ?";
		return this.jdbcTemplate.update(sql,bookNum,carId); //(sql,bookNum,bookNum,carId); 
	}
//删除购物车
	@Override
	public int deleteBookCar(Integer carId) {
		String sql = "delete from book_car where car_id = ?";
		return this.jdbcTemplate.update(sql,carId);
	}

}

service

package com.wanbangee.service;

import com.wanbangee.entrties.Account;

public interface LoginService {
	/**
	 * 登入业务
	 * @param accName
	 * @param accPass
	 * @return
	 */
	public Account login(String accName,String accPass);
}
package com.wanbangee.service;

import java.util.List;

import com.wanbangee.entrties.BookCar;
import com.wanbangee.entrties.BookInfo;

public interface BuyBookService {
	/**
	 * 买书业务
	 * @param accId
	 * @param bookNo
	 */
	public void buyBook(Integer accId,Integer bookNo);
	/**
	 * 查询账户余额
	 * @param accId
	 * @return
	 */
	public double selectAccBalanceByAccId(Integer accId);
	/**
	 * 修改账户余额
	 * @param accId
	 * @param money
	 * @return
	 */
	public int updateAccBalanceByAccId(Integer accId,Double money);
	/**
	 * 图书信息查询
	 * @param pageSize
	 * @param pageCurrent
	 * @return
	 */
	public List<BookInfo> selectBookInfo(Integer pageSize,Integer pageCurrent);
	
	/**
	 * 	查询数据总笔数,便于分页查询操作
	 * @return
	 */
	public int selectCount();
	
	/**
	 * 增加购物车
	 * @param accId
	 * @param bookNo
	 * @return
	 */
	public int addCar(Integer accId,Integer bookNo);
	
	/**
	 * 	获得购物车信息
	 * @param accId
	 * @return
	 */
	public List<BookCar> getBookCar(Integer accId);
	
	/**
	 * 	修改购物车数量
	 * @param carId
	 * @param bookNum
	 * @return
	 */
	public int updateBookCar(Integer carId,Integer bookNum);
	
	/**
	 * 	删除购物车
	 * @param carId
	 * @return
	 */
	public int deleteBookCar(Integer carId);
	
	/**
	 * 	提交购物车
	 * @param accId
	 */
	public void submitBookCar(Integer accId);
	
}

serviceIMP

package com.wanbangee.service.imp;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.wanbangee.dao.AccountDao;
import com.wanbangee.entrties.Account;
import com.wanbangee.service.LoginService;
@Service
public class LoginServiceImp implements LoginService {
	@Autowired
	private AccountDao accountDao;

	@Override
	public Account login(String accName, String accPass) {
		//1.查询数据笔数
		int count = this.accountDao.selectCountByAccNameAndAccPass(accName, accPass);
		if(count == 1) {
			return this.accountDao.selectAccountByAccNameAndAccPass(accName, accPass);
		}
		return null;
	}
}
package com.wanbangee.service.imp;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.wanbangee.dao.AccountDao;
import com.wanbangee.dao.BookCarDao;
import com.wanbangee.dao.BookInfoDao;
import com.wanbangee.dao.BookStockDao;
import com.wanbangee.entrties.BookCar;
import com.wanbangee.entrties.BookInfo;
import com.wanbangee.service.BuyBookService;
@Service
public class BuyBookServiceImp implements BuyBookService {
	@Autowired
	private AccountDao accountDao;
	@Autowired
	private BookInfoDao bookInfoDao;
	@Autowired
	private BookStockDao bookStockDao;
	@Autowired
	private BookCarDao bookCarDao;
//买书业务
	@Transactional //加上事务管理
	@Override
	public void buyBook(Integer accId, Integer bookNo) {
		//1 查询图书单价
		double money = this.bookInfoDao.selectBookPriceByBookNo(bookNo);
		//2 减少账户余额,要用到图书单价
		this.accountDao.updateAccBalanceByAccId(accId, money*-1);
		//2.1 查询账户余额,买书是减少,money*-1
		if(this.accountDao.selectAccBalanceByAccId(accId)<0) {
			throw new RuntimeException("账户余额不足");
		}
		//3 减少图书库存,买一本书减少图书库存1
		this.bookStockDao.updateStockNumByBookNo(bookNo,1);
		//3.1 查询图书库存
		if(this.bookStockDao.selectStockNumByBookNo(bookNo)<0) {
			throw new RuntimeException("图书库存不足");
		}
	}
//查询账户余额业务
	@Override
	public double selectAccBalanceByAccId(Integer accId) {
		return this.accountDao.selectAccBalanceByAccId(accId);
	}
//充值业务,修改账户余额
	@Override
	public int updateAccBalanceByAccId(Integer accId, Double money) {
		 return this.accountDao.updateAccBalanceByAccId(accId, money);
	}
//图书信息查询业务
	@Override
	public List<BookInfo> selectBookInfo(Integer pageSize, Integer pageCurrent) {
		List<BookInfo> bookInfos = this.bookInfoDao.selectBookInfo(pageSize, pageCurrent);
		for (BookInfo bookInfo : bookInfos) {
			if(bookInfo.getStockId() != null) {//查询库存封装到集合中,stock_id不为空才封装
				bookInfo.setBookStock(this.bookStockDao.selectBookStockByStockId(bookInfo.getStockId()));
			}
		}
		return bookInfos;
	}
//查询数据总笔数,便于分页查询操作
	@Override
	public int selectCount() {
		return this.bookInfoDao.selectCount();
	}

	
	//只用改业务层,加入购物车会来到这个方法addCar,业务处理都是在service完成的,
	//控制层调用数据访问层,中间加个业务层来处理复杂业务
	//加入购物车,多次测试看看效果,账户ID相同,图书号不同
	@Override  
	public int addCar(Integer accId, Integer bookNo) {
		//1 判断当前人购物车中是否有当前的图书
		int count = this.bookCarDao.selectCountByAccIdAndBookNo(accId, bookNo);
		//2 如果有 则修改数据
		if(count > 0) {
			return this.bookCarDao.updateBookCarByAccIdAndBookNo(accId, bookNo);
		}
		//3 如果没有则新增数据
		return this.bookCarDao.insertBookCar(accId, bookNo);
	}
//获得购物车信息
	@Override
	public List<BookCar> getBookCar(Integer accId) {
		return this.bookCarDao.selectBookCarByAccId(accId);
	}
//修改购物车数量
	@Override
	public int updateBookCar(Integer carId, Integer bookNum) {
		return this.bookCarDao.updateBookCarByBookNumAndTotoalPrice(carId, bookNum);
	}
//删除购物车
	@Override  //这个业务比较简单,直接返回数据访问层
	public int deleteBookCar(Integer carId) {
		return this.bookCarDao.deleteBookCar(carId);
	}
//提交购物车业务
	@Transactional //加上事务管理
	@Override
	public void submitBookCar(Integer accId) {
		//1 查询accId 的所有购物车数据
		List<BookCar> bookCars = this.bookCarDao.selectBookCarByAccId(accId);
		for (BookCar bookCar : bookCars) {
		//2 减少图书库存
		this.bookStockDao.updateStockNumByBookNo(bookCar.getBookNo(), bookCar.getBookNum());
		//2.1 查询图书库存
		if(this.bookStockDao.selectStockNumByBookNo(bookCar.getBookNo()) < 0) {
			throw new RuntimeException("图书库存不足");
		}
		//3 减少账户余额
		this.accountDao.updateAccBalanceByAccId(accId, bookCar.getTotalPrice()*-1);
		//3.1 查询账户余额
		if(this.accountDao.selectAccBalanceByAccId(accId) < 0) {
				throw new RuntimeException("账户余额不足");
		}
		//4 清空购物车
		this.bookCarDao.deleteBookCar(bookCar.getCarId());
		}
	}
	
}

controller

package com.wanbangee.controller;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.wanbangee.entrties.Account;
import com.wanbangee.service.LoginService;

@Controller
public class LoginController {
	@Autowired
	private LoginService loginService;
	/**
	 * 	根据用户名和密码查询账户信息,如果存在账户信息,则登录成功,返回ture,将账户信息加入到session域中,否则返回false
	 * @param accName
	 * @param accPass
	 * @return
	 */
	@ResponseBody	//可将Map<String,Object> map放入方法入参中
	@RequestMapping(value="login",method=RequestMethod.POST)//用GET请求密码显示在地址栏不安全
	public Map<String,Object> login(String accName,String accPass,HttpSession session) {
		Map<String,Object> map = new HashMap<>();
		Account account = this.loginService.login(accName, accPass);
		if(account != null) {
			session.setAttribute("account", account);//将用户信息加入到session域中
			//这里用原生的,SpringMVC就是加个session注解
			map.put("account", account);//将用户信息的数据加入到请求域
			map.put("code", "1001");
			map.put("message", "登录成功");
		}else {
			map.put("code", "1003");
			map.put("message", "登录失败");
		}
		return map;
	}
}
package com.wanbangee.controller;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.wanbangee.entrties.BookCar;
import com.wanbangee.entrties.BookInfo;
import com.wanbangee.service.BuyBookService;

@Controller
public class BuyBookController {
	@Autowired
	private BuyBookService buyBookService;
	
	/**
	 * 买书
	 * @param accId
	 * @param bookNo
	 * @return
	 */
	@ResponseBody //请求方式以修改为主,买书要修改账户余额图书库存,是个修改操作
	@RequestMapping(value="buyBook",method=RequestMethod.PUT)
	public Map<String,Object> buyBook(Integer accId,Integer bookNo){
		Map<String,Object> map = new HashMap<>();
		try {
			this.buyBookService.buyBook(accId, bookNo);
			map.put("code", 1001);
			map.put("message", "买书成功");
			return map;
		} catch (Exception e) {//有异常就失败
			e.printStackTrace();
			map.put("code", 1002);
			map.put("message", "买书失败,有异常");
			return map;
		}
	}
	
	/**
	 * 图书列表信息查询
	 * @param pageSize 
	 * @param pageCurrent 
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value="getBookInfo",method=RequestMethod.GET)
	public Map<String,Object>  getBookInfo(Integer pageSize,Integer pageCurrent){
		Map<String,Object> map = new HashMap<>();
		try {
			List<BookInfo> bookInfos = this.buyBookService.selectBookInfo(pageSize, pageCurrent);
			if(bookInfos.isEmpty()) {//查询结果为空,或者有异常就失败
				map.put("code", 1002);
				map.put("message", "查询失败");
				return map;
			}
			map.put("code", 1001);
			map.put("message", "查询成功");
			map.put("bookInfos", bookInfos);//把查询到的数据放到map中响应给前端
			map.put("total", this.buyBookService.selectCount());//做分页查询,把查询到的数据总笔数响应给前端
			return map;
		} catch (Exception e) {//有异常就失败
			e.printStackTrace();
			map.put("code", 1002);
			map.put("message", "查询失败,有异常");
			return map;
		}
	}
	
	/**
	 * 	充值
	 * @param accId
	 * @param addMoney
	 * @return
	 */
	@ResponseBody  //请求方式以修改为主,充值要修改账户余额,是个修改操作
	@RequestMapping(value="addMoney",method=RequestMethod.PUT)
	public Map<String,Object> addMoney(Integer accId,Double money){
		Map<String,Object> map = new HashMap<>();
		int count = 0;
		count = this.buyBookService.updateAccBalanceByAccId(accId, money);
		try {
			count = this.buyBookService.updateAccBalanceByAccId(accId, money);
			if(count == 0) {//影响的数据笔数是0笔,或者出现异常,就会充值失败
				map.put("code", 1002);
				map.put("message", "充值失败");
				return map;
			}
			map.put("code", 1001);
			map.put("message", "充值成功");
			return map;
		} catch (Exception e) {//有异常就失败
			e.printStackTrace();
			map.put("code", 1002);
			map.put("message", "充值失败,有异常");
			return map;
		}
	}
	
	/**
	 * 	查询账户余额
	 * @param accId
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value="getAccBalance",method=RequestMethod.GET)
	public Map<String,Object> getAccBalance(Integer accId){
		Map<String,Object> map = new HashMap<>();
		double accBalance = 0;
		try {
			accBalance = this.buyBookService.selectAccBalanceByAccId(accId);
			map.put("code", 1001);
			map.put("message", "账户余额查询成功");
			map.put("accBalance",accBalance);//把查询到的数据响应给前端
			return map;
		} catch (Exception e) {//有异常就失败
			e.printStackTrace();
			map.put("code", 1002);
			map.put("message", "账户余额查询失败,有异常");
			return map;
		}
	}
	/**
	 * 加个购物车
	 * 同一个商品加入购物车两次,应该是在数量和总价上更改,而不是再加一笔购物车数据
	 * 每增加一个商品,要先判断这个商品在购物车里是否存在,没有的话才新增数据,有的话就不新增数据
	 * @param accId
	 * @param bookNo
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value="addCar",method=RequestMethod.POST)
	public Map<String,Object> addCar(Integer accId,Integer bookNo){
		Map<String,Object> map = new HashMap<>();
		try {
			int count = this.buyBookService.addCar(accId, bookNo);
			if(count == 0) {
				map.put("code", 1002);
				map.put("message", "加入购物车失败");
				return map;
			}
			map.put("code", 1001);
			map.put("message", "加入购物车成功");
			return map;
		} catch (Exception e) {//有异常就失败
			e.printStackTrace();
			map.put("code", 1002);
			map.put("message", "加入购物车失败,有异常");
			return map;
		}
	}
	
	
	/**
	 * 	购物车列表查询
	 * 没有分页不用放数据的笔数
	 * @param accId
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value="getBookCar",method=RequestMethod.GET)
	public Map<String,Object> getBookCar(Integer accId){
		Map<String,Object> map = new HashMap<>();
		try {
			List<BookCar> bookCars = this.buyBookService.getBookCar(accId);
			if(bookCars.isEmpty()) {
				map.put("code", 1002);
				map.put("message", "查询失败");
				return map;
			}
			map.put("code", 1001);
			map.put("message", "查询成功");
			map.put("bookCars", bookCars);
			return map;
		} catch (Exception e) {
			e.printStackTrace();
			map.put("code", 1002);
			map.put("message", "查询失败,有异常");
			return map;
		}
	}
	
	
	/**
	 * 	修改购物车数量
	 * @param carId
	 * @param bookNum
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value="updateBookCar",method=RequestMethod.PUT)
	public  Map<String,Object> updateBookCar(Integer carId,Integer bookNum){
		Map<String,Object> map = new HashMap<>();
		try {
			int count = this.buyBookService.updateBookCar(carId, bookNum);
			if(count == 0) {
				map.put("code", 1002);
				map.put("message", "修改失败");
				return map;
			}
			map.put("code", 1001);
			map.put("message", "修改成功");
			return map;
		} catch (Exception e) {
			e.printStackTrace();
			map.put("code", 1002);
			map.put("message", "修改失败,有异常");
			return map;
		}
	}
	
	
	/**
	 * 	删除购物车
	 * @param carId
	 * @param bookNum
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value="deleteBookCar",method=RequestMethod.DELETE)
	public  Map<String,Object> deleteBookCar(Integer carId){
		Map<String,Object> map = new HashMap<>();
		try {
			int count = this.buyBookService.deleteBookCar(carId);
			if(count == 0) {
				map.put("code", 1002);
				map.put("message", "移除失败");
				return map;
			}
			map.put("code", 1001);
			map.put("message", "移除成功");
			return map;
		} catch (Exception e) {
			e.printStackTrace();
			map.put("code", 1002);
			map.put("message", "移除失败,有异常");
			return map;
		}
	}
	
	
	//提交购物车,查询这个人的所有的购物车数据,然后在一笔笔去购买图书,减少图书库存和账户余额
	/**
	 * 	提交购物车
	 * @param accId
	 * @return
	 */
	@RequestMapping(value="submitBookCar",method=RequestMethod.PUT)
	@ResponseBody
	public Map<String,Object> submitBookCar(Integer accId){
		Map<String,Object> map = new HashMap<>();
		try {
			this.buyBookService.submitBookCar(accId);
			map.put("code", 1001);
			map.put("message", "提交购物车成功");
			return map;
		} catch (Exception e) {
			e.printStackTrace();
			map.put("code", 1002);
			map.put("message", "提交购物车失败,有异常");
			return map;
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值