Tmall_Fore_Sum
总结
一、项目结构
tmall
包结构
tmall.bean 实体类
tmall.comparator 比较器
tmall.dao DAO类
tmall.filter 过滤器
tmall.servlet servlet
tmall.test 测试类
tmall.util 工具类
web目录
int start= 0;
int count = 5;
try {start = Integer.parseInt(request.getParameter("page.start"));
} catch (Exception e) {}
try {count = Integer.parseInt(request.getParameter("page.count"));
} catch (Exception e) {
}
Page page = new Page(start,count);
这个好理解,剩下的就是jsp页面上的各种方法了。具体可以看之前的category
概述一下,adminPage中,中间页
${status.count}
注意status.index是从0开始的,status.count是从1开始的,点击了中间的链接,就相当于传了参。0-4;5-9;这样一页页的传出来的,通过新的start,以分类为例,List
5. 一类产品多属性配置
属性管理,准备好PropertyServlet类,属性是依附在分类上的,在分类时,点击按钮进入属性管理页面,先通过页面点击时获取分类的id,进行DAO操作,获取该分类下的所有属性,并且从此可以对其进行CRUD。
public String list(HttpServletRequest request, HttpServletResponse response, Page page) {int cid = Integer.parseInt(request.getParameter("cid"));Category c = categoryDAO.get(cid);List ps = propertyDAO.list(cid, page.getStart(),page.getCount());int total = propertyDAO.getTotal(cid);page.setTotal(total);page.setParam("&cid="+c.getId());request.setAttribute("ps", ps);request.setAttribute("c", c);request.setAttribute("page", page);return "admin/listProperty.jsp";}
Param也可以看出来用在了这里
6. 一款产品多图片维护
难点在于上传图片
public String add(HttpServletRequest request, HttpServletResponse response, Page page) {//上传文件的输入流InputStream is = null;//提交上传文件时的其他参数Map params = new HashMap<>();//解析上传is = parseUpload(request, params); //根据上传的参数生成productImage对象String type= params.get("type");int pid = Integer.parseInt(params.get("pid"));Product p =productDAO.get(pid);ProductImage pi = new ProductImage(); pi.setType(type);pi.setProduct(p);productImageDAO.add(pi);//生成文件String fileName = pi.getId()+ ".jpg";String imageFolder;String imageFolder_small=null;String imageFolder_middle=null;if(ProductImageDAO.type_single.equals(pi.getType())){imageFolder= request.getSession().getServletContext().getRealPath("img/productSingle");imageFolder_small= request.getSession().getServletContext().getRealPath("img/productSingle_small");imageFolder_middle= request.getSession().getServletContext().getRealPath("img/productSingle_middle");}elseimageFolder= request.getSession().getServletContext().getRealPath("img/productDetail");File f = new File(imageFolder, fileName);f.getParentFile().mkdirs();// 复制文件try {if(null!=is && 0!=is.available()){try(FileOutputStream fos = new FileOutputStream(f)){byte b[] = new byte[1024 * 1024];int length = 0;while (-1 != (length = is.read(b))) {fos.write(b, 0, length);}fos.flush();//通过如下代码,把文件保存为jpg格式BufferedImage img = ImageUtil.change2jpg(f);ImageIO.write(img, "jpg", f); if(ProductImageDAO.type_single.equals(pi.getType())){File f_small = new File(imageFolder_small, fileName);File f_middle = new File(imageFolder_middle, fileName);ImageUtil.resizeImage(f, 56, 56, f_small);ImageUtil.resizeImage(f, 217, 190, f_middle);}}catch(Exception e){e.printStackTrace();}}} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}return "@admin_productImage_list?pid="+p.getId();}
接着在ProductImageServlet的add()方法中进行处理
1. parseUpload 获取上传文件的输入流
2. parseUpload 方法会修改params 参数,并且把浏览器提交的type,pid信息放在其中
3. 从params 中取出type,pid信息,并根据这个type,pid,借助productImageDAO,向数据库中插入数据。
4. 根据request.getSession().getServletContext().getRealPath( "img/productSingle"),定位到存放分类图片的目录
除了productSingle,还有productSingle_middle和productSingle_small。 因为每上传一张图片,都会有对应的正常,中等和小的三种大小图片,并且放在3个不同的目录下
5. 文件命名以保存到数据库的分类对象的id+".jpg"的格式命名
6. 根据步骤1获取的输入流,把浏览器提交的文件,复制到目标文件
7. 借助ImageUtil.change2jpg()方法把格式真正转化为jpg,而不仅仅是后缀名为.jpg
8. 再借助ImageUtil.resizeImage把正常大小的图片,改变大小之后,分别复制到productSingle_middle和productSingle_small目录下。
9. 处理完毕之后,客户端条跳转到admin_productImage_list?pid=,并带上pid。
7. 产品展示
产品展示也是重头戏,主要用到了集合包含集合的思路,
一个Cs集合,包含了所有的Category;
其中的一个Category集合中又会有所有的产品集合,CPs,这是正常的
其中的一个Category集合中又会有所有的产品集合,但是这些产品集合被装在ProByRow中,有多个pbrs集合,然后展示的时候直 接获取pbrs就可以了
8. 搜索查询
这一块没有好好做,不过看看原理基本也差不多,通过表中的关键字+模糊查询,然后把所有符合的产品放到list中,然后展示出来所有的products。当然了,会有自己的专属search页面。
9. 登录、注册
好像一般的比较简单
复杂点的是登录验证,也就是买东西加入购物车的时候进行的验证,验证之后如果没有登录,那么进行拟态登录,其中拟态登录的时候用到了JQuery中的Ajax技术,这个觉得有必要稍微提一下,具体可以看simulatieLogin
两个监听器,通过class进行监听,这两个按钮都会通过JQuery的get方法,用异步ajax的方式访问forecheckLogin,获取当前是否登录状态
如果返回的不是"success" 即表明是未登录状态,那么就会打开登录的模态窗口
public String checkLogin(HttpServletRequest request, HttpServletResponse response, Page page) {User user =(User) request.getSession().getAttribute("user");if(null!=user)return "%success";return "%fail";}
10. 登录验证
哪些页面需要登录?哪些页面不需要呢?
a. 不需要登录也可以访问的
如:注册,登录,产品,首页,分类,查询等等
b. 需要登录才能够访问的
如:购买行为,加入购物车行为,查看购物车,查看我的订单等等
不需要登录也可以访问的已经确定了,但是需要登录才能够访问,截止目前为止还不能确定,所以这个过滤器就判断如果不是注册,登录,产品这些,就进行登录校验
1. 准备字符串数组 noNeedAuthPage,存放哪些不需要登录也能访问的路径
2. 获取uri
3. 去掉前缀/tmall
4. 如果访问的地址是/fore开头,又不是/foreServlet
4.1 取出fore后面的字符串,比如是forecart,那么就取出cart
4.2 判断cart是否是在noNeedAuthPage
4.2 如果不在,那么就需要进行是否登录验证
4.3 从session中取出"user"对象
4.4 如果对象不存在,就客户端跳转到login.jsp
4.5 否则就正常执行
public class ForeAuthFilter implements Filter{@Overridepublic void destroy() {}@Overridepublic void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)throws IOException, ServletException {HttpServletRequest request = (HttpServletRequest) req;HttpServletResponse response = (HttpServletResponse) res;String contextPath=request.getServletContext().getContextPath();String[] noNeedAuthPage = new String[]{"homepage","checkLogin","register","loginAjax","login","product","category","search"};String uri = request.getRequestURI();uri =StringUtils.remove(uri, contextPath);if(uri.startsWith("/fore")&&!uri.startsWith("/foreServlet")){String method = StringUtils.substringAfterLast(uri,"/fore" );if(!Arrays.asList(noNeedAuthPage).contains(method)){User user =(User) request.getSession().getAttribute("user");if(null==user){response.sendRedirect("login.jsp");return;}}}chain.doFilter(request, response);}@Overridepublic void init(FilterConfig arg0) throws ServletException {}}
三、设计模式
1.MVC模式
这个模式贯穿了整个项目
通过模型+试图+控制器的模式,页面时输入请求,通过Servlet进行处理,然后再其中加入DAO代码对数据库进行操作, 查到数据以后再通过servlet传递到视图中去。
2. Filter+Servlet+反射
之前的Servlet开发中会发现,当数量多了以后,一个功能模块3个方法,几十个模块加起来就近百个servlet,此时配置web.xml页面和编写Servlet类都变得极其冗余和复杂,所以我们引入了新的模式,Filter+Servlet,这样极大的减轻了开发的负担
具体:当有路径访问admin_category_list时候,通过BackServletFilter,查出所有admin开头的类,然后是categary,取值比如list,会把这个list存在method中后面使用,会访问categoryServlet,但是这个Servlet会继承BaseBackServlet,Base的service方法中就可以写一些初始的东西,比如list方法,然后给与相应的返回值。
如此一来,只要web配置了路径,Filter截取并按照设计模式来,大部分的模块功能都能较为简单的解决,也为后期SSH,SSM等框架做一个基础。
3. 统一的分页查询简化开发
所有的后台都使用同一个Page类,默认显示0-5,点击href的时候,会传参,通过计算重新获取新的start等值,再在数据库中查询新的数据并且显示到分页中。
4. 模块化JSP设计
简单的说就是能用公共页面的均为公共页面,从上往下
adminHeader.jsp 页面头,
最基本的声明,jsp指令
<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8" isELIgnored="false"%>
contentType="text/html; charset=UTF-8" 告诉浏览器使用UTF-8进行中文编码识别
pageEncoding="UTF-8" 本jsp上的中文文字,使用UTF-8进行编码
isELIgnored="false" 本jsp上会使用EL表达式
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix='fmt' %>
引入JSTL,使用c和fmt两种标准标签库
引入js和css
页脚页
<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8" isELIgnored="false"%>