zoukankan      html  css  js  c++  java
  • 跟着视频做的SSH项目总结

    一直没做过SSH(Struts2+Spring+Hibernate)的实际项目,只是三个框架学的还熟练,但整合起来使用就不知道了。所以前段时间在网上找了一套SSH实际项目的视频来学习(确切的说是买的...),一直没时间来总结,得到的经验主要是SSH的整合及配置,更多的则是SSH之外的一些经验,比如代码的书写及规范上就给了我很大的启发,很多经验只有从实际项目中才能得到。总体来说,SSH整合起来使用不是很难,配置文件也基本是固定的模式。

    先看下项目截图

    1.首页

    2.商品详细

    3.购物车

    4.订单管理

    5.用户注册

    6.后台管理系统首页【后台系统使用的是easyui】

    7.管理用户

    8.项目工程结构

     

    *******************************************************************************************************************************************************************

    *******************************************************************************************************************************************************************

     

    经验总结

    一.首先说说这个项目

    1.之前做过的项目大多只有后台系统,没有前端,不过学了这个系统之后,其实前端也不难,前端页面主要由专门的人员做好后,你只需要把数据显示到上面就行了,然后你可能还需要写一些js的代码。

    然后说说前端页面,前端页面把一些公共的部分提取出来,其它页面只需引入即可。公共部分如顶部,底部:

    通用页面放到一个文件夹里:

    在页面引入即可:

    2.系统不变的数据在系统启动时就缓存到application中。

    比如首页商品分类,导航栏内容等,这些数据基本是不会变的,可以在系统启动时就加载出来。就需要写一个监听器类,在服务启动时,将数据库中的数据加载进内存,并将其赋值给一个属性名,其它的 Servlet 就可以通过 getAttribute 进行属性值的访问

    3.导航,如下图。以前我写类似的导航代码时一般是用js判断各个层级,然后拼凑出一个导航来。然而作者是在服务端生成导航代码,他将生成导航的方法写到一个工具类中,每次访问哪个页面的时候,直接生成这段导航代码,然后返回到前端。这种做法不仅提高了开发效率,也提高了代码的重用性,好!

    导航工具类:

     1 package com.lizhou.tools;
     2 
     3 import java.util.List;
     4 
     5 /**
     6  * 导航工具类
     7  * @author Administrator
     8  *
     9  */
    10 public class NavTool {
    11 
    12     /**
    13      * 生成一级导航
    14      * @param subName
    15      * @return
    16      */
    17     public static String genNavCode(String subName){
    18         StringBuffer navCode=new StringBuffer();
    19         navCode.append("您现在的位置:");
    20         navCode.append("<a href='index.jsp'>首页</a>&nbsp;");
    21         navCode.append("&gt; ");
    22         navCode.append(subName);
    23         return navCode.toString();
    24     }
    25     
    26     /**
    27      * 生成多级导航
    28      * @param hrefList 导航标签链接的集合
    29      * @return
    30      */
    31     public static String genNavCode(List<String> hrefList){
    32         StringBuffer navCode=new StringBuffer();
    33         navCode.append("您现在的位置:");
    34         navCode.append("<a href='index.jsp'>首页</a>&nbsp;");
    35         navCode.append("&gt; ");
    36         for(String href : hrefList){
    37             navCode.append(href);
    38             navCode.append("&gt; ");
    39         }
    40         String nav = navCode.substring(0, navCode.lastIndexOf("&gt; "));
    41         return nav;
    42     }
    43 }

     

    二、说一说使用SSH开发的感受

    之前做一些完整的项目时一直使用的是JDBC+Servlet+Jsp,然后还有就是DBUtils等一些包来简化一些工作量。我会将mysql的一些操作封装成一个工具类,会写一个BaseDao来操作数据库,BaseDao能解决简单的增删改查功能,但要解决一些比较复杂的,比如涉及到级联的时候,可能就不适用了,需要重新写个类来实现相关的功能。自己设计好bean类后,还需要去设计表结构,而如果类有改动,则需要重新设计表,复杂的时候可能设计到几张表,如果有外键关系的话更恼火......

    使用SSH的话,首先来说你需要设计好类结构,然后加上注解或者声明式配置好,hibernate会自动生成表结构,而如果类有改动,表结构也会自动更改,这算是大大节省了开发时间了。然后,hibernate只需要一个BaseDao就基本能解决所有的数据操作,因为hibernate支持泛型。还有传数据和参数的问题,我们只需在action里写一个字段即可,省了很多代码。

    总的来说,使用SSH框架,我们只需要关心业务逻辑的实现即可,其它的很多问题不必担心。不过我在想我是不是离底层越来越远了......我个人还是挺喜欢写原生代码的...不喜欢框架。

    三、代码上得到的一些经验

    1.一类操作写到一个方法里:比如,根据产品名称查询,根据产品类别查询,模糊查询,查询所有等操作本属于一个操作:查询产品。在以前,我可能会分别写几个方法来查询,getByProductName(String name), getByProductType(String type), getProductList(),然而这些方法只是sql语句不一样而已,代码非常冗余。这些参数本就是产品这个类的字段,所以完全可以将这些查询参数封装到一个Product对象里,在一个方法里每个条件一个判断语句,然后拼凑Sql语句即可:getProductList(User user).

    比如下面这个service里查询产品的操作:使用一个集合来装参数,根据条件拼SQL语句。这样减少了代码,逻辑性也更强了,维护也方便。

     1 public List<Product> getProductList(Product product, PageBean pageBean) {
     2     StringBuffer sbHQL = new StringBuffer("FROM Product ");
     3     //存放参数
     4     List<Object> param = new LinkedList<Object>();
     5     if(product != null){
     6         //获取特价商品
     7         if(product.getSpecialPrice() == 1){ 
     8             sbHQL.append("AND specialPrice=1 ORDER BY specialPriceTime DESC ");
     9         }
    10         //获取热卖商品
    11         if(product.getHot() == 1){
    12             sbHQL.append("AND hot=1  ORDER BY hotTime DESC ");
    13         }
    14         //获取大类下的商品
    15         if(product.getBigType() != null){
    16             //添加参数
    17             param.add(product.getBigType().getId());
    18             sbHQL.append("AND bigType.id=? ");
    19         }
    20         //获取大类下的某个小类商品
    21         if(product.getSmallType() != null){
    22             //添加参数
    23             param.add(product.getSmallType().getId());
    24             sbHQL.append("AND smallType.id=? ");
    25         }
    26         //模糊搜索
    27         if(!StringTool.isEmpty(product.getName())){
    28             //添加参数
    29             param.add("%"+product.getName()+"%");
    30             sbHQL.append("AND name like ?");
    31         }
    32     }
    33     String hql = sbHQL.toString().replaceFirst("AND", "WHERE");
    34     //是否分页
    35     if(pageBean != null){
    36         return baseDao.find(hql, param, pageBean);
    37     } else{
    38         return baseDao.find(hql, param);
    39     }
    40 }

    2.关于json的一个技巧:可以写一个处理器来转换JSON中的一些对象。比如产品有一个日期属性,类型为java.util.Date。如果不重新处理这个日期,

    首先看一下应用场景:

     1 /**
     2  * 查询产品集合
     3  * @return
     4  * @throws Exception
     5  */
     6 public String list() throws Exception{
     7     //分页对象
     8     PageBean pageBean = new PageBean(page, Integer.parseInt(rows));
     9     //根据查询条件和分页对象查询产品集合
    10     List<Product> productList = productService.getProductList(product, pageBean);
    11     //产品总记录数
    12     long total = productService.getProductCount(searchProduct);
    13     
    14     //JSON配置
    15     JsonConfig config = new JsonConfig();
    16     //过滤掉的属性
    17     config.setExcludes(new String[]{"orderProductList"});
    18     JSONArray rows = JSONArray.fromObject(productList, config);
    19     JSONObject result = new JSONObject();
    20     result.put("rows", rows);
    21     result.put("total", total);
    22     //返回json字符串
    23     ResponseTool.write(ServletActionContext.getResponse(), result);
    24     System.out.println(result.toString());
    25     return null;
    26 }

    这里没有对产品的日期做处理,输出如下结果:"hotTime":{"date":1,"day":3,"hours":0,"minutes":0,"month":0,"nanos":0,"seconds":0,"time":1388505600000,"timezoneOffset":-480,"year":114}

    可以看到把Date类型直接按对象来解析了,这不是我们想要的。在以前我的处理办法是在Product里再添加一个String类型的日期字段,这种方法虽然可行,但其实不符合程序设计,用起来着实不爽O(∩_∩)O哈哈~。

    然后这次学到了,可以写一个处理器类,该类需要实现JSON的一个接口:net.sf.json.processors.JsonValueProcessor

    实现类如下:

     1 package com.lizhou.tools;
     2 
     3 import java.text.SimpleDateFormat;
     4 
     5 import net.sf.json.JsonConfig;
     6 import net.sf.json.processors.JsonValueProcessor;
     7 
     8 /**
     9  * json-lib 日期处理类
    10  * @author bojiangzhou
    11  *
    12  */
    13 public class DateJsonValueProcessor implements JsonValueProcessor{
    14 
    15     /**
    16      * 日期格式
    17      */
    18     private String format;  
    19     
    20     public DateJsonValueProcessor(String format){  
    21         this.format = format;  
    22     }  
    23     
    24     public Object processArrayValue(Object value, JsonConfig jsonConfig) {
    25         // TODO Auto-generated method stub
    26         return null;
    27     }
    28     
    29     public Object processObjectValue(String key, Object value, JsonConfig jsonConfig) {
    30         if(value == null)  
    31         {  
    32             return "";  
    33         }  
    34         if(value instanceof java.sql.Timestamp)  
    35         {  
    36             String str = new SimpleDateFormat(format).format((java.sql.Timestamp)value);  
    37             return str;  
    38         }  
    39         if (value instanceof java.util.Date)  
    40         {  
    41             String str = new SimpleDateFormat(format).format((java.util.Date) value);  
    42             return str;  
    43         }  
    44           
    45         return value.toString(); 
    46     }
    47 
    48 }

    然后只需注册该处理器即可:config.registerJsonValueProcessor(java.util.Date.class, new DateJsonValueProcessor("yyyy-MM-dd"));

     1 /**
     2  * 查询产品集合
     3  * @return
     4  * @throws Exception
     5  */
     6 public String list() throws Exception{
     7     //分页对象
     8     PageBean pageBean = new PageBean(page, Integer.parseInt(rows));
     9     //根据查询条件和分页对象查询产品集合
    10     List<Product> productList = productService.getProductList(product, pageBean);
    11     //产品总记录数
    12     long total = productService.getProductCount(searchProduct);
    13     
    14     //JSON配置
    15     JsonConfig config = new JsonConfig();
    16     //过滤掉的属性
    17     config.setExcludes(new String[]{"orderProductList"});
    18     //注册日期处理器
    19     config.registerJsonValueProcessor(java.util.Date.class, new DateJsonValueProcessor("yyyy-MM-dd"));
    20     JSONArray rows = JSONArray.fromObject(productList, config);
    21     JSONObject result = new JSONObject();
    22     result.put("rows", rows);
    23     result.put("total", total);
    24     //返回json字符串
    25     ResponseTool.write(ServletActionContext.getResponse(), result);
    26     System.out.println(result.toString());
    27     return null;
    28 }

    输出结果:"hotTime":"2014-01-01"

    同样的,也可以实现其它级联对象处理器,比如产品里有个BigType(大类别,有id,name,remark,productList),但我在显示产品列表时只需要大类别的名称和id,这时就可以写一个对象处理器。

    如下:

     1 package com.lizhou.tools;
     2 
     3 import java.beans.PropertyDescriptor;
     4 import java.lang.reflect.Method;
     5 
     6 import net.sf.json.JSONObject;
     7 import net.sf.json.JsonConfig;
     8 import net.sf.json.processors.JsonValueProcessor;
     9 
    10 /**
    11  * 解决对象级联问题
    12  * @author Administrator
    13  *
    14  */
    15 public class ObjectJsonValueProcessor implements JsonValueProcessor{
    16 
    17     /**
    18      * 保留的字段
    19      */
    20     private String[] properties;  
    21     
    22     /**
    23      * 处理类型
    24      */
    25     private Class<?> clazz;  
    26     
    27     /**
    28      * 构造方法 
    29      * @param properties
    30      * @param clazz
    31      */
    32     public ObjectJsonValueProcessor(String[] properties,Class<?> clazz){  
    33         this.properties = properties;  
    34         this.clazz =clazz;  
    35     }  
    36     
    37     public Object processArrayValue(Object arg0, JsonConfig arg1) {
    38         // TODO Auto-generated method stub
    39         return null;
    40     }
    41 
    42     public Object processObjectValue(String key, Object value, JsonConfig jsonConfig) {
    43         PropertyDescriptor pd = null;  
    44         Method method = null;  
    45         StringBuffer json = new StringBuffer("{");  
    46         try{  
    47             for(int i=0;i<properties.length;i++){  
    48                 pd = new PropertyDescriptor(properties[i], clazz);  
    49                 method = pd.getReadMethod();  
    50                 String v = String.valueOf(method.invoke(value));  
    51                 json.append("'"+properties[i]+"':'"+v+"'");  
    52                 json.append(i != properties.length-1?",":"");  
    53             }  
    54             json.append("}");  
    55         }catch (Exception e) {  
    56             e.printStackTrace();  
    57         }  
    58         return JSONObject.fromObject(json.toString());  
    59     }
    60 
    61 }

    同样,注册该处理器即可:

    1 config.registerJsonValueProcessor(ProductBigType.class, new ObjectJsonValueProcessor(new String[]{"name", "id"}, ProductBigType.class));
    2 config.registerJsonValueProcessor(ProductSmallType.class, new ObjectJsonValueProcessor(new String[]{"name", "id"}, ProductSmallType.class));

    *******************************************************************************************************************************************************************

    *******************************************************************************************************************************************************************

    总的来说就是这些,还有些比较细节的忘了,最大的收获就是经验还是得从实际项目中来....

    然后还遇到一个非常纠结的问题:那就是session的过期时间。场景是这样的,以前做项目的时候我在session中存的数据几乎是在10秒内就消失了,比如我存登录用户的信息(User对象)到session中,如果一直刷新页面不会消失,但停留几秒钟,再刷新一次,数据就消失了,但是session并没有销毁。以前百度过很多资料,包括修改session过期时间,都没用,也有说是tomcat的配置问题,我就懒得改了。

    直到做这个项目,我发现存在session中的登录用户信息、包括购物车里的数据同样是如此,过不了多久就消失了;但是存的其它的一些信息,比如字符串形式的数据,一直没有消失,在不关闭浏览器的情况下,那些数据一直都在;我就纠结了,难道消失的只是那些对象型数据?后面再找时间测试,如果你们知道问题所在,请告诉我,O(∩_∩)O谢谢!!!

     -------------------------------------------------------------------------------------------------------------

     附上源码:仅供学习,后台大部分没有做完!

    文件包含:

    地址:SSH商城系统(ebuy)

  • 相关阅读:
    65_磁盘文件的使用
    64_设备文件的使用
    63_json解析成map格式
    62_json文件解析成结构体格式
    61_map生成json的使用
    60_通过结构体生成json
    59_字符串的转换
    58_字符串的一些操作函数的使用
    57_recover的使用
    56_异常处理error,errors和painc的使用
  • 原文地址:https://www.cnblogs.com/chiangchou/p/project-ebuy.html
Copyright © 2011-2022 走看看