网上商城实战
一、环境搭建
···············导入包 10个jar包
···············搭建包结构dao utils domain service web(filter listener servlet)
1.数据工具包,c3p0连接池,通用Servlet
2.BaseServlet继承Httpservlet,重写Service(每个请求都会经过BaseServlet,修改编码为UTF-8,处理各种请求,利用反射让对应的方法执行)
BaseServlet··································
//获取参数
request.setCharacterEncoding("UTF-8");
String methodName = request.getParameter("method");
//健壮性判断
if(methodName==null || "".equals("method")){
//跳转到404
return;
}
try {
//通过反射找到执行的方法
Method method = this.getClass().getMethod(methodName, HttpServletRequest.class,HttpServletResponse.class);
String path = (String) method.invoke(this, request,response);
if(path!=null){
//做跳转
request.getRequestDispatcher(path).forward(request,response);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
用户模块······················································
一、创建表
表设计:
商品表
用户表 >用户id 用户名 密码 邮箱 姓名 性别 生日 用户状态 激活码
订单 >订单id 订单时间 订单总价 收货人 联系电话 送货地址 订单状态 用户id(指向用户主键)
(订单详情表)中间表 >订单id 商品id 数量 总价(小计)(包含两个表的主键)
分析实体
用户 订单 商品 商品分类
用户 订单 一对多
订单 商品 多对多
商品 商品分类 多对一
商城需求分析
二、复制项目
1.修改图片路径
2.修改首页不显示Servlet
<jsp:forward page="/IndexServlet">
<jsp:param value="index" name="method">
</c:forward>
3.创建用户实体类
三、创建用户dao接口,用户dao层实现类
四、创建用户service接口,用户Service实现类
五、创建用户servlet继承BaseServlet
六、注册页面跳转(每个请求都要过Servlet)
跳转RegisterUI(method="registerUI")
#异步用户名校验
#表单校验
#注册成功
#Servlet-Service-dao-发送邮件
#创建menu.jsp
<%@ incude %>把导航和注册包含
<%@ include file="menu.jsp"%>
表单>
异步检测用户名是否存在
$.post("",{},function(data){})//格式
Userservlet>UserService>UserDao>retrun User
!#使用父类接口指向实现类?
List<String> list = LinkedList<String>();
七、注册成功后跳转(String类型转Date类型)beanUtil.converter(new 实现类,date.class);
#邮件注册(激活码已经生成)
导email.jar包
##理解
邮箱服务器-----:如果安装了邮箱服务器软件,这个电脑称为邮箱服务器
电子邮箱-------:理解成服务器上的一块空间,通过账号访问自己的区域
收发邮件的协议
发邮件smtp:25端口
收邮件pop3:110端口
软件安装
邮件服务器搭建
邮件客户端
定义发送邮件方法
public static void sendMail(String to,String code)
service 给 to(发给谁),把激活码发送给code
//获得连接
Prooerties props = new Prooerties();
props.setProperty()-------默认连接本地
Session session = Session.get(props,new Authenticator(){
@override
protected PasswordAuthentication getPasswordAuthentication(){
return new PasswordAuthentication("service@store.com","111")
}
})
//构建邮件
Message message = new MimeMessage(session);
message.setFrom(new InterNetAddress("service@store.com"))
//设置收件人
message.addRecipient(RecipentType.TO,new InternetAddress(to));
//to : 收件人 Cc :抄送 BCC:暗送,密送
//主题
message.setSubject("来自黑马商城的激活邮件")
//正文
message.setContent("<h1>来自黑马商城的激活邮件:请点击下面连接激活</h1>","text/html;charset=uft-8");
//发送 (可以设置成一个properties管理员在外面设置)
Transport.send(message);
八、用户登录点击激活码
调用激活方法
查询是否有该激活码
如果有,就将该用户的state属性改为2
(###注意Sql语句千万要写对)
九、用户登录
1.登录到主页
跳转到method = login
判断状态是否已经激活,如果激活就登录。
用户退出
删除Session 销毁Session
2.验证码(异步检测验证码是否相等)
点击验证码换一张(new Date())
(扩展表单中的StringUtil)
return obj==null || "".equals(obj) 字符串顺序要正确
2.自动登录
登录成功后判断用户是否选中自动登录
AutoLogin
创建过滤器
//获取参数如果为true,就将用户名写入到Cookie中,放7天,登录时候就要将value中的值修改为${cookie.username.value }
${cookie.cookie.value}//获取cookie值 jsp中非常牛逼的工具
自动登录
记住密码
十一.首页分类
1. 异步加载分类加载,页面加载时候请求后台
1.建表>建servet>service>dao
页面加载$(function(){
loadCategory();
loadProduct()
})
效率问题:每次都要请求数据库,响应到前台,
[{"cid":1,"cname":"鞋靴箱包"},{"cid":1,"cname":"鞋靴箱包"},{"cid":1,"cname":"鞋靴箱包"}]
(每次都要ajax都要异步查询所有分类)###影响效率
解决方案:可以把数据先放到某个缓存中,先去拿如果没有就再去查找
ehcache 缓存框架 Hibernate 二级缓存使用的技术.
memcached 缓存技术
redis 缓存技术
内存也相当于一种数据,用空间换时间的方法
操作缓存步骤
1.去缓存中查找数据
找到,直接返回数据
未找到,进行第二步
2.没有找到的话,去数据库中查询数据,还需要将数据存入缓存中
//使用缓存技术
cache
//先去查找缓存
//读取配置文件
CacheManager cacheManager = CacheManager.create(CategoryServiceImpl.class.getClassLoader().getResourceAsStream("ehcache.xml"));
//读取指定的缓存
Cache cache = cacheManager.getCache("categoryCache");
List<Category> list = null;
Element element = cache.get("list");
//如果没有
if(element==null){
System.out.println("缓存中没有数据--------------");
CategoryDao categoryDao = new CategoryDaoImpl();
list = categoryDao.findAll();
element = new Element("list", list);
cache.put(element);
return list;
}else{
//缓存中有数据
System.out.println("缓存中有数据--------------");
list = (List<Category>) element.getObjectValue();
return list;
}
}
3.缓存的工具类
获取缓存中值的方法.
设置缓存中值的方法.
(###处理缓存,在服务器初始化时,将初始化资源写入到缓存中 利用ServletContextListener 中init方法中直接将分类信息写入到缓存中.)
十二.商品模块(###查询热门商品,和最新商品)
1.建商品表
2.创建实体>servlet>service>dao层
hibernate ORM的DAO层框架 object-relational mapping d对象关系映射
热门商品显示
最新商品显示
bo思想
商品页,查询分类下商品,按分页显示
参数 cid method="findByCid" currPage= 1
封装PageBean
//当前页>页面大小>List<T>list>总页数>开始begin>查询几页
3.根据商品id查询商品信息,点击某个商品,获取商品id提交后台。
4.商品浏览记录
###获取指定名称的Cookie
点击某个商品,将商品id存入cooke中,
进行判断,如果空,就创建一个cookie,如果不为空,
判断是否包含,如果不包含,判断长度,如果长度小于6,
#(最后添加到cookie中)就appendFrist,如果长度大于6,就把removeLast,appendFirst.
按照指定格式放到cookie中
(前台调用业务层,findProductByid(),返回对象,依次写到page域中,通过p.pimage路径显示图片)
如果没有浏览记录,也就是没有cookie ,使用out.print("<h1>恁还有米有浏览记录</h1>")
5.清除缓存
clearHistor
(现在编写的不太方便扩展)推演出工厂模式.
传统方式
Servlet>Service>dao
Servlet>ServiceIml>ServletDao
面向接口,可以对程序进行扩展
接口和实现类存在耦合关系.
原来模式:Ocp:open-close原则:对程序扩展可以,修改代码不行
工程模式
工厂+反射+配置文件的方式完成程序的解耦合 --- Spring 的 IOC:控制反转:用来解决程序的解耦合
创建BeanFactory
解析xml文件
获取指定元素 Element elementBean = (Element) selectsingleNode("//bean[@id='"+id(传入的id)+"']");
获取指定属性 String class = element.AttributeValue("class");
通过反射创建类的实例
return Class.forName(class).newInstance();
当每次获取实现类时,就调用BeanFactory.getBean(传入xml配置的id)
<bean id="UserDao" class="UserDaoImpl.class">
十三.加入购物车
创建两个实体类
(带有逻辑的实体类BO)bisnasi Object
购物项:每个商品的对象,商品数量,小计(小计=对象价格*商品数量),因为不需要修改小计,所以就不用set方法
商品对象 - 商品数量 - 小计 (小计=单价*count)
(BO模式实体类)
购物车:总价:购物项的集合(总价是每个购物车里商品项中的小计之和)
购物车集合:Map<String,CartItem> map = new LinkedList<String,CartItem>();
总价:total;
将页面修改成表单,添加隐藏字段
页面跳转如果用转发,就会造成重复添加到购物车.
购物车(
map<String,cartItem>
total
)
cartItem
product, count ,subtotal
加入购物车,如果没有登录,点击登录,弹出登录界面,异步登录
登录成功刷新页面
登录失败提示失败
十四.订单模块
1.点击提交订单,js中判断用户是否登录 ###()${empty resultUser},生成订单,向两个表插入数据,订单表>订单项中(利用事务保证代码的完整性
建表,实体
订单的总金额就是购物车中的总金额(从Session中获取cart的total)
2.点击生成订单,封装Order对象.
如果购物车时空,就跳转到Product_list
如果用户为空,跳转登录页面
3.订单项封装数据
遍历cart中购物项中所有的列,设置订单项
4.插入数据,使用事务传入con
十五,查看我的订单
进入查找所有订单,传入当前页为1,
封装page,List<Order>:中查找所有用户为(从域中获取)当前用户的所有订单, select * from order where uid = (session中获取)----返回订单
并且查询订单项中的所有商品,select * from orderItem o,product p where o.pid = p.pid and oid=''
遍历所有订单,获取每一个orderIteml,根据每个订单的oid,查询商品信息和订单项封装成对象,将订单的订单项封装,返回订单列表
page传入到页面,显示所有订单,订单中的订单项.
(封装成MapListHandler) List<Map<String,Object>> ---查询出来的订单项和product的键为key,值为value,
订单id---
订单项
product
product
product
订单项
product
product
product
订单项
订单id---
订单项
订单项
订单项
订单id---
订单项
订单项
订单项
十六.订单支付
判断订单属性,
1.2.3.4种状态 多表查询,封装order对象, 将order的实体封装,遍历每个订单项,将订单项对象和product对象封装到order对象中,响应到页面
在线支付:
1.直接和银行网银支付接口对接
2.支付宝_微信
支付流程.
电子签名:
向支付接口提交参数
创建付款方法(利用隐藏字段<input type="hidden"/>)
扩展properties工具类
业务对象,将支付的所有参数封装成业务对象,pay对象,跳转到一个页面,让表单提交,
配置回滚页面,修改订单状态.
十七.权限过滤器
判断是否登录.获取Session中的信息,如果登录了>放行,如果没有登录显示没有登录
一个filter可以配置多个mapping,过滤所有后台的东西.
|
|