java的异常分为两类:
1.error:jvm错误造成无法被程序员处理
2.Exception:可以由程序员有针对性的处理
因此我们需要关注的就是Exception,通常我们都只是针对程序本身的业务逻辑进行设计进而忽视了对异常处理的设计而这显然是不好的。
现在就以用户登陆这个流程来设计一个简单的异常处理设计
流程十分简单:用户表单提交数据->后台校验数据->反馈登陆结果
异常基类
首先我们自定义一个通用的异常基类,该类继承自RuntimeException
package com.hw.myp2c.common.exception;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author chengjian
* @description
* @date 18-11-10:上午11:28
*/
public class GenericException extends RuntimeException{
private final Logger logger = LoggerFactory.getLogger(this.getClass());
/**
* Constructs a new runtime exception with the specified detail message.
* The cause is not initialized, and may subsequently be initialized by a
* call to {@link #initCause}.
*
* @param message the detail message. The detail message is saved for
* later retrieval by the {@link #getMessage()} method.
*/
public GenericException(String message) {
super(message);
logger.error(message);
}
/**
* Constructs a new runtime exception with the specified detail message and
* cause. <p>Note that the detail message associated with
* {@code cause} is <i>not</i> automatically incorporated in
* this runtime exception's detail message.
*
* @param message the detail message (which is saved for later retrieval
* by the {@link #getMessage()} method).
* @param cause the cause (which is saved for later retrieval by the
* {@link #getCause()} method). (A <tt>null</tt> value is
* permitted, and indicates that the cause is nonexistent or
* unknown.)
* @since 1.4
*/
public GenericException(String message, Throwable cause) {
super(message, cause);
logger.error(message, cause);
}
}
所有自定义的异常类都继承自该类
数据库层异常类
在数据库操作层面定义类ItemsNotFoundException字面意思也能明白这个类的作用用户告知上层调用没有从数据库找到该用户
package com.hw.myp2c.common.exception;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author chengjian
* @description
* @date 18-11-10:上午11:28
*/
public class ItemsNotFoundException extends GenericException {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
/**
* Constructs a new runtime exception with the specified detail message.
* The cause is not initialized, and may subsequently be initialized by a
* call to {@link #initCause}.
*
* @param message the detail message. The detail message is saved for
* later retrieval by the {@link #getMessage()} method.
*/
public ItemsNotFoundException(String message) {
super(message);
logger.error(message);
}
/**
* Constructs a new runtime exception with the specified detail message and
* cause. <p>Note that the detail message associated with
* {@code cause} is <i>not</i> automatically incorporated in
* this runtime exception's detail message.
*
* @param message the detail message (which is saved for later retrieval
* by the {@link #getMessage()} method).
* @param cause the cause (which is saved for later retrieval by the
* {@link #getCause()} method). (A <tt>null</tt> value is
* permitted, and indicates that the cause is nonexistent or
* unknown.)
* @since 1.4
*/
public ItemsNotFoundException(String message, Throwable cause) {
super(message, cause);
logger.error(message,cause);
}
}
业务异常类
在本示例中的体现就是用户登陆失败所以我们定义了UserLoginException
package com.hw.myp2c.common.exception;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author chengjian
* @version 1.0
* @date 2018-11-10
* @Description
*/
public class UserLoginException extends GenericException {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
/**
* Constructs a new runtime exception with the specified detail message.
* The cause is not initialized, and may subsequently be initialized by a
* call to {@link #initCause}.
*
* @param message the detail message. The detail message is saved for
* later retrieval by the {@link #getMessage()} method.
*/
public UserLoginException(String message) {
super(message);
logger.error(message);
}
}
异常调用实现
在定义好异常类基础上展示对用户登陆这一流程的异常处理
public interface Myp2cUserService extends BaseService<Myp2cUserEntity,String> {
/**
* @author chengjian
* @description 根据用户名获取用户信息
* @date 18-11-10:下午4:11
* @param userId
* @return com.hw.myp2c.user.entity.Myp2cUserEntity
*/
Myp2cUserEntity loadUserByUserId(String userId) throws ItemsNotFoundException;
}
@Service
@Transactional(readOnly = true, rollbackFor = Exception.class)
public class Myp2cUserServiceImpl extends BaseServiceImpl<Myp2cUserEntity, String> implements Myp2cUserService {
private Myp2cUserDao myp2cUserDao;
@Autowired
public Myp2cUserServiceImpl(Myp2cUserDao myp2cUserDao) {
this.myp2cUserDao = myp2cUserDao;
}
/**
* @param userId
* @return com.hw.myp2c.user.entity.Myp2cUserEntity
* @author chengjian
* @description 根据用户名获取用户信息
* @date 18-11-10:下午4:11
*/
@Override
public Myp2cUserEntity loadUserByUserId(String userId) throws ItemsNotFoundException {
try {
Myp2cUserEntity userEntity = myp2cUserDao.findFirstByUserId(userId);
if (userEntity == null) {
throw new ItemsNotFoundException("未找到该用户!");
}
return userEntity;
} catch (Exception e) {
throw new ItemsNotFoundException("登陆出错,请联系管理员!");
}
}
}
从代码看到对数据库的查询产生2个异常
1.执行数据库查询时产生异常
2.没有找到用户
这两个异常最终导致的结果就是没有找到该用户信息,所以抛出了ItemsNotFoundException
public interface SecurityService {
/**
* @param userId
* @param userPwd
* @return
* @author chengjian
* @description 用户登陆
* @date 18-11-10:下午6:48
*/
Myp2cUserEntity userLogin(String userId, String userPwd) throws UserLoginException;
}
@Service
public class SecurityServiceImpl implements SecurityService {
private Myp2cUserService myp2cUserService;
private Myp2cRoleService myp2cRoleService;
private Myp2cMidsService myp2cMidsService;
@Autowired
public SecurityServiceImpl(Myp2cUserService myp2cUserService, Myp2cRoleService myp2cRoleService, Myp2cMidsService myp2cMidsService) {
this.myp2cUserService = myp2cUserService;
this.myp2cRoleService = myp2cRoleService;
this.myp2cMidsService = myp2cMidsService;
}
/**
* @param userId
* @param userPwd
* @return java.lang.String
* @author chengjian
* @description 用户登陆
* @date 18-11-10:下午6:48
*/
@Override
public Myp2cUserEntity userLogin(String userId, String userPwd) {
try {
Myp2cUserEntity userEntity = myp2cUserService.loadUserByUserId(userId);
String encodePwd = MD5Util.MD5(userPwd);
if (!encodePwd.equalsIgnoreCase(userEntity.getUserPwd())) {
throw new UserLoginException("用户名或密码错误!");
}
List<Myp2cRoleEntity> roles = myp2cRoleService.findByUser(userId);
roles.forEach(role -> role.setRoleMids(myp2cMidsService.findByRole(role.getId())));
userEntity.setUserRoles(roles);
userEntity.setMenuHtml(Mids.createUserMenuHtml(userEntity.initUserMids(), userId));
return userEntity;
} catch (ItemsNotFoundException e) {
throw new UserLoginException(e.getMessage());
}
}
}
从代码看到在本业务类中捕获ItemsNotFoundException并针对用户登陆校验情况产生UserLoginException
/**
* @author chengjian
* @version 1.0
* @date 2018-11-10
* @Description
*/
@RestController
public class SecurityController {
private SecurityService securityService;
@Autowired
public SecurityController(SecurityService securityService) {
this.securityService = securityService;
}
@PostMapping
public String login(@RequestParam(required = true)String userId,@RequestParam(required = true)String userPwd){
try {
Myp2cUserEntity userEntity=securityService.userLogin(userId,userPwd);
return userEntity.user2JsonString();
}catch (UserLoginException e){
return e.getMessage();
}
}
}
最终在controller中对异常进行处理并将封装好的错误信息返回给用户
通过异常的方式来返回信息比通过设置各种返回代码(1:成功;0:失败)这一方式来返回结果信息更有逻辑性,同时也能提高代码的可读性。
留言与评论(共有 0 条评论) |