11、用Ajax时,弹出对话框的内容为乱码
原因:jsp文件的pageEncoding和js文件的pageEncoding不同,把它们改成相同就行了.
这里我们就要规范一下,在实际的开发过程中关于编码的问题要规范一下,由于我们用的是MyEclipse开发所以给我们提供了一个很好的统一的方法,所以我们在开发之前应该将所有文件的默认编码都改成一样的,这样的话在我们建文件的时候就不用去手动的修改pageEncoding以求所有文件的编码都相同.在这个项目初始我没有统一所有文件的编码方式,所以有时候就会出现乱码,之前jsp、html文件用的是gbk,后来想统一用UTF-8,因为原先用gbk创建的文件,所以改为UTF-8后网页中的中文就无法显示了,所以这里就告诉我们在项目初始就应该确统一文件的编码,推荐统一为UTF-8。
12、CSS格式的问题
今天在做表单验证提示信息的时候,想给提示信息的前面加一个图标,最后测试在FireFox中可以显示,在IE中就不能显示,最后终于弄出是什么原因了,下面是我没修改前的CSS文件中的内容:
#signup .wrong{
background:url(i/icons-signup.png)no-repeat
scroll 5px -47px transparent;
color:#CC6666;
}
这样不行,下面是我修改后的内容
#signup .wrong{
background:url(i/icons-signup.png) no-repea
t scroll 5px -47px transparent;
color:#CC6666;
}
看错有什么不同了吗?不同就在红色部分,要和前面有一个空格
多出了一个空格问题就解决了,这就可以总结了:如果出现这样的情况,就说明是CSS文件格式的问题,以后这方面要时刻注意,尽量写得规范些。
13、POJO
关于POJO的具体定义网络上有很多,但是都不是很准确,下面是我根据《精通Hibernate》这本书讲述理解的:
POJO在Hibernate语义中理解为数据库所对应的Domain Object(领域模型)。这里我们这样考虑,我们之所以要用Hibernate是因为我们想通过面向对象的方式来处理数据库操作,而不是像以前那样直接对数据库中的进行操作,由此就产生了一个问题,我们希望有一个事物来代替表,我们对这个事物进行操作,就间接地对表进行了操作,POJO就是这样的事物。
POJO中有一些private的参数作为对象的属性,对象类中的属性对应于数据库表中的字段。在运用中我们需要访问对象的属性,而对象的属性不能直接访问,POJO中针对每个参数定义了get和set方法作为访问的接口,我们就是通过这些方法来访问属性的。
上面的叙述,把POJO当成了PO来解释,实际上POJO并不仅仅是这样,下面是我觉得比较好的一篇解释POJO的:
POJO(Plain Old Java Object)这种叫法是Martin Fowler、Rebecca Parsons和Josh MacKenzie在2000年的一次演讲的时候提出来的。
我在做J2EE培训中发现我的很多学生问我什么是POJO,后来我在写书(《Spring2初学者实践教材》和《Spring3初学者实践教材》)的时候 发现POJO这个概念无法回避。现在网上对于POJO的解释很多,但是很多都是有错误的或者不够准确。对此我一开始也是存在误区的,我原来是这样理解的:
POJO是这样的一种“纯粹的”JavaBean,在它里面除了JavaBean规范的方法和属性没有别的东西,即private属性以及对这个属性方法的public的get和set方法。我们会发现这样的JavaBean很“单纯”,它只能装载数据,作为数据存储的载体,而不具有业务逻辑处理的能力。
所以下面的代码被认为是POJO了。
package com.tongking.spring;
public class DbHello implements Hello {
private DictionaryDAO dao;
public void setDao(DictionaryDAO dao) {
this.dao = dao;
}
}
其实,这样的认为是错误的,我仔细阅读了《POJOs in Action》这本书的有关部分和POJO的最原始的出处http://martinfowler.com/bliki/POJO.html,
The term was coined while Rebecca Parsons, Josh MacKenzie and I were preparing for a talk at a conference in September 2000. In the talk we were pointing out the many benefits of encoding business logic into regular java objects rather than using Entity Beans. We wondered why people were so against using regular objects in their systems and concluded that it was because simple objects lacked a fancy name. So we gave them one, and it''s caught on very nicely.
基本的意思是我们要给具有业务逻辑处理的规则的Java对象(regular java objects)起了一个名字——POJO,这些Java对象不是EntityBeans(EJB的一种)。
我又在http://www.webopedia.com/TERM/P/POJO.htm查到解释如下:
POJO, or Plain Old Java Object, is a normal Java object class (that is, not a JavaBean, EntityBean etc.) and does not serve any other special role nor does it implement any special interfaces of any of the Java frameworks. This term was coined by Martin Fowler, Rebbecca Parsons and Josh MacKenzie who believed that by creating the acronym POJO, such objects would have a "fancy name", thereby convincing people that they were worthy of use.
基本意思是说POJO一个正规的Java对象(不是JavaBean,EntityBean等),也不担当任何的特殊的角色,也不实现任何Java框架指定的接口。
我觉得上面的解释很准确,POJO应该不是我们开始认为的JavaBean,当然更不是EJB,它不应该依赖于框架即继承或实现某些框架类或接口。例 如:Struts1中的Action和ActionForm当然不属于POJO了,而在Struts2中的Action由于可以不继承任何的接口,所以在 这种情况下Action是POJO,但是Struts2中的Action也可以继承ActionSupport类就不再属于POJO了。POJO里面是可 以包含业务逻辑处理和持久化逻辑,也可以包含类似与JavaBean属性和对属性访问的set和get方法的。
最后,我们总结一下给一个定义把,POJO是一个简单的、正规Java对象,它包含业务逻辑处理或持久化逻辑等,但不是JavaBean、EntityBean等,不具有任何特殊角色和不继承或不实现任何其它Java框架的类或接口。
POJO的概念确实不怎么好理解,但是在Hibernate中我觉得真要引入POJO这个说法,我觉得解释成“数据库的领域模型”是比较准备的。我们写的领域模型,就是这种简单的、正规Java对象,不具有任何特殊觉得和不继承实现任何其他Java框架的或接口。所以在Hibernate中理解成”数据库的领域模型”很正确。
14、PO和VO
VO, 值对象(Value Object)
它是主要指用户提交的数据,如提交的表单数据,这些数据全部保存一个叫VO的类中。通常由一个VO可以对应多个PO(概念与POJO类似)
通常用于业务层之间的数据传递,和PO一样也是仅仅包含数据而已。但应是抽象出的业务对象,可以和表对应,也可以不,这根据业务的需要.
PO,持久对象(Persistent Object)
它们是由一组属性和属性的get和set方法组成。在o/r映射的时候出现的概念,如果没有o/r映射,没有这个概念存在了。通常对应数据模型(数据库),本身还有部分业务逻辑的处理。可以看成是与数据库中的表相映射的java对象。最简单的PO就是对应数据库中某个表中的一条记录,多个记录可以用PO的集合。PO中应该不包含任何对数据库的操作。
PO的属性是跟数据库表的字段一一对应的。PO对象需要实现序列化接口。
总结:在实际开发中理论上PO和VO是要分开使用各自干各自的事的,但是也不是说PO一定就不能当成VO用,我觉得大部分的时候还是把PO当成VO了,当然我们还是可以自定义一个business包把一些PO不能很好做到的交给这个包下的VO来使用,也就是说VO起到一个辅助的作用.
15、Hibernate映射类型
我们知道在使用Hibernate进行关系映射的时候,如果使用的是用映射文件进行映射需要指定一个type类型,我们也知道这个type类型既不是Java中的类型也不是标准的SQL类型,而是Hibernate的映射类型,那么为什么要引入这样的一个类型呢?我们知道Java中的类型是确定的,而不同的数据库中某种字段的存储类型却是不同的,比如MySQL表示字符串类型用varchar,而Oracle用varchar2类型。这种类型的不同我们使用的JDBC驱动来完成,它会把这些底层的类型转换成标准的SQL数据类型,我们只要提供一个桥梁来实现Java数据类型和标准SQL数据类型的相互映射就行了,而Hibernate自定义的映射类型就是这样的一个桥梁。
16、MyEclipse逆向工程
项目的开发过程中关于是先建表再写实体类还是先写实体类再建表的问题不同人有不同的看法,同时两种方法利用MyElipse强大的正向和逆向功能都可以很好的实现,不过我个人还是倾向于先建表再通过MyEclipse的逆向功能生成实体类。具体的如何操作在这里我就不用说了,网上都有,我要说的是SSH整合中的具体操作。
首先我的jar是我搭建SSH框架的时候自己导入进去的,而且没有hibernate.cfg.xml配置文件,配置文件的信息我都写到了Spring的配置为文件中。现在具体来说一下从表生成映射实体的过程:
第一步:打开MyEclipse Hibernate视图后,右键需要生成实体类的表,选择Hibernate
Reverse Engineering。
第二步:
这里因为我是用annotation的方式所以选择Add Hiberante mapping annotations to POJO
同时要注意了Create abstract class这个选项不要选
第三步:这里要注意一下三点:
Type Mapping选择Hibernate Types
Id Generator 自己选择
Generate version and timestamp tags这个选项选上
我上面是已经用这个生成了实体类所以后面没有要选择生成配置文件之类的,如果要选择就直接选Spring中有hibernate配置信息的文件即可,具体视情况而定。
17、关于编写DAO接口
DAO接口的作用在这里就不再介绍了,我要说的是如何更好地书写一个DAO组件,下面是我想存储一个用户而在DAO接口中定义的一个抽象方法:
/** * 新增用户 * @param email 用户的email * @param username 用户名 * @param password 用户密码 * @param mobile 用户手机号码 * @param city_id 城市 */ public void addUser(String email,String username,String password,String mobile,Integer city_id);
我的目的就是把这些内容存储到数据库中,当然我也是严格根据大型项目开发的要求进行分层,我有一个service包,这个包就是业务逻辑组件包,比如我有一个业务就是注册用户那么我就会在我的service组件中调用这个DAO组件,但是我们仔细想一想这样写DAO接口是不是好,其实这样写是不好的,为什么?因为假如我们需要录入的信息中多了一项,那么我们在修改service组件后还要在修改这个DAO接口的这个方法,这样就很麻烦,实际的项目开发中我们是这样做的:DAO接口中的参数尽量让它都是对象,我们面向对象进行操作,比如上面的按照这个思想就写成:
/** * 新增用户 */ public void addUser(User user);
这样当我们的业务逻辑发生变化的时候,只需要修改业务逻辑层就行了而不需要修改DAO层。
DAO组件用于操作特定的持久化实体,用户实现对特定实体的增加、删除和修改等操作。除此之外,DAO组件还包含了数量不等的查询方法,这些查询方法往往根据系统的业务需要确定。
18、用Hibernate时关于字段default值的处理
我在建数据库的时候,对于一些字段设成非空的,而且设置了默认值,用MyEclipse的反向工程生成实体类的时候是类似这样的:
@Column(name = "city_id",nullable=false) public Integer getCityId() { return this.cityId; } public void setCityId(Integer cityId) { this.cityId = cityId; }
这里多了个nullable的属性,当我保存实体的时候,我也像一般那样的操作,不给那些有默认值的字段设置值,结果却报错了:
org.springframework.dao.DataIntegrityViolationException: not-null property references a null or transient value: com.zuwoba.model.User.cityId; nested exception is org.hibernate.PropertyValueException: not-null property references a null or transient value: com.zuwoba.model.User.cityId
为什么会有这样的错误,那是因为你以为这样做也可以帮你设置默认值,而实际上不是这样,数据库中设置默认值只是只当你插入数据到数据库之后如果这个字段没有值那么数据库就会自动帮你设置成默认值,这个操作是在数据库层次上来说的,而上面的定义nullable=false,是指保存实体的时候需要检查的条件,这是在Hibernate层来说的,所以因为没有设置值,这个条件就不能通过,所以就会报错。那么怎么解决了,以下有三种方法解决:
将这里的nullable属性去掉
在Hibernate层设置默认值,这样设置:
private Integer cityId=0;
还是在Hibernate层设置默认值,这样设置
@Column(name = “cityid”, nullable = false, columnDefinition = “int default 0")
以上是解决这个问题的三个方法,第三个方法没时候,不过觉得不是很好,解决这个方法我觉得最好的还是第一个方法,在实际的开发过程中采用第一个方法。解决这个问题的文摘:
If you want a real database default value, use columnDefinition - @Column(name = “myColumn”, nullable = false, columnDefinition = “int default 100"). Notice that the string in columnDefinition is database dependent. Also if you choose this option, you have to use dynamic-insert, so Hibernate doesn't include columns with null values on insert. Otherwise talking about default is irrelevant. But if you don't want database default value, but simply a default value in your Java code, just initialize your variable like that - private Integer myColumn = 100;
19、关于日期在数据库中的存储
在这个项目的原型中,它在设计数据库的时候对于日期的存储并不是像通常那样用date、time或timestamp来存储而是用int来存储。刚开始没弄懂其中的缘由,现在清楚了,其实它用到到Unix Timestamp这样的时间表示方式,看看下面一段话:
Representing points in time by UNIX time In IT systems we sometimes need to refer to precise points in time. Examples are: • When was a file last modified • Start of an appointment • When an email was sent These points in time have the characteristics of an event. If two events have the same time stamp they occurred in the very same moment. It doesn't matter if one occurs in Shanghai and the other in London: they still occur in the very same moment. Independent of any time zone. We usually use UNIX time to represent points in time. UNIX time stamps are the number of seconds that have elapsed since midnight 1.1.1970 UTC. Uh... here appears a "date". Never mind, we'll get to that in a minute. Java's java.util.Date class effectively encapsulates a UNIX time stamp. It represents a point in time by a millisecond counter in a 64 bit long variable. While 32 bit representation on UNIX will overflow in 2038 the 64 bit signed long will last for roughly another 18 billion years. Please note that the all the deprecated methods and constructors of the Date class should never be used. They are from a time when the Sun people were confused about time themselves. javax.management.timer.Timer has some convenient constants for the most used millisecond values.
上面提到了用这样表示的好处:Independent of any time zone.
下面的例子就是普通时间和Unix Timestamp互换方法:
Timestamp timestamp=new Timestamp(System.currentTimeMillis()/1000); System.out.println(timestamp.getTime()); String date = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new java.util.Date(timestamp.getTime() * 1000)); System.out.println(date);
在这里面要注意的是,System.currentTimeMillis()返回的是毫秒数,而Timestamp需要表示的是秒数,所以就像上面一样进行了一个转换。
20、邮件的收发
下面是普通的JavaProject发送邮件的方式:
package javamail; import java.util.Properties; import javax.mail.Address; import javax.mail.Message; import javax.mail.Session; import javax.mail.Transport; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; public class Demo1 { /** * @param args add by zxx ,Feb 5, 2009 */ public static void main(String[] args) throws Exception{ // TODO Auto-generated method stub Properties props = new Properties(); props.setProperty("mail.smtp.auth", "true"); props.setProperty("mail.transport.protocol", "smtp"); Session session = Session.getInstance(props); session.setDebug(true); Message msg = new MimeMessage(session); msg.setText("你好吗?"); msg.setFrom(new InternetAddress("[email protected]")); Transport transport = session.getTransport(); transport.connect("smtp.sina.com", 25, "tianhandigeng", "14981498"); transport.sendMessage(msg, new Address[]{new InternetAddress("[email protected]")}); //transport.send(msg,new Address[]{new InternetAddress("[email protected]")}); transport.close(); } }
这里面有几个问题
1、 msg.setFrom(new InternetAddress("[email protected]"));
这里的邮件地址必须是真实的,而且是你登陆的那个SMTP服务器的邮件地址,看视频的时候这个地址说是可以任意的,但是自己尝试了不行,我觉得原因可能是这些SMTP服务器升级了,不是自己服务器的账号无法发送邮件.
2、 transport.connect("smtp.sina.com", 25, "tianhandigeng", "14981498");
这里的用户名和密码是你的邮箱登陆的用户名和密码.
例外一种写法:
package javamail; import java.util.Properties; import javax.mail.Address; import javax.mail.Authenticator; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.PasswordAuthentication; import javax.mail.Session; import javax.mail.Transport; import javax.mail.Message.RecipientType; import javax.mail.internet.AddressException; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; public class Demo2 { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub Properties props=new Properties(); props.setProperty("mail.smtp.auth","true"); props.setProperty("mail.transport.protocol","smtp"); props.setProperty("mail.host", "smtp.sina.com"); Session session=Session.getDefaultInstance(props, new Authenticator(){ protected PasswordAuthentication getPasswordAuthentication(){ return new PasswordAuthentication("tianhandigeng","14981498"); } } ); try { Message msg=new MimeMessage(session); msg.setFrom(new InternetAddress("[email protected]")); msg.setSubject("中文主题"); msg.setRecipients(RecipientType.TO, InternetAddress.parse("[email protected],[email protected]")); msg.setContent("<span style='color:red'>呵呵</span>", "text/html;charset=gbk"); Transport.send(msg); } catch (AddressException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } catch (MessagingException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } }
下面发是另外一种发送邮件的方式,它的思想是不在程序内部利用代码的方式创建邮件文件,而是首先用邮件客户端软件生成一个邮件文件(*.eml),然后再在程序中发送这个文件。
package javamail; import java.io.FileInputStream; import java.util.Properties; import javax.mail.Address; import javax.mail.Authenticator; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.PasswordAuthentication; import javax.mail.Session; import javax.mail.Transport; import javax.mail.Message.RecipientType; import javax.mail.internet.AddressException; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; public class Demo4 { /** * @param args */ public static void main(String[] args) throws Exception { // TODO Auto-generated method stub Properties props=new Properties(); props.setProperty("mail.smtp.auth","true"); props.setProperty("mail.transport.protocol","smtp"); props.setProperty("mail.host", "smtp.sohu.com"); Session session=Session.getDefaultInstance(props, new Authenticator(){ protected PasswordAuthentication getPasswordAuthentication(){ return new PasswordAuthentication("tianhandigeng","14981498"); } } ); session.setDebug(true); Message msg=new MimeMessage(session,new FileInputStream("E:\\demo\\demo.eml")); Transport.send(msg,InternetAddress.parse("[email protected],[email protected],[email protected]")); } }
下面是手工地创建一个邮件的例子
package javamail; import java.io.FileOutputStream; import java.io.OutputStream; import java.util.Properties; import javax.activation.DataHandler; import javax.activation.DataSource; import javax.activation.FileDataSource; import javax.mail.Address; import javax.mail.Session; import javax.mail.Message.RecipientType; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeBodyPart; import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMultipart; import javax.mail.internet.MimeUtility; public class Demo3 { /** * @param args */ public static void main(String[] args) throws Exception { // TODO Auto-generated method stub Session session=Session.getInstance(new Properties()); MimeMessage msg=new MimeMessage(session); msg.setFrom(new InternetAddress(" \" " +MimeUtility.encodeText("胡学汪")+ " \" <[email protected]>")); msg.setSubject("你们的Java很牛吗"); msg.setReplyTo(new Address[]{new InternetAddress("[email protected]")});//答复 msg.setRecipients(RecipientType.TO,InternetAddress.parse(MimeUtility.encodeText("胡学汪")+" <[email protected]>,"+MimeUtility.encodeText("胡学汪")+"<[email protected]>")); MimeMultipart msgMultipart=new MimeMultipart("mixed"); msg.setContent(msgMultipart); MimeBodyPart attch1=new MimeBodyPart(); MimeBodyPart attch2=new MimeBodyPart(); MimeBodyPart content=new MimeBodyPart(); msgMultipart.addBodyPart(attch1); msgMultipart.addBodyPart(attch2); msgMultipart.addBodyPart(content); DataSource ds1=new FileDataSource( "E:\\demo\\JavaMailSender.java" ); DataHandler dh1=new DataHandler(ds1); attch1.setDataHandler(dh1); attch1.setFileName( MimeUtility.encodeText("中文名.java") ); DataSource ds2=new FileDataSource( "E:\\demo\\pic.jpg" ); DataHandler dh2=new DataHandler(ds2); attch2.setDataHandler(dh2); attch2.setFileName("pic.jpg"); MimeMultipart bodyMultipart=new MimeMultipart("related"); content.setContent(bodyMultipart); MimeBodyPart htmlPart=new MimeBodyPart(); MimeBodyPart gifPart=new MimeBodyPart(); bodyMultipart.addBodyPart(htmlPart); bodyMultipart.addBodyPart(gifPart); DataSource gifds=new FileDataSource("E:\\demo\\pic.jpg"); DataHandler gifdh=new DataHandler(gifds); gifPart.setDataHandler(gifdh); gifPart.setHeader("Content-Location","http://www.itcast.cn/logo.gif"); htmlPart.setContent("<a href='www.baidu.com'>百度</a>你们的Java培训真的是最牛的吗?大家都这么说,我想跟你们比试一下!这可是我自己用程序生成和发送的邮件哦!<img src='http://www.itcast.cn/logo.gif'>" , "text/html;charset=gbk"); msg.saveChanges(); OutputStream ips=new FileOutputStream("E:\\demo\\demo.eml"); msg.writeTo(ips); ips.close(); } }
Web应用中的邮件收发
第一种方法:自己创建Session
第二种方法:让Tomcat帮助我们创建Session,我们从JNDI容器中获得Session
在这里先讲第二种方法:
将mail.jar包拷入Tomcat的lib文件夹下
在Web Project的META-INF下建文件context.xml
<Context> <Resource name="mail/Dog" auth="Container" type="javax.mail.Session" mail.smtp.host="smtp.sina.com" mail.smtp.auth="true" mail.transport.protocol="smtp" /> </Context>
1、 第三步在servlet(或其他)中操作
package cn.itcast.javamail3.web.mail.servlets; import java.io.IOException; import java.io.PrintWriter; import javax.mail.Message; import javax.mail.Session; import javax.mail.Transport; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; import javax.naming.Context; import javax.naming.InitialContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import cn.itcast.javamail2.Demo2; public class SendMailServlet extends HttpServlet { /** * The doGet method of the servlet. <br> * * This method is called when a form has its tag value method equals to get. * * @param request the request send by the client to the server * @param response the response send by the server to the client * @throws ServletException if an error occurred * @throws IOException if an error occurred */ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } /** * The doPost method of the servlet. <br> * * This method is called when a form has its tag value method equals to post. * * @param request the request send by the client to the server * @param response the response send by the server to the client * @throws ServletException if an error occurred * @throws IOException if an error occurred */ public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { //Demo2.main(new String[]{}); Context initCtx = new InitialContext(); Context envCtx = (Context) initCtx.lookup("java:comp/env"); Session session = (Session) envCtx.lookup("mail/Dog"); Message message = new MimeMessage(session); message.setFrom(new InternetAddress("[email protected]")); InternetAddress to[] = new InternetAddress[1]; to[0] = new InternetAddress("[email protected]"); message.setRecipients(Message.RecipientType.TO, to); message.setSubject("ha"); message.setText("test"); //Transport.send(message); Transport transport = session.getTransport(); transport.connect("smtp.sina.com", "itcast_test", "123456"); transport.sendMessage(message, to); transport.close(); response.getWriter().print("ok!"); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(response.getWriter()); } } }
-----未完待续--------