您的位置:首页 > 运维架构 > 网站架构

公司网站项目遇到的问题

2008-07-23 10:18 253 查看
1. hibernate.cfg.xml配置文件直接写在WEB-INF下,spring的配置文件报错说找不到hibernate.cfg.xml(文件路径配置为)
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="configLocation">
<value>classpath:hibernate.cfg.xml</value>
</property>
</bean>
可能是classpath的问题,把hibernate.cfg.xml改放在WEB-INF/classes/目录下就行了。同样的,log4j.properties也不要直接放在WEB-INF/下,可以放在WEB-INF/classes/下。

2. PO的Id属性不用给它赋值,我在程序中用了po.setId(vo.getId()),始终报NullPointerException异常,但是po,vo都已经new出来了的,后来去掉这条语句后才没有出现异常。我配置的Id为auto_increment。

3. 我用MyEclipse生成的dao调用getHibernateTemplate().sava()方法始终不能自动提交事务,但我在spring的配置文件中声明了事务管理的,最后通过在CSDN上提问才解决,原来是业务逻辑组件Service依赖的DAO应该配置成DAOProxy。最开始解决的办法是在自动生成的hibernate.cfg.xml文件中加上<property name="connection.autocommit">true </property>,其实这样任然没有用到Spring的声明式事务处理,它是每执行一个操作,就自动提交事务。另外,用了代理类时必须实现接口,否则需要使用CGlib,即通过JDK自动帮我们实现接口。

4. Spring和Struts的集成。我用的是WebApplicationContextUtils类从ServletContext中获得WebApplicationContext对象的实例,然后再注入Bean,还要注意web.xml配置。这是一般要自己定义一个BaseAction,让它继承自Action或DispatchAction,覆盖setServlet()方法,并注入需要的DAO,然后将作为控制器的Action继承BaseAction,这样就集成好了Spring。

5. Hibernate中,id一般作为代理主键,没有实际意义。如果表中本身有主键,可以把该字段的约束设置为unique,表示该字段是唯一的。

6. 当把对一个PO对象的CRUD操作都放在一个Action中时,要用DispatchAction,如果需要多个input属性,则要配置多个<action>,这些<action>的path不同,type相同。这样就能为不同的行为指定不同的“action”,自然就可以使用不同的input,分别指定validate是true或者false, 甚至可以使用不同的ActionForm。

7. 在程序中,尝试了抛出异常的方法。我定义了一个validate ()方法,当用户名不存在是抛出NameNotFoundException,当密码错误时,抛出PasswordErrorExcepion,然后在调用该validate ()方法时,要用try-catch,在catch中处理用户名不存在和密码错误的操作。

8. 用log4j记录日志,详细记录了操作了数据库时的日志。如用户登录时,登录是否成功,密码是否正确都以日志的形式记录下来了。这样以后可以查看谁在尝试登录系统。

9. 想log4j.properties,MessageResource.properties等文件中不允许出现中文,可以用native2ascii工具实现转换,或者在MyEclipse中通过设计视图Design中编辑实现转换。

10. 熟悉ActionErrors,ActionMessages,<html:errors>,的用法,如果在Acton中添加Errors,则需要在添加后saveErrors(),因为<html:errors>输出错误是在request范围内,而forward后request并没有变化。

11. request.setAttribute().当添加成功操作完成后,希望在转向后的页面输出“添加成功”信息。可以在sava()后面加上一句request.setAttribute("addSuccess","添加成功");然后在转向后的页面调用out.println("request.getAttribute("addSuccess")");也可以用弹出对话框的方式。

12. 如果用了DispatchAction,那么可能在这个Action中会有许多方法,但是在配置文件中不要每个<action>都配置它的name属性,即将这个<action>关联一个form,特别是用了验证框架的时候,否则会因为本来该<action>不需要form,但是验证框架发现form的每个字段都为空,然后转向input的页面。

13. 一般情况下,如果要通过Hibernate来update一个PO,要先get该PO对象,然后再update,而不是直接给PO对象赋一个值(包括id),认为修改的对象就是id所唯一决定的PO.要注意PO对象的生命周期,持久状态的PO才能update。
但是spring的HibernateTemple.update()就可以直接修改没有get过的PO对象,只要PO的id是已经在数据库中存在的就行了。

14. 遇到异常或错误是要仔细阅读异常报告,不要乱猜错在什么地方,多读两边有助于快速拍错。

15. 数据库的日期的字段一般不要设置为非空,特别是日期为创建的当前日期时,不然在程序中没有注意赋值会经常导致异常。

16. 在updateAdmin中,验证框架规定了adminForm的name和password属性不能超过4个字符,但是validate()方法返回后request.setAttribute()设置的属性就失效了,为了在validate()后任然有效,需要重写validate()方法,并在其中调用request.setAttribute()。

