shopping自练体会

来源:互联网 发布:mac如何删除office 编辑:程序博客网 时间:2024/04/27 14:19

关于用户模块:
其实在User类中,定义了系列的方法,
怎么在jsp页面中不经过post方法,将该User对象的信息保存下来,那么就要用到session的方法,在用户登陆时,可以将
session.setAttribute("user", u);这样写只能在jsp页面中,(目前知道的情况下),但是用到struts时,编写action时,判断session时,可以用到对应的写法:request.getSession().getAttribute("username")!= null
以及赋值session:
request.getSession().setAttribute("username", username);
而这时的u怎么得到该用户的所用信息,这时,用户登陆,需要检测吧,但是这里设计的JavaBean,方法,返回值可以是User,其中还包括检测部分,如果检测部分通不过,后面就不需要返回User,然后再将返回值赋给u,不就好了嘛。

User u=(User)session.getAttribute("user");

想到这里,购物时的商品收藏,这项功能,可以用到相似的技术。
其实这里商品收藏。可以在用户中定义一个外键即可,然后提取出来即可。


关于Category模块:
这里主要用到DAO的设计思想,关于与数据库打交道的的具体代码那一层都写到DAO中,在向相应的jsp显示层,只调用相应的逻辑层。而这相应的逻辑层只是调用DAO的方法而已,这样在后期的维护中,起到意想不到的好处。
同时,在Category模块中,还用到JS的相关知识,分层展示类列表,有一定的难度。
主要的特点,在DAO设计中像一些操作,方法采用递归的方法。像id 、pid即本节点、父节点,删除或者取出类列表时,用到递归。这种递归怎么运用呢?public static void getCategories(List<Category> categories,int id)根据是否是叶子节点,然后再采取相应的操作。
在Category中,涉及到JS的面向对象编程,怎么动态的显示数据。以及怎么用到js向数据库中添加数据,可以参照categoryAjax.jsp相关内容。

想一些JavaBean的设计,怎么更新数据,获得对象列表信息。这里主要用到对象为参数,这样较方便。什么添加啦,更新啦,可以将信息赋给对象,然后再定义一个DAO方法保存对象即可。
在这个模块中主要学到多接口的定义方法。这种思想,以后要加强。
遗留问题js的点击,和双击事件的不同现象问题,有待考虑。
2010年01月26号 14:53于家中


SQL.DATE只有日期没有时间,而SQL.Timestamp中既包含日期也包含日期,但是两者都继承UTIL.DATE,难怪在商品添加时,Date类型的不能用Timestamp转换了,因为引用的包错误,如果改为Java.util.Date就好了,但是如果引用java.sql.Date就会出错。因为两者的范围不同。

商品添加,可以利用Boolean 类型的lazy变量。当lazy为true时,可以用loadById(int id)进行赋值。但是用到上述loadById(int id)需要再进行一次数据库查询操作。对优化效率不利。
还有非lazy型的,在初始化product时,自动给Category 初始化。
在添加商品时,选择类别时一定要选择叶子节点,这样用利于商品的搜索。像阿里巴巴、淘宝大型的网站时,都是采用将商品添加在叶子节点下面。
怎么在类别列表中添加商品,而传到productadd.jsp页面时,怎么将类别的下拉列框自动选择呢?
只要在productadd.jsp页面中添加如下语句即可。<option value="<%=c.getId()%>"<%=c.getId()==categoryid ? "selected" : "" %>>
         <%=preStr + c.getName()%>
        </option>


 <!--  如果用<jsp:forward page="complexsearchresult.jsp"></jsp:forward>标签的话,可以将request对象传给到complexsearchresult.jsp页面,这样通过request得到的参数值就会传到该要的页面。如果用response.sendRedirect("complexsearchresult.jsp")重定向的话说,那么将得不到request对象的值。所以要舍弃。-->
 这样,在做复杂的搜索时,参数较多,在一个页面时,不容易分析,最好将搜索结果的页面,重新再写一个,可以根据action的值,进行jsp:forward即可。其实用form表单提交一样,但是方法多样性,还是有必要的,这样不好 吗?

