个人使用SpringMVC框架项目的心得
2015-08-09 14:28
477 查看
4月19日更新 : 已在Github中上传了精简的SpringMVC框架的M***EN工程包。可以在进行简单配置后使用。
链接: springMVC
本文仅作SpringMVC框架使用过程中的一些个人总结。
大致目录:
Worksapce
|-common-utils
|-core
|-web
common-utils
|-exception
|-utils
|-Generic
|-GenericDao
|-GenericService
异常处理
根据业务逻辑分成:系统异常
业务异常
通常指业务处理中可能出现的异常情况,通常是违反业务正常进行规则出现的异常,而不是系统错误。
应该给前台反馈适当的异常信息。而不是单纯的错误代码。且一般是业务逻辑判断后主动抛出的异常,而不是程序错误抛出的异常。
系统异常
一般是程序错误,或者违规操作造成程序无法继续运行的状况。为了提高用户体验,通常捕捉到程序异常
然后将其包装成系统异常
同时也不影响查询日志获得更详细的错误信息。
工具库
可以从网络上获取:引入M***EN依赖,或者导入java。并可以适当的进行继承与扩展。对于提高编程效率很有帮助。尽量用T、E等,扩大适用范围。
公共接口
数据层
所有项目的公共实现,如:增、删、改、查…。
2。 服务层
所有项目的业务实现。
core
|-commons
|-utils
|-comstatic
|-config
|-Module_1
|-Dao
|-Domain
|-Service
|-Module_2
|-Dao
|-Domain
|-Service
。。。。
公共库
包括工具库、静态参数类、配置类
工具库
可以从网络上获取:引入M***EN依赖,或者导入java。并可以适当的进行继承与扩展。对于提高编程效率很有帮助。
静态参数类
避免在代码中直接写入参数,而是将参数提取出来放进参数类中。
配置类
将一些允许在项目发布后进行设置的参数暴露出来,以
数据层
在
比如:
清空整张表、从JSON文件导入数据、针对该表个性化数据查询、处理等。
接口
针对某个表
实现
针对某个表
业务逻辑层
接口
针对某一项业务的接口,可能涉及多个表Entity,因此在Service层可以调用多个Dao。
实现
针对某一项业务的具体实现。
为实现数据库的事务处理,在
web
|-controller
|-Module_1
|-ModuleController
|-webapp
|-WEB-INF
|-resource
控制器
用来控制页面跳转
1. 返回页面与数据 `ModelAndView`。
使用 `RequestMapping` 标签。
2. 返回数据实体
使用 `ResponseBody`+`RequestMapping` 标签。
一般Mapping时候在路径上加上`/api/`比较好。这样有利于明显标志数据与页面的分离。
3. 在`Controller`上方也可以加入统一的`Mapping`路径.
这样可以用于在有用户认证拦截的框架中(如:`Shiro`)实现统一的免密连接。多用于`api`或者后台调试页面。
资源
用于一般资源文件的放置。
一般`resource`可以放置`images`,`css`,`javascript`等文件。`WEB-INF`中放置`html`文件。
一般
* `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;
}
}
“`
避免在日志点直接写入日志实现方法,这样对于后期统一的修改有好处。
通过
通过
设置日志级别 DEBUG(3) > INFO(2) > ERROR(1) > NONE(0)
则当设置
伪代码如下:
最终效果如下
链接: springMVC
本文仅作SpringMVC框架使用过程中的一些个人总结。
项目结构
项目大致分为公共包(common-utils)、核心(core)、前端(web)三个工程。大致目录:
Worksapce
|-common-utils
|-core
|-web
公共包
common-utils
全系统(包括其它模块)公用的部分:common-utils
|-exception
|-utils
|-Generic
|-GenericDao
|-GenericService
异常处理
根据业务逻辑分成:系统异常
SystemException、业务异常
BusinessException两大类。
业务异常
通常指业务处理中可能出现的异常情况,通常是违反业务正常进行规则出现的异常,而不是系统错误。
应该给前台反馈适当的异常信息。而不是单纯的错误代码。且一般是业务逻辑判断后主动抛出的异常,而不是程序错误抛出的异常。
系统异常
一般是程序错误,或者违规操作造成程序无法继续运行的状况。为了提高用户体验,通常捕捉到程序异常
Exception后记录日志系统,
然后将其包装成系统异常
BusinessException抛给前台。这样反馈给用户的时异常的概述,而不是冗长的异常代码。
同时也不影响查询日志获得更详细的错误信息。
工具库
可以从网络上获取:引入M***EN依赖,或者导入java。并可以适当的进行继承与扩展。对于提高编程效率很有帮助。尽量用T、E等,扩大适用范围。
公共接口
数据层
GenericDao,
GenericDaoImpl
所有项目的公共实现,如:增、删、改、查…。
2。 服务层
GenericService, `GenericServiceImpl
所有项目的业务实现。
核心
core
具体模块的核心工程:core
|-commons
|-utils
|-comstatic
|-config
|-Module_1
|-Dao
|-Domain
|-Service
|-Module_2
|-Dao
|-Domain
|-Service
。。。。
公共库
包括工具库、静态参数类、配置类
工具库
可以从网络上获取:引入M***EN依赖,或者导入java。并可以适当的进行继承与扩展。对于提高编程效率很有帮助。
静态参数类
避免在代码中直接写入参数,而是将参数提取出来放进参数类中。
配置类
config
将一些允许在项目发布后进行设置的参数暴露出来,以
.property或者
.xml方式保存。
数据层
DaoExtends
GenericDao
在
common-utils的
GenericDao基础上添加个性化的方法。
比如:
清空整张表、从JSON文件导入数据、针对该表个性化数据查询、处理等。
接口
Dao
针对某个表
Entity实现对其数据基本的处理。
实现
DaoImpl
针对某个表
Entity实现对其数据基本的处理。
业务逻辑层
ServiceExtends
GenericService
接口
Service
针对某一项业务的接口,可能涉及多个表Entity,因此在Service层可以调用多个Dao。
实现
ServiceImpl
针对某一项业务的具体实现。
为实现数据库的事务处理,在
Service的实现上,应加上事务标签
@Transactional
前端
web
前端工程: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 - Service - Dao 的三层结构
阐述
Controller用于与用户直接交互,浏览器,
HTTP请求等。
Service用于业务逻辑处理。注意接口输入输出的规范,这样有利于接口复用。
Dao用于直接与数据实体交互,实现数据的简单提取与处理。避免在
Dao层出现跨表操作现象.
结构
结构示意图如下:一般
Controller只与
Service交互。
Service只与
Dao交互。
异常处理
抛出与捕获
Controller-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(); } }
最终效果如下
相关文章推荐
- Spring基于自定义注解的用户认证
- Spring实现定时任务
- 浅析Java中的final关键字
- 开发工具之MyEclipse用法基本总结(断点测试,快捷键,Junit测试)
- java.lang.IllegalStateException:Unable to initialise endpoint. A previous call to init() failed. See
- struts工作原理
- 搭建SpringMVC框架
- JAVA中的树的遍历
- 如何将JAVA工程转为MAVEN工程
- 关于CMUSphinx的一些整理
- Spring和Hibernate相遇
- hibernate中的通用<K,V>查询法
- Java项目建构工具之Maven
- 找出数组中前K小的值&最小堆
- 【Java多线程】之九:守护线程
- 《Java并发编程实战》第二章 线程安全 札记
- Log4j配置文件位置+Spring数据源配置文件位置
- XStream转换java对象与XML
- 【Java多线程】之八:单例模式的线程安全
- Java 接口与抽象类