17. 在web.xml中,<filter-mapping>的子元素<filter-name>如果对应多个<url-pattern>,则它只关联最后一个<url-pattern>,而不是每个<url-pattern>都关联。如:
<filter-mapping>
<filter-name>AdminCheckFilter</filter-name>
<url-pattern>/admin/index*</url-pattern>
<url-pattern>/admin/newsList.jsp</url-pattern>
<url-pattern>/admin/productList.jsp</url-pattern>
</filter-mapping>
与过滤器AdminCheckFilter关联的是最后一个<url-pattern>/admin/productList.jsp</url-pattern>,如果一个过滤器想关联多个url,可以这样:
<filter-mapping>
<filter-name>AdminCheckFilter</filter-name>
<url-pattern>/admin/index.jsp</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>AdminCheckFilter</filter-name>
<url-pattern>/admin/newsList.jsp</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>AdminCheckFilter</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
即写过个<filter-mapping>,其中<filter-name>相同,而<url-pattern>就可以了。
另外还要注意通配符*的使用,*好像只能出现在第一个字母,像<url-pattern>*.do</url-pattern>,而类似于<url-pattern>/admin/*.jsp</url-pattern>,<url-pattern>/*List.jsp</url-pattern>这样的都不行,但<url-pattern>*.*</url-pattern>又可以。

18. 如果用struts从action中返回到forward指向的页面出了乱码问题,在action中加一句request.removeAttribute(mapping.getAttribute());这样可以解决。

19. 用过滤器时,如果请求页面被拦截后采用的转发方式为RequestDispatcher,且登录页面所在的目录下有子目录,那么登录提交的action最好不要用相对路径,如:<form action="adminLogin.do"...>,这样的话访问子目录的页面被过滤器拦截后返回的地址就位于子目录下了。所以要采用绝对路径(相对应Web应用程序的路径)。如:<form action="<%=request.getContextPath()%>/admin/adminLogin.do">

20. 如果数据库的一个字段设为非空,再给它一个默认值是没有意义的,因为非空意味着你在新增一个记录时必须给它赋值。同样在hibernate中如果设置了not-null,再给它一个default也是没有用的。

21. 如果在创建数据库表时设置了默认值(即使用了default关键字),并且要想通过Hibernate写入数据时把空字段自动赋值为指定的默认值,需要在xxx.hbm.xml文件的class子元素中加上属性dynamic-insert="true"。

22. 本项目中,为了对Struts解耦,特别区分了PO和VO(ActionForm),因此在程序中经常出现PO和VO之间的相互转换。为此,定义了一个工具类BeanUtils,专门负责PO和VO的转换。但是在修改操作中,如果ActionForm遇到一些不在表单中出现的属性,如ClickTimes(点击次数),那么直接把VO复制给PO会使这些属性对应的表字段成为空值。要解决这个问题,需要在BeanUtils类的转换方法中注意,赋值时要先判断这些不出现的属性是否为空,为空就不赋值,不为空才赋值。另外在Action中,调用BeanUtils转换方法前要先得到PO对象。

23. 本项目中,很多数据库表的name字段都有unique约束。在设计程序时,使用了抛出异常的方法来解决name字段重复的问题public void addAdmin(Admin admin) throws NameAlreadyExistsException {
String name = admin.getName();
Admin adminPO = adminDAO.findByName(name);
if(null != adminPO) { //判断用户名是否已存在
log.error("添加管理员失败,用户名" + name + "已存在");
throw new NameAlreadyExistsException();
}
adminDAO.save(admin);
}
这段代码就是添加管理员的操作。但这段代码不能用于修改操作,如果用户只想修改密码等字段,而用户名不修改,程序会报异常。可以这样修改:
public void updateAdmin(Admin admin) throws NameAlreadyExistsException {
try {
adminDAO.update(admin);
} catch (Exception e) {
log.error("修改管理员失败,用户名" + admin.getName() + "已存在");
throw new NameAlreadyExistsException();
}
}
这样修改也不是最好的办法,因为其中用到了系统异常ConstraintViolationException,并且虽然在程序中捕获了异常,但在控制台任然要打印异常报告。改进的办法是仿照第一种:
public void updateAdmin(Admin admin) throws NameAlreadyExistsException {
String name = admin.getName();
Admin adminPO = adminDAO.findByName(name);
if(null != adminPO && admin.getId() != adminPO.getId()) { //用户名已修改且用户名已存在
log.error("修改管理员失败,用户名" + name + "已存在");
throw new NameAlreadyExistsException();
}
adminDAO.update(admin);
}

24. 自己写ValidatorForm的validate()方法的时候:
@Override
public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {
// TODO Auto-generated method stub
request.setAttribute("admin", this); //把当前vo写入request,以便在input属性对应的页面访问,这句非常重要
return super.validate(mapping, request);
}
如果用了Validator框架,在修改操作的时候,如果修改操作的表单里有非法字段,则要返回到input属性指定的页面,而input属性指定的页面又调用了request.getAttribute()方法,这是就需要在validate()方法中写上request.setAttribute(),否则出错。
但如果用的是session而不是request,就没有必要重写validate()。

25. request.setAttribute("","");
用这个传值,必须是从上一个请求到下一个请求是转发请求(forward),而不能是重定向请求(redirect)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: