4月19日更新 : 已在Github中上传了精简的SpringMVC框架的MAVEN工程包。可以在进行简单配置后使用。
链接: springMVC
本文仅作SpringMVC框架使用过程中的一些个人总结。
项目大致分为公共包(common-utils)、核心(core)、前端(web)三个工程。
大致目录:
Worksapce
|-common-utils
|-core
|-web
全系统(包括其它模块)公用的部分:
common-utils
|-exception
|-utils
|-Generic
|-GenericDao
|-GenericService
异常处理
根据业务逻辑分成:系统异常SystemException
、业务异常BusinessException
两大类。
业务异常
通常指业务处理中可能出现的异常情况,通常是违反业务正常进行规则出现的异常,而不是系统错误。
应该给前台反馈适当的异常信息。而不是单纯的错误代码。且一般是业务逻辑判断后主动抛出的异常,而不是程序错误抛出的异常。
系统异常
一般是程序错误,或者违规操作造成程序无法继续运行的状况。为了提高用户体验,通常捕捉到程序异常Exception
后记录日志系统,
然后将其包装成系统异常BusinessException
抛给前台。这样反馈给用户的时异常的概述,而不是冗长的异常代码。
同时也不影响查询日志获得更详细的错误信息。
工具库
可以从网络上获取:引入MAVEN依赖,或者导入java。并可以适当的进行继承与扩展。对于提高编程效率很有帮助。尽量用T、E等,扩大适用范围。
公共接口
GenericDao
, GenericDaoImpl
2。 服务层 GenericService
, `GenericServiceImpl
所有项目的业务实现。
具体模块的核心工程:
core
|-commons
|-utils
|-comstatic
|-config
|-Module_1
|-Dao
|-Domain
|-Service
|-Module_2
|-Dao
|-Domain
|-Service
。。。。
公共库
包括工具库、静态参数类、配置类
工具库
可以从网络上获取:引入MAVEN依赖,或者导入java。并可以适当的进行继承与扩展。对于提高编程效率很有帮助。
静态参数类
避免在代码中直接写入参数,而是将参数提取出来放进参数类中。
配置类config
将一些允许在项目发布后进行设置的参数暴露出来,以.property
或者.xml
方式保存。
数据层 Dao
Extends GenericDao
在common-utils
的GenericDao
基础上添加个性化的方法。
比如:
清空整张表、从JSON文件导入数据、针对该表个性化数据查询、处理等。
接口 Dao
针对某个表Entity
实现对其数据基本的处理。
实现 DaoImpl
针对某个表Entity
实现对其数据基本的处理。
业务逻辑层 Service
Extends GenericService
接口 Service
针对某一项业务的接口,可能涉及多个表Entity,因此在Service层可以调用多个Dao。
实现 ServiceImpl
针对某一项业务的具体实现。
为实现数据库的事务处理,在Service
的实现上,应加上事务标签@Transactional
前端工程:
web
|-controller
|-Module_1
|-ModuleController
|-webapp
|-WEB-INF
|-resource
Controller
用来控制页面跳转 1. 返回页面与数据 `ModelAndView`。 使用 `RequestMapping` 标签。 2. 返回数据实体 使用 `ResponseBody`+`RequestMapping` 标签。 一般Mapping时候在路径上加上`/api/`比较好。这样有利于明显标志数据与页面的分离。 3. 在`Controller`上方也可以加入统一的`Mapping`路径. 这样可以用于在有用户认证拦截的框架中(如:`Shiro`)实现统一的免密连接。多用于`api`或者后台调试页面。
webapp
用于一般资源文件的放置。
一般`resource`可以放置`images`,`css`,`javascript`等文件。`WEB-INF`中放置`html`文件。
Controller
用于与用户直接交互,浏览器,HTTP
请求等。
Service
用于业务逻辑处理。注意接口输入输出的规范,这样有利于接口复用。
Dao
用于直接与数据实体交互,实现数据的简单提取与处理。避免在Dao
层出现跨表操作现象.
Controller
只与Service
交互。 Service
只与Dao
交互。* `Dao` 中不涉及业务,一般错误都是系统异常,不做处理,直接抛出`Exception`, 在`Service`中做进一步处理。 “`java public void doSomething() throws Exception { try{ someFunction(); } catch(Exception e){ throw e; } } “` * `Service` 中涉及复杂业务,一般错误处理在这里处理完成后抛出。 “`java public void doSomething() throws Exception { logger.debug(); try{ someFunction(); if(BusinessError){ logger.info(); throw new BusinessException(); } } catch (Exception e){ logger.error(); throw new SystemException(); } } “` * `Controller`中捕获系统抛出的异常,并交予用户处理。 “`java public void doSomething() throws Exception { /*为保证系统正常运行,一般进行try-catch操作,不管正常与否均能返回结果*/ boolean statusFlag; String ErrMsg; try{ service.doSomething(); statusFlag = true; } catch (SystemException e) { statusFlag = false; ErrMsg = e.getMessage(); } catch (BusinessException e) { statusFlag = false; ErrMsg = e.getMessage(); } catch (Exception e) { statusFlag = false; //系统内未捕获的错误,应该记录日志 logger.error(); ErrMsg = e.toString(); } //最终判断是否成功执行 if(statusFlag) { return success; } else { return ErrMsg; } } “`
埋点工作最好在项目进行中时就留意进行。初期可以先写个日志工具logger
,并加上空方法,甚至简单的System.out.println()
都行。
避免在日志点直接写入日志实现方法,这样对于后期统一的修改有好处。
如上文的异常处理为例,代码中可以看到日志埋点中可以使用debug
,info
,error
三个级别的日志处理。这样就可以方便地区分日志类别。同时不同的日志级别区分,可以为以后实现控制日志记录级别,减少日志量打下基础。
为日志专门创建一个logger
,其中加入个性化的设置,日志器log4jLogger
,customLogger
等等。通过统一的方法调用各个logger
。
通过config
在外部.property
文件中实现不同logger
的调度开关。
通过config
在外部实现日志级别的处理
设置日志级别 DEBUG(3) > INFO(2) > ERROR(1) > NONE(0)
则当设置logLevel = 3
时,会记录所有日志; 当logLevel = 1
时,就只会记录系统错误日志了。
伪代码如下:
public void error(String className, String functionName, String logInfo) {
try {
if(onfig.getLOG_LEVEL() >= Static.LOG_LEVEL_ERROR) {
if(config.isUSE_LOGGER()) {
logger.errorLog(className, functionName, logInfo);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}