最近手头的工作不太繁重,自己试着倒腾了一套用开源框架组建的 JavaWeb 后端解决方案。

感觉还不错的样子,但实践和项目实战还是有很大的落差,这里只做抛砖引玉之用。

项目 git 地址:https://git.oschina.net/LanboEx/sdh.git

大体采用的开源项目有:Spring + SpringMVC + Druid + JPA(Hibernate Impl)。

1. 采用到的开源项目漫谈

Spring 迷人的依赖注入特性, 使其已经稳稳的占据在 JavaEE 项目引用开源项目列表中的上层位置。

秉承低耦合高内聚的遵旨, Spring 提倡的对象工厂解耦类关系的思想已深入到每个攻城狮的心中。

SpringMVC 做为 Spring 的干儿子,最让我沉醉的是她强大的扩展能力,深邃的像大海一样。

前端无论是 freemarker/velocity/jsp...,后端 DAO 层无论是传统的 ORM 还是新近上位的领域模型。

她的态度始终如一,给你360度最贴心的呵护,有一人对你如此,此生足矣。

官网地址:http://projects.spring.io/spring-framework/

项目中关于 SpringMVC + Spring 的依赖:

       <!--spring mvc-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.3.RELEASE</version>
</dependency> <!-- Spring-orm -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>4.3.3.RELEASE</version>
</dependency> <!-- Spring AOP 动态代理 -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.9</version>
</dependency>

这上面我想说的是 AspectJ 这个东东, AspectJ 是最早、功能比较强大的 AOP 实现之一。

在 Java 领域,AspectJ 中的很多语法结构基本上已成为 AOP 领域的标准。

Spring 也有自己的 Spring-AOP,Spring-AOP 采用运行时生成代理类,底层可以选用 JDK 或者 CGLIB 动态代理。

通俗点,AspectJ 在编译时增强要切入的类,而 Spring-AOP 是在运行时通过代理类增强切入的类,效率和性能可想而知。

所以 Spring 在 2.0 的时候就已经开始支持 AspectJ ,现在到 4.X 的时代已经很完美的和 AspectJ  结合到一起。

有兴趣的可以在接着读读:https://www.oschina.net/translate/comparative_analysis_between_spring_aop_and_aspectj?cmp

Druid 出自阿里巴巴技术团队之手,个人认为是比较好的数据库连接池之一,尤其是监控部分是我的最爱。

官方 github 地址:https://github.com/alibaba/druid/wiki/常见问题

项目中的 web.xml 配置监控配置和监控界面:

   <!--Druid 数据库连接池监控-->
<servlet>
<servlet-name>DruidStatView</servlet-name>
<servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DruidStatView</servlet-name>
<url-pattern>/druid/*</url-pattern>
</servlet-mapping>

JPA 作为 Sun 公司引入的 ORM 规范,就像是 JDBC 之于各种数据库驱动 Jar,

不要去在意使用了什么样的数据库,用 JDBC 提供的规范方法去撸代码即可。

JPA 制定持久层规范,相同与抽象接口,有 ORM 框架撸具体的实现层。

Sun 想实现 ORM 技术统一,可能不远的将来,你不用在纠结选择什么样子的 ORM 框架。

而现有热门的 ORM 框架会渐渐失去光泽,这毕竟是个漫长的过程,让我们拭目以待。

2. 方案整体一览

方案中所有的类都位于 SpringContext 中,由 Spring 统一进行管理。

让 Spring 统一管理的前提是你要告诉有这样一个类需要它管理,目前我接触到的告诉途径有两种。

传统的 xml 配置和注解方式,xml 配置和注解方式各有优劣,比如 xml 配置的优点:

a. 如果你公司项目在引用另外一个公司的 jar,这时候,唯一可行方式为 xml 配置。

b. 如果类之间的依赖关系变动频繁,xml 配置是比较优秀的,改动代码和改动配置文件,无论是技术上还是风险上,xml 都稳赢注解。

注解声明的方式优点:代码和声明在一起,开发的时候不用切来切去,比 xml 配置声明要简单明了的多。

现在很多主流的框架都引入了注解,但也无法摈弃 xml 配置声明的方式。

在这个方案中我使用干净简单注解的方式,controller 包下使用注解@controller,dao-impl 包下使用@Repository,service 包下使用@service。

控制层注入服务实例,服务层注入数据访问层对象,持久层对象由 JAP 进行注解,页面通过控制层来传输和获取数据。

web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<!--Spring mvc -->
<servlet>
<servlet-name>springMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:spring-mvc-base.xml
classpath:spring-mvc-beans.xml
classpath:spring-hibernate-beans.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<async-supported>true</async-supported>
</servlet> <servlet-mapping>
<servlet-name>springMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping> <!--Druid 数据库连接池监控-->
<servlet>
<servlet-name>DruidStatView</servlet-name>
<servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DruidStatView</servlet-name>
<url-pattern>/druid/*</url-pattern>
</servlet-mapping>
</web-app>

maven pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.rambo</groupId>
<artifactId>sdh</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>sdh</name>
<description>spring mvc + Druid + hibernate</description> <dependencies>
<!--spring mvc-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.3.RELEASE</version>
</dependency> <!-- Spring-orm -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>4.3.3.RELEASE</version>
</dependency> <!-- Spring AOP 动态代理 -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.9</version>
</dependency> <!-- Hibernate-core -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.3.1.Final</version>
</dependency> <!-- Druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.26</version>
</dependency> <!--mysql 数据驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency> <!--日志-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version><!--2012.05 最后版本-->
</dependency>
</dependencies>
<build>
<finalName>sdh</finalName>
<plugins>
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.2.11.v20150529</version>
<configuration>
<jvmArgs>-XX:PermSize=256M -XX:MaxPermSize=1024M</jvmArgs>
<webApp>
<contextPath>/${project.name}</contextPath>
</webApp>
<httpConnector>
<port>4040</port>
</httpConnector>
<stopKey>foo</stopKey>
<stopPort>9998</stopPort>
</configuration>
</plugin>
</plugins>
</build>
</project>

3. DAO 层的种种设计思路

Controller 和 Service 层非常容易理解,这里不赘述了。

DAO 层 中 BasePo 希望将一些共有的属性抽象在父类当中(属性由具体项目需求决定)。

@MappedSuperclass
public class BasePO implements Serializable {
@Id
@Column(length = 32, nullable = true)
@GeneratedValue(generator = "uuid")
@GenericGenerator(name = "uuid", strategy = "uuid")
private String uuid; @Column(updatable = false)
private Date createDate; private Date modifyDate; ....getter/setter
}

BasePO

BaseDaoImpl 希望将一些公共的数据访问方法实现在父类当中(我这里的方法可能有点少,可以由具体项目增加)。

@Repository
public class BaseDaoImpl<T, PK extends Serializable> implements BaseDao<T, PK> { private Class<T> entityClass;
@Resource
protected SessionFactory sessionFactory; public BaseDaoImpl() {
this.entityClass = null;
Class<?> c = getClass();
Type type = c.getGenericSuperclass(); //反射获取超类
if (type instanceof ParameterizedType) {
Type[] parameterizedType = ((ParameterizedType) type).getActualTypeArguments();
this.entityClass = (Class<T>) parameterizedType[0];
}
} protected Session getSession() {
return sessionFactory.getCurrentSession();
} public T getByKey(PK id) {
Assert.notNull(id, "id is required");
return (T) getSession().get(entityClass, id);
} public T add(T entity) {
Assert.notNull(entity, "entity is required");
getSession().save(entity);
return entity;
} public T edit(T entity) {
Assert.notNull(entity, "entity is required");
getSession().update(entity);
return entity;
} public T deleteByKey(PK id) {
Assert.notNull(id, "id is required");
T t = (T) getSession().load(entityClass, id);
getSession().delete(t);
return t;
}
}

BaseDaoImpl

使用 JAP 注解编写业务使用到的持久层对象(主流的开发工具都支持由数据库反向生成持久层对象)。

@Entity
@Table(name = "t_user")
public class User extends BasePO {
@Column(nullable = false)
String name;
@Column(nullable = false)
String pwd;
....getter/setter
}

配置启动时扫描 POJO 的动作,至于是新建还是更新都有配置选项,可以自己查阅相关文档。

    <!-- 配置hibernate session工厂,需添加 spring-orm -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="hibernateProperties">
<props>
<prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
</props>
</property> <!-- 自动扫描注解方式配置的hibernate类文件 -->
<property name="packagesToScan">
<list>
<value>com.rambo.sdh.pojo</value>
</list>
</property>
</bean>

操纵数据库最主要的事务管理,采用 AOP 声明方式,在执行含有数据变动的方法前后进行拦截。

采用 AOP 声明方式进行拦截的好处,不用去关注数据库事务的开启和关闭,将重心放到业务逻辑上面。

    <!-- 配置事务管理器 -->
<bean name="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean> <!-- 1)基于 <tx> 和 <aop> 命名空间的声明式事务管理:transaction-manager指定事务管理器为transactionManager- -->
<tx:advice id="transactionAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="add*" propagation="REQUIRED" rollback-for="Exception"/>
<tx:method name="save*" propagation="REQUIRED" rollback-for="Exception"/>
<tx:method name="update*" propagation="REQUIRED" rollback-for="Exception"/>
<tx:method name="edit*" propagation="REQUIRED" rollback-for="Exception"/>
<tx:method name="modify*" propagation="REQUIRED" rollback-for="Exception"/>
<tx:method name="delete*" propagation="REQUIRED" rollback-for="Exception"/>
<tx:method name="remove*" propagation="REQUIRED" rollback-for="Exception"/>
<tx:method name="get*" propagation="NOT_SUPPORTED" read-only="true"/>
<tx:method name="find*" propagation="NOT_SUPPORTED" read-only="true"/>
<tx:method name="list*" propagation="NOT_SUPPORTED" read-only="true"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="transactionPointcut" expression="execution(* com.rambo.sdh.*.dao.impl.*.*(..))"/>
<aop:advisor pointcut-ref="transactionPointcut" advice-ref="transactionAdvice"/>
</aop:config> <!--2)基于 @Transactional 的方式将声明式事务管理:激活启用事务相关处理 Bean 配置-->
<tx:annotation-driven transaction-manager="transactionManager"/>

方式一在包 com.rambo.sdh.*.dao.*Impl.* 下所执行的已 add/save/update.....开头的方法。

方法在执行前后都会被 HibernateTransactionManager 拦截,进行事务的开启和关闭。

方式二在你想进行事务管理的接口、接口方法、类以及类方法上添加 @Transactional  注解。

当然还有一些其他的事情,有兴趣可以 debug 源码去一探究竟。

貌似说的也差不多了,该方案为 JavaEE 后端解决方案,前端用你想用的渲染技术即可。

项目开源 GIT 地址已在最上面给出,如果有兴趣的可以检出到本地跑一跑,该方案中小公司其实都挺适合,上手和开发速度快。

Spring + SpringMVC + Druid + JPA(Hibernate impl) 给你一个稳妥的后端解决方案的更多相关文章

  1. Spring + SpringMVC + Druid + MyBatis 给你一个灵活的后端解决方案

    生命不息,折腾不止. 折腾能遇到很多坑,填坑我理解为成长. 两个月前自己倒腾了一套用开源框架构建的 JavaWeb 后端解决方案. Spring + SpringMVC + Druid + JPA(H ...

  2. Spring boot之JPA/Hibernate/Spring Data

    1.什么是JPA? JPA全称Java Persistence API.JPA通过JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中. JPA(Java Per ...

  3. JPA+Hibernate 3.3 ——第一个JPA程序

    所需要的最小的jar包(注意:jar包所在路径不能含有空格或中文) hibernate3.jarhibernate-cglib-repack-2.1_3.jarslf4j-api-1.5.2.jarj ...

  4. javaweb各种框架组合案例(四):maven+spring+springMVC+spring data jpa(hibernate)【失败案例】

    一.失败案例 1. 控制台报错信息 严重: Exception sending context initialized event to listener instance of class org. ...

  5. spring+hibernate+jpa+Druid的配置文件,spring整合Druid

    spring+hibernate+jpa+Druid的配置文件 spring+hibernate+jpa+Druid的完整配置 spring+hibernate+jpa+Druid的数据源配置 spr ...

  6. Spring Boot + Jpa(Hibernate) 架构基本配置

    本文转载自:https://blog.csdn.net/javahighness/article/details/53055149 1.基于springboot-1.4.0.RELEASE版本测试 2 ...

  7. 【maven + hibernate(注解) +spring +springMVC】 使用maven搭建项目

    研究,百度,查资料+好友帮助,使用MyEcplise2015工具,通过maven搭建hibernate+springMVC+spring的项目,数据库采用MySql5.5 不过使用的版本会在项目搭建过 ...

  8. javaweb各种框架组合案例(三):maven+spring+springMVC+hibernate

    1.hibernate译为"越冬",指的是给java程序员带来春天,因为java程序员无需再关心各种sql了: 2.hibernate通过java类生成数据库表,通过操作对象来映射 ...

  9. Spring+SpringMVC+Hibernate 与 shiro 整合步骤

    目录 1. 业务需求分析 2. 创建数据库 3. 创建 maven webapp 工程 4. 创建实体类(POJO) 5. 配置 Hibernate 和 Mapping 5.1 Hibernate 主 ...

随机推荐

  1. 数百个 HTML5 例子学习 HT 图形组件 – 拓扑图篇

    HT 是啥:Everything you need to create cutting-edge 2D and 3D visualization. 这口号是当年心目中的产品方向,接着就朝这个方向慢慢打 ...

  2. 2.ASP.NET MVC 中使用Crystal Report水晶报表

    上一篇,介绍了怎么导出Excel文件,这篇文章介绍在ASP.NET MVC中使用水晶报表. 项目源码下载:https://github.com/caofangsheng93/CrystalReport ...

  3. IL接口和类的属性

    上一篇文章学习了IL的入门,接下来我们再通过两个例子来了解下类的属性.构造函数以及接口的使用 一.类的属性.构造函数 1.先看下我们要构建的类的C#代码,然后再进行IL的实现,示例代码如下: [Ser ...

  4. 翻译:使用 ASP.NET MVC 4, EF, Knockoutjs and Bootstrap 设计和开发站点 - 5 - 数据库设计

    数据库方面我们需要的主要功能如下: 联系人有姓名和电子邮件地址. 联系人可以拥有多个地址. 联系人可以拥有多个电话. 为了实现目标,我们需要在数据库中创建下列表.表与表的关系如下图所示: 数据库的脚本 ...

  5. JavaWeb_day08_EL JSTL

    本文为博主辛苦总结,希望自己以后返回来看的时候理解更深刻,也希望可以起到帮助初学者的作用. 转载请注明 出自 : luogg的博客园 谢谢配合! day08 EL JSTL EL表达式 语法:${} ...

  6. 多线程中的volatile和伪共享

      伪共享 false sharing,顾名思义,“伪共享”就是“其实不是共享”.那什么是“共享”?多CPU同时访问同一块内存区域就是“共享”,就会产生冲突,需要控制协议来协调访问.会引起“共享”的最 ...

  7. 信贷业务(Ali)

    1.信贷业务视角 信贷业务主要有两个视角,借款人和出资机构.借款人关心借多少钱,还多少钱,多少利息:机构关心信贷资产风险,收益. 领域模型上两个视角分开:个人--->账单.机构--->资产 ...

  8. springmvc的数据校验

       springmvc的数据校验 在Web应用程序中,为了防止客户端传来的数据引发程序异常,常常需要对数据进行验证,输入验证分为客户端验证与服务器端验证. 客户端验证主要通过javaScript脚本 ...

  9. SSH远程登录原理与运用

    SSH是每一台Linux电脑的标准配置. 随着Linux设备从电脑逐渐扩展到手机.外设和家用电器,SSH的使用范围也越来越广.不仅程序员离不开它,很多普通用户也每天使用. SSH具备多种功能,可以用于 ...

  10. iOS多线程之8.NSOPeration的其他用法

      本文主要对NSOPeration的一些重点属性和方法做出介绍,以便大家可以更好的使用NSOPeration. 1.添加依赖 - (void)addDependency:(NSOperation * ...