刷新窗口的js代码:<script type="text/javascript">window.parent.main.location.reload()</script>这里的main指的是框架中指定的位置代表符,就是指定的刷新区域。像更改操作时,需要及时刷新界面,那么,这段代码添加在哪里呢?就是执行JavaBean方法后,紧跟着即可,一般在}中。只是用<%执行的JavaBean方法%>js代码<%}%>

String sql="select * from product order by pdate desc limit 0,"+count;这句sql的语句是从表product中按pdate从大到小的顺序,取出记录集0至count个,其实就是count个。


商品模块部分剩余总结:
像商品的修改,添加等,都涉及到JavaBean中相似方法的模仿,它们的参数都是以商品的对象,通过对象,可以得到对象的属性,给对象的属性赋值,其实就是get和set方法,其实这种就是面向对象的 编程。

像分页的实现。采用的是什么方法呢?
public int getProducts(List<Product> products, int pageNo, int pageSize)
首先返回值是什么呢?当然是总页数(pageCount)。
String sqlcount="select count(*) from product";
 rsCount=DB.getResultSet(stmt, sqlcount);
  
       rsCount.next();
    pageCount=(rsCount.getInt(1)+pageSize-1)/pageSize;

根据商品的属性,有时在用户用到的界面时,要显示商品的类别名称时,这种功能怎么实现呢?往往有些程序员会new 一个Category对象。或者再通过id号在ByLoad(id)一个category对象,这样不是不可以,但是效率上是不好的。这样执行了两个表的查询,不如执行一次表连接的效率快。将Category作为Product的属性来看待即可。这样不是一举两得吗?,其实方法多的是,就是想到的问题。

像多个categoryid怎么通过request提交过来呢?

还有一些表单值怎么在提交时,怎么用js给其赋值呢?

一些sql语句的添加,如多个categoryid怎么添加到sql语句中呢?
String strId="";
if(categoryId!=null&&categoryId.length>0){
   strId+="("; 
for(int i=0;i<categoryId.length;i++){
       if(i < categoryId.length-1)
        strId+=categoryId[i]+",";
       else
        strId+=categoryId[i];
        
       }
      strId+=")";
      sql+=" and categoryid in "+strId;

像like搜索:if(keyword!=null && !keyword.trim().equals("")){
       sql+=" and name like'% "+keyword+" %'or descr like '%"+keyword+"%'";
      }

关于日期类搜索sql:if(endDate!=null){
       sql+=" and pdate <='"+new SimpleDateFormat("yyyy-MM-dd").format(endDate)+"'";
      }

最主要的DAO设计模式即面向接口的编程。

button类型的转换页面用js<input type="button" value="确认订单"
   onclick="document.location.href='confirm.jsp'">,submit类型的就简单了,

左外连接,left SQL语句。

<img src="../images/reports/salesCountReport.jpg"></img>
<img src="<%=request.getContextPath() %>/images/reports/salesCountReport.jpg"></img>
request.getContextPath()得到的是web工程名下的路径,如工程名为shop则结果是:http://localhost:8080/shop(上述只是按照本机示例而已。)
在这里学会了怎么定义标签<product:list></product:list>,这里详细介绍一下标签定义,及运用。首先在jsp页面内写入:
<%@ taglib prefix="product" uri="/productlist"%>这里的productlist是WEB-ING目录下或其子目录下的productlist.tld文件名,在productlist.tld中
写入如下内容:<?xml version="1.0" encoding="ISO-8859-1" ?>

<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
 xmlns:xsi="
http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="
http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
 version="2.0">

  <tlib-version>2.0</tlib-version>
  <short-name>product</short-name>
  <uri>/productlist</uri>
  <tag>
    <name>list</name>
    <tag-class>com.sy.shop.Tag.productlistTag</tag-class>
    <body-content>empty</body-content>
  </tag>      
</taglib>
其中 <short-name>product</short-name>指的是标签前缀,<uri>/productlist</uri>可以为任意值,如/com.sy.shop.list,可以根据相应的意思来定义。
<name>list</name>指的是标签后缀。
下面要定义class了,定义类时,一定要定义在包内,定义类时要继承SimpleTagSupport然后再重写doTag方法,这里都可以先继承,然后再重写。如:public class productlistTag extends SimpleTagSupport {
 
   @Override
 public void doTag() throws JspException, IOException {
  
    List<Product>list=new ArrayList<Product>();
    list=ProductMgr.Instance().getProducts();
    for(int i=0;i<list.size();i++){
     this.getJspContext().getOut().write(list.get(i).getName()+"<br>");
    }
 }


  
}


前台搜索下拉框联动AJAX实现:
共有如下方法:
1:第一种动态生成JS代码,把所用到的JS代码都一次性生成完毕。然后再function方法里直接将<%=StrJs%>加入即可。具体怎么生成StrJs字符串呢?这里用到JavaBean,在该页面中<%!
定义获得Str的方法,该方法最好是private String类型的。根据该项目,就是将父节点的所用孩子结点找到,然后按照相应的方式形成一定规则的字符串。部分代码如下:
StringBuffer buf=new StringBuffer();
  //buf.append("if(document.form2.category1.options[document.form2.category1.selectedIndex].value=="+topCategory.getId()+"){");
  int childcount=1;//因为二级目录一开始已经存在一个了。
  for(int i=0;i<categories.size();i++){
   Category c=new Category();
   c=categories.get(i);
   
   if(c.getPid()==topCategory.getId()){
    buf.append("document.form2.category2.options["+childcount+"].text='"+c.getName()+"';/n");
    buf.append("document.form2.category2.options["+childcount+"].value='"+c.getId()+"';/n");
    childcount++;
   }
  }
  buf.insert(0,"document.form2.category2.options[0].text='请选择二级目录'"+";/n");
  buf.insert(0,"document.form2.category2.options[0].value='-1'"+";/n");
  buf.insert(0,"document.form2.category2.selectedIndex=0"+";/n");
  buf.insert(0,"document.form2.category2.options.length="+childcount+";/n");
  buf.insert(0,"if(document.form2.category1.options[document.form2.category1.selectedIndex].value=="+topCategory.getId()+"){"+"/n");
  buf.append("}/n");
  return buf.toString();
%>
2:第二种方式:用到了AJAX。
在显示页面(indexAJAX.jsp),用到JS代码,发送信息到后台页面(getChildCategory.jsp),而后台页面又将所需信息返回到显示页面。这时怎么返回的呢?这里用到JS,取出信息,然后再生成所需下拉框状态改变时,相应的代码,这比第一种方法,好多了。不用将所用的下拉框所有状态的代码都生成,而是需要时再产生。indexAJAX.jsp中代码如下:
<script type="text/javascript">
   <!--
       var req;
      
     function changeCategory(){
     
     var id = document.form2.category1.options[document.form2.category1.selectedIndex];
  var url = "getChildCategory.jsp?id=" + escape(id.value);
  if(window.XMLHttpRequest) {
   req = new XMLHttpRequest();
  } else if (window.ActiveXObject) {
   req = new ActiveXObject("Microsoft.XMLHTTP");
  }
  req.open("GET", url, true);
 
  req.onreadystatechange = callback;
 
  req.send(null);
  
     }
     
     function callback() {
  if(req.readyState == 4) {//readyState有四种状态0、1、2、3、4分别代表uninitialized/loading/loaded/interactive/completed
   if(req.status == 200) {//status==200表示正常。
    parse(req.responseText);
   
   }
  }
 }
 
 function parse(msg){
  msg=msg.replace(/(^/s*)|(/s*$)/g,"");
    
     if(msg==null || new String(msg)==""){
      alert("|"+msg+"|");
      document.form2.category2.length=1;
   document.form2.category2.selectedIndex=0;
   document.form2.category2.options[0].text='请选择二级列表';
   document.form2.category2.options[0].value='-1';
  //return;有return则不用else了。
     }else{
  var categories=msg.split("-");
  //alert(categories.length);
   document.form2.category2.length=categories.length+1;
   document.form2.category2.selectedIndex=0;
   document.form2.category2.options[0].text='请选择二级列表';
   document.form2.category2.options[0].value='-1';
  
  for(var i=0;i<categories.length;i++){
  
   var categoryprops=categories[i].split(",");
   var id=categoryprops[0];
   var name=categoryprops[1];
   document.form2.category2.options[i+1].text=name;
   document.form2.category2.options[i+1].value=id;
  }}
  
 }
     
  
  
   -->
</script>
后台:response.setContentType("text/xml");
 response.setHeader("Cache-Control", "no-store"); //HTTP1.1
 response.setHeader("Pragma", "no-cache"); //HTTP1.0
 response.setDateHeader("Expires", 0); //prevents catching at proxy server
 int id = Integer.parseInt(request.getParameter("id"));
 Category parent = Category.loadById(id);
 System.out.println("id=" + id);
 System.out.println("parent:" + parent.getId() + ","
   + parent.getName());
 List<Category> childs = new ArrayList<Category>();
 childs = parent.getChilds();

 StringBuffer buf = new StringBuffer();

 for (Iterator<Category> it = childs.iterator(); it.hasNext();) {
  Category child = new Category();
  child = it.next();
  buf.append(child.getId() + "," + child.getName() + "-");
 }
 if (childs.size() > 0) {
  buf.deleteCharAt(buf.length() - 1);
 }
 System.out.println(buf.toString());
 response.getWriter().write(buf.toString());
3:第三种方法:
这种方法主要用到JS中的一个方法:eval(req.responseText)意思是将req.responseText的内容直接执行,如果没有这个方法,必须还在相应的页面定义解析req.responseText的function方法形如:方法2中的function parse(msg){}。上面所说的执行req.responseText内容,而req.responseText又是指的是什么呢?
指的是后台页面的中response.getWriter().write(buf.toString());,其实在后台页面中还要定义了buf,其实buf就是StringBuffer对象,然后再给buf赋值,形如:StringBuffer buf = new StringBuffer();
    for(int i=0;i<childs.size();i++){
     Category c=new Category();
     c=childs.get(i);
     buf.append("document.form2.category2.options["+(i+1)+"].text='"+c.getName()+"';/n");
  buf.append("document.form2.category2.options["+(i+1)+"].value='"+c.getId()+"';/n");
    }
   buf.insert(0,"document.form2.category2.options[0].text='请选择二级目录'"+";/n");
   buf.insert(0,"document.form2.category2.options[0].value='-1'"+";/n");
   buf.insert(0,"document.form2.category2.selectedIndex=0"+";/n");
   buf.insert(0,"document.form2.category2.options.length="+(childs.size()+1)+";/n");
4:第四种方法:这里涉及到XML
其实就是将buf生成XML类型的文件,然后再返回到前台页面。然后前台页面在根据生成的xml内容,利用JS方法将其转换成相应的所需的JS代码。关键JS代码如下:
var req;
      
     function changeCategory(){
     
     var id = document.form2.category1.options[document.form2.category1.selectedIndex];
  var url = "getChildCategoryXML.jsp?id=" + escape(id.value);
  if(window.XMLHttpRequest) {
   req = new XMLHttpRequest();
  } else if (window.ActiveXObject) {
   req = new ActiveXObject("Microsoft.XMLHTTP");
  }
  req.open("GET", url, true);
 
  req.onreadystatechange = callback;
 
  req.send(null);
  
     }
     
     function callback() {
  if(req.readyState == 4) {//readyState有四种状态0、1、2、3、4分别代表uninitialized/loading/loaded/interactive/completed
   if(req.status == 200) {//status==200表示正常。
    //parse(req.responseText);
    alert(req.responseText);
    alert(req.responseXML);
    parseXML(req.responseXML);
   }
  }
 }
 
 function parseXML(xml){
  var categories=xml.getElementsByTagName("categories")[0];
  document.form2.category2.length=categories.childNodes.length+1;
  document.form2.category2.selectedIndex=0;
  document.form2.category2.options[0].text='请选择二级列表';
  document.form2.category2.options[0].value='-1';
  
  for(var i=0;i<categories.childNodes.length;i++){
   var category=categories.childNodes[i];
   var id=category.childNodes[0].childNodes[0].nodeValue;
   var name=category.childNodes[1].childNodes[0].nodeValue;
   document.form2.category2.options[i+1].text=name;
   document.form2.category2.options[i+1].value=id; 
  }
 }