J2EE项目异常处理(转)
public String getPassword(String userId)throws DataAccessException{
String sql = “select password from userinfo where userid=’”+userId +”’”;
String password = null;
Connection con = null;
Statement s = null;
ResultSet rs = null;
try{
con = getConnection();//获得数据连接
s = con.createStatement();
rs = s.executeQuery(sql);
while(rs.next()){
password = rs.getString(1);
}
rs.close();
s.close(); }
Catch(SqlException ex){
throw new DataAccessException(ex);
}
finally{
try{
if(con != null){
con.close();
}
}
Catch(SQLException sqlEx){
throw new DataAccessException(“关闭连接失败!”,sqlEx);
}
}
return password;
}
可以看出Java的异常处理机制具有的优势:
public String getPassword(String userId){
try{
……
Statement s = con.createStatement();
……
Catch(SQLException sqlEx){
……
}
……
}
或者
public String getPassword(String userId)throws SQLException{
Statement s = con.createStatement();
}
(当然,像Connection,Satement这些资源是需要及时关闭的,这里仅是为了说明checked 异常必须强制调用者进行捕获或继续抛出)
String str = “123”;
int value = Integer.parseInt(str);
parseInt的方法签名为:
public static int parseInt(String s) throws NumberFormatException
当传入的参数不能转换成相应的整数时,将会抛出NumberFormatException。因为NumberFormatException扩展于RuntimeException,是unChecked异常。所以调用parseInt方法时无需要try…catch
try{
……
Statement s = con.createStatement();
……
Catch(SQLException sqlEx){
sqlEx.PrintStackTrace();
}
或者
try{
……
Statement s = con.createStatement();
……
Catch(SQLException sqlEx){
//什么也不干
}
checked异常导致了许多难以理解的代码产生
public void methodA()throws ExceptionA{
…..
throw new ExceptionA();
} public void methodB()throws ExceptionB{
try{
methodA();
……
}catch(ExceptionA ex){
throw new ExceptionB(ex);
}
} Public void methodC()throws ExceptinC{
try{
methodB();
…
}
catch(ExceptionB ex){
throw new ExceptionC(ex);
}
}
我们看到异常就这样一层层无休止的被封装和重新抛出。
如
IllegalArgumentException, UnsupportedOperationException
不管是新的异常是chekced异常还是unChecked异常。我们都必须考虑异常的嵌套问题。
public void methodA()throws ExceptionA{
…..
throw new ExceptionA();
}
public void methodB()throws ExceptionB{
try{
methodA();
……
}catch(ExceptionA ex){
throw new ExceptionB(ex);
}
}
public Class ExceptionB extends Exception{
private Throwable cause; public ExceptionB(String msg, Throwable ex){
super(msg);
this.cause = ex;
} public ExceptionB(String msg){
super(msg);
} public ExceptionB(Throwable ex){
this.cause = ex;
}
}
public void printStackTrace(PrintStrean ps){
if(cause == null){
super.printStackTrace(ps);
}else{
ps.println(this);
cause.printStackTrace(ps);
}
}
public NestedException extends Exception{
private Throwable cause;
public NestedException (String msg){
super(msg);
} public NestedException(String msg, Throwable ex){
super(msg);
This.cause = ex;
} public Throwable getCause(){
return (this.cause == null ? this :this.cause);
} public getMessage(){
String message = super.getMessage();
Throwable cause = getCause();
if(cause != null){
message = message + “;nested Exception is ” + cause;
}
return message;
}
public void printStackTrace(PrintStream ps){
if(getCause == null){
super.printStackTrace(ps); }else{
ps.println(this);
getCause().printStackTrace(ps);
}
} public void printStackTrace(PrintWrite pw){
if(getCause() == null){
super.printStackTrace(pw);
}
else{
pw.println(this);
getCause().printStackTrace(pw);
}
}
public void printStackTrace(){
printStackTrace(System.error);
}
}
public String getPassword(String userId)throws NoSuchUserException{
UserInfo user = userDao.queryUserById(userId);
If(user == null){
Logger.info(“找不到该用户信息,userId=”+userId);
throw new NoSuchUserException(“找不到该用户信息,userId=”+userId);
}
else{
return user.getPassword();
}
} public void sendUserPassword(String userId)throws Exception {
UserInfo user = null;
try{
user = getPassword(userId);
//……..
sendMail();
//
}catch(NoSuchUserException ex)(
logger.error(“找不到该用户信息:”+userId+ex);
throw new Exception(ex);
}
我们注意到,一个错误被记录了两次.在错误的起源位置我们仅是以info级别进行记录。而在sendUserPassword方法中,我们还把整个异常信息都记录了。
笔者曾看到很多项目是这样记录异常的,不管三七二一,只有遇到异常就把整个异常全部记录下。如果一个异常被不断的封装抛出多次,那么就被记录了多次。那么异常倒底该在什么地方被记录?
异常应该在最初产生的位置记录! 如果必须捕获一个无法正确处理的异常,仅仅是把它封装成另外一种异常往上抛出。不必再次把已经被记录过的异常再次记录。 如果捕获到一个异常,但是这个异常是可以处理的。则无需要记录异常 java 代码
public Date getDate(String str){
Date applyDate = null;
SimpleDateFormat format = new SimpleDateFormat(“MM/dd/yyyy”);
try{
applyDate = format.parse(applyDateStr);
}
catch(ParseException ex){
//乎略,当格式错误时,返回null
}
return applyDate;
}
捕获到一个未记录过的异常或外部系统异常时,应该记录异常的详细信息
try{
……
String sql=”select * from userinfo”;
Statement s = con.createStatement();
……
Catch(SQLException sqlEx){
Logger.error(“sql执行错误”+sql+sqlEx);
}
public class BusinessException extends Exception {
private void logTrace() {
StringBuffer buffer=new StringBuffer();
buffer.append("Business Error in Class: ");
buffer.append(getClassName());
buffer.append(",method: ");
buffer.append(getMethodName());
buffer.append(",messsage: ");
buffer.append(this.getMessage());
logger.error(buffer.toString()); }
public BusinessException(String s) {
super(s);
race();
}
//
public class UserSoaImpl implements UserSoa{
public UserInfo getUserInfo(String userId)throws RemoteException{
//……
远程方法调用.
//……
}
}
public interface UserManager{
public UserInfo getUserInfo(Stirng userId)throws RemoteException;
}
同样JDBC访问都会抛出SQLException的checked异常。
public DataAccessException extends RuntimeException{
……
}
public interface UserDao{
public String getPassword(String userId)throws DataAccessException;
} public class UserDaoImpl implements UserDAO{
public String getPassword(String userId)throws DataAccessException{
String sql = “select password from userInfo where userId= ‘”+userId+”’”;
try{
…
//JDBC调用
s.executeQuery(sql);
…
}catch(SQLException ex){
throw new DataAccessException(“数据库查询失败”+sql,ex);
}
}
}
定义一个checked的业务异常,让业务层的接口的所有方法都声明抛出Checked异常.
public class BusinessException extends Exception{
…..
} public interface UserManager{
public Userinfo copyUserInfo(Userinfo user)throws BusinessException{
Userinfo newUser = null;
try{
newUser = (Userinfo)user.clone();
}catch(CloneNotSupportedException ex){
throw new BusinessException(“不支持clone方法:”+Userinfo.class.getName(),ex);
}
}
}
J2ee表示层应该是一个很薄的层,主要的功能为:获得页面请求,把页面的参数组装成POJO对象,调用相应的业务方法,然后进行页面转发,把相应的业务数据呈现给页面。表示层需要注意一个问题,表示层需要对数据的合法性进行校验,比如某些录入域不能为空,字符长度校验等。
ModeAndView handleRequest(HttpServletRequest request,HttpServletResponse response)throws Exception{
String ageStr = request.getParameter(“age”);
int age = Integer.parse(ageStr);
………… String birthDayStr = request.getParameter(“birthDay”);
SimpleDateFormat format = new SimpleDateFormat(“MM/dd/yyyy”);
Date birthDay = format.parse(birthDayStr); }
上面的代码应该经常见到,但是当用户从页面录入一个不能转换为整型的字符或一个错误的日期值。
ModeAndView handleRequest(HttpServletRequest request,HttpServletResponse response)throws Exception{
String ageStr = request.getParameter(“age”);
String birthDayStr = request.getParameter(“birthDay”);
int age = 0;
Date birthDay = null;
try{
age=Integer.parse(ageStr);
}catch(NumberFormatException ex){
error.reject(“age”,”不是合法的整数值”);
}
………… try{
SimpleDateFormat format = new SimpleDateFormat(“MM/dd/yyyy”);
birthDay = format.parse(birthDayStr);
}catch(ParseException ex){
error.reject(“birthDay”,”不是合法的日期,请录入’MM/dd/yyy’格式的日期”);
} }
在表示层一定要弄清楚调用方法的是否会抛出unChecked异常,什么情况下会抛出这些异常,并作出正确的处理。
J2EE项目异常处理(转)的更多相关文章
- J2EE项目中异常处理
为什么要在J2EE项目中谈异常处理呢?可能许多java初学者都想说:“异常处理不就是try….catch…finally吗?这谁都会啊!”.笔者在初学java时也是这样认为的.如何在一个多层的j2e ...
- J2EE项目中后台定时运行的程序
转自:http://www.2cto.com/kf/201311/260676.html 在开发J2EE项目中,有时候需要在后台定时执行一些代码. 比如定时对web数据建立倒排索引.定时发送邮件.定时 ...
- 如何正确的将J2ee项目部署到Tomcat
如何正确的将J2ee项目部署到Tomcat 1.打开配置文件(我的如下:C:\Program Files\Apache Software Foundation\Tomcat 7.0\conf\serv ...
- eclipse配置j2ee项目
1.下载jdk (1.5,1.6) 安装 从sun的官方网站下载,我下的是jdk-1_5_0_19-nb-6_5_1-windows-ml.exe,集成netbean的版本,下载后一路默认安装. 配置 ...
- Maven构建真正的J2EE项目
今天同事问起我眼下用Maven构建的多模块项目架构和曾经用Eclipse创建的Web项目的问题.以下将讲一下使用maven搭建多模块的J2ee项目,以及採用这样的方式搭建项目对日后项目的水平拆分和垂直 ...
- J2EE项目集成SAP的BO报表
网上的方案: 每个用户在自己的J2EE系统的用户登陆的同时登陆bo系统,这做法的缺点是登陆bo速度慢,而且如果J2EE用户比较多的话会在bo服务器生成很多的token. 最佳方案(自己研究): 1.调 ...
- 用javac编译整个j2ee项目
转自:http://www.blogjava.net/zhyiwww/archive/2011/10/13/361145.html 我们做项目,可能会使用ant做系统集成和部署.其实ant在编译项目时 ...
- J2EE 项目读写分离
先回答下 1.为啥要读写分离? 大家都知道最初开始,一个项目对应一个数据库,基本是一对一的,但是由于后来用户及数据还有访问的急剧增多, 系统在数据的读写上出现了瓶颈,为了让提高效率,想读和写不相互影响 ...
- J2EE 项目本地发布路径及修改
J2EE的项目Run on Server后,在tomcat安装目录下的webapps没有出现所建立的工程名字. 很明显项目并没有自动部署到tomcat的webapps中而是部署在了别的容器中. 在内置 ...
随机推荐
- 【angular5项目积累总结】表单复杂校验
view code form.css :host { display: flex; width: 100%; height:100%; border-left:1px solid #ccc; } .i ...
- JQuery ajax-向服务器发送请求的方法
如需将请求发送到服务器,我们使用 XMLHttpRequest 对象的 open() 和 send() 方法: xmlhttp.open("GET","ajax_info ...
- MYSQL DATE_FORMAT() 函数时间大小比较
DATE_FORMAT() 函数用于以不同的格式显示日期/时间数据. DATE_FORMAT(date,format) 可以使用的格式有: 格式 描述 %a 缩写星期名 %b 缩写月名 %c 月,数值 ...
- mybatis之typehandles
mybatis之typehandles 无论是Mybatis在预处理语句PreparedStatement中设置一个参数时,还是从结果集中取出一个值时,都会用类型处理器将获取的值以合适的方式转换成ja ...
- MongoDB 更改数据库位置
MongoDB在Windows中默认的数据库目录是 C:\data.如果在没有该目录的情况下,执行命令mongod,则会报如下错误: 如果我们不想把mongoDB的数据库放在C盘,可以使用如下两种方法 ...
- 新手嘛,先学习下 Vue2.0 新手入门 — 从环境搭建到发布
Vue2.0 新手入门 — 从环境搭建到发布 转自:http://www.runoob.com/w3cnote/vue2-start-coding.html 具体文章详细就不搬了,步骤可过去看,我这就 ...
- 02_Netty实现的Echo服务器和客户端
[Echo服务端] [EchoServer] public class EchoServer { private final int port; public EchoServer(int port) ...
- Flex 加载dwg
之前写的几种格式不是专门gis格式,这次来说说加载dwg.首先dwg格式不同于dxf格式,虽然autocad都能加载进去,真正用的比较多的是dwg格式,反正测绘,国土规划部门都是,吐槽下,然而auto ...
- Windows 批处理(cmd/bat)常用命令教程
Windows批处理(cmd/bat)常用命令教程 简单详细,建议收藏 常见问题: 1.如果你自己编写的.bat文件,双击打开,出现闪退 2.批处理.bat 文件中输出中文乱码 解决方法在文章末尾! ...
- 微信小程序开发10-开发流程
1.Flex布局 Flex是Flexible Box的缩写,意为”弹性布局”,用来为盒状模型提供最大的灵活性.任何一个容器都可以指定为Flex布局. 2.设置容器,用于统一管理容器内项目布局,也就是管 ...