Spring Boot + Jpa(Hibernate) 架构基本配置详解
1、基于springboot-1.4.0.release版本测试
2、springboot + hibernate + druid + mysql + servlet(jsp)
不废话,直接上代码
一、maven的pom文件
<?xml version="1.0" encoding="utf-8"?> <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/xsd/maven-4.0.0.xsd"> <modelversion>4.0.0</modelversion> <groupid>com.zsx</groupid> <artifactid>demo</artifactid> <packaging>war</packaging> <version>0.0.1</version> <name>zsx maven webapp</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceencoding>utf-8</project.build.sourceencoding> <jdk.version>1.7</jdk.version> <tomcat.version>7.0.69</tomcat.version> </properties> <parent> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-parent</artifactid> <version>1.4.0.release</version> </parent> <dependencies> <!-- 添加对jsp视图解析的支持 --> <dependency> <groupid>org.apache.tomcat.embed</groupid> <artifactid>tomcat-embed-jasper</artifactid> </dependency> <dependency> <groupid>javax.servlet</groupid> <artifactid>jstl</artifactid> </dependency> <dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-web</artifactid> </dependency> <!-- 下面两个引入为了操作数据库 --> <dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-data-jpa</artifactid> </dependency> <dependency> <groupid>mysql</groupid> <artifactid>mysql-connector-java</artifactid> </dependency> <dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-tomcat</artifactid> <scope>provided</scope> </dependency> <!-- 只需引入spring-boot-devtools 即可实现热部署 --> <dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-devtools</artifactid> </dependency> <!-- json包 --> <dependency> <groupid>com.alibaba</groupid> <artifactid>fastjson</artifactid> <version>1.2.16</version> </dependency> <!-- 为了监控数据库 --> <dependency> <groupid>com.alibaba</groupid> <artifactid>druid</artifactid> <version>1.0.25</version> </dependency> <dependency> <groupid>org.apache.poi</groupid> <artifactid>poi</artifactid> <version>3.14</version> </dependency> <!-- junit 单元测试 --> <dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-test</artifactid> <scope>test</scope> </dependency> <dependency> <groupid>io.springfox</groupid> <artifactid>springfox-swagger2</artifactid> <version>2.6.0</version> </dependency> <dependency> <groupid>io.springfox</groupid> <artifactid>springfox-swagger-ui</artifactid> <version>2.6.0</version> </dependency> </dependencies> <build> <finalname>/</finalname> <plugins> <plugin> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-maven-plugin</artifactid> <dependencies> <!-- 热部署 --> <dependency> <groupid>org.springframework</groupid> <artifactid>springloaded</artifactid> <version>1.2.6.release</version> </dependency> </dependencies> </plugin> </plugins> </build> <repositories> <repository> <id>ali</id> <name>ali repository</name> <url>http://maven.aliyun.com/nexus/content/groups/public/</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories> </project>
二、项目架构
想想还是介绍一下项目的目录结构,这样方便梳理整体的架构配置
src ├─main │ ├─java │ │ └─com │ │ └─zsx │ │ │ application.java │ │ │ springbootstartapplication.java │ │ │ │ │ ├─common │ │ │ ├─config │ │ │ │ druiddbconfig.java │ │ │ │ multipartconfig.java │ │ │ │ │ │ │ ├─filter │ │ │ │ druidstatfilter.java │ │ │ │ │ │ │ ├─interceptors │ │ │ │ authinterceptor.java │ │ │ │ webappconfigurer.java │ │ │ │ │ │ │ ├─servlet │ │ │ │ druidstatviewservlet.java │ │ │ │ │ │ │ └─swagger │ │ │ swagger2.java │ │ │ │ │ ├─controller │ │ │ │ logincontroller.java │ │ │ │ testcontroller.java │ │ │ │ usercontroller.java │ │ │ │ │ ├─dao │ │ │ │ tuserdao.java │ │ │ │ │ │ │ └─impl │ │ ├─entity │ │ │ │ baseentity.java │ │ │ │ │ ├─model │ │ │ │ tree.java │ │ │ │ │ ├─service │ │ │ │ userservice.java │ │ │ │ │ │ │ └─impl │ │ │ userserviceimpl.java │ │ │ │ │ └─util │ │ generatepageable.java │ │ │ ├─resources │ │ │ application.properties │ │ │ logback-test.xml │ │ │ │ │ └─static │ │ ├─css │ │ ├─img │ │ └─js │ │ │ └─webapp │ │ index.jsp │ │ │ └─web-inf │ │ web.xml │ │ │ └─view │ │ login.jsp │ │ │ ├─error │ │ 500.jsp │ ├─jsp │ main.jsp │ └─test └─java utiltest.java
标准的maven项目结构,其中java下是dao、service、controller ,还有实体类映射entity,其他配置config
三、resources下的应用配置文件application.properties
#server.port=9090 # 数据库访问配置 # 主数据源,默认的 spring.datasource.type=com.alibaba.druid.pool.druiddatasource spring.datasource.url=jdbc:mysql://localhost:3306/test spring.datasource.username= root spring.datasource.password= root spring.datasource.driverclassname = com.mysql.jdbc.driver # 下面为连接池的补充设置,应用到上面所有数据源中 # 初始化大小,最小,最大 spring.datasource.initialsize=5 spring.datasource.minidle=5 spring.datasource.maxactive=20 # 配置获取连接等待超时的时间 spring.datasource.maxwait=60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 spring.datasource.timebetweenevictionrunsmillis=60000 # 配置一个连接在池中最小生存的时间,单位是毫秒 spring.datasource.minevictableidletimemillis=300000 spring.datasource.validationquery=select 1 from dual spring.datasource.testwhileidle=true spring.datasource.testonborrow=false spring.datasource.testonreturn=false # 打开pscache,并且指定每个连接上pscache的大小 spring.datasource.poolpreparedstatements=true spring.datasource.maxpoolpreparedstatementperconnectionsize=20 # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙 spring.datasource.filters=stat,wall,log4j # 通过connectproperties属性来打开mergesql功能;慢sql记录 spring.datasource.connectionproperties=druid.stat.mergesql=true;druid.stat.slowsqlmillis=5000 # 合并多个druiddatasource的监控数据 spring.datasource.useglobaldatasourcestat=true #jpa configuration: spring.jpa.database=mysql # show or not log for each sql query spring.jpa.show-sql=false spring.jpa.generate-ddl=true # hibernate ddl auto (create, create-drop, update) spring.jpa.hibernate.ddl-auto=create #spring.jpa.database-platform=org.hibernate.dialect.mysql5dialect spring.jpa.hibernate.naming_strategy=org.hibernate.cfg.improvednamingstrategy #spring.jpa.database=org.hibernate.dialect.mysql5innodbdialect spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.mysql5dialect spring.mvc.view.prefix=/web-inf/view/ spring.mvc.view.suffix=.jsp #spring.resources.static-locations=classpath:/resources/,classpath:/static/
四、启动应用主类文件 application.java
package com.zsx; import org.springframework.boot.springapplication; import org.springframework.boot.autoconfigure.springbootapplication; import org.springframework.boot.web.servlet.servletcomponentscan; @springbootapplication @servletcomponentscan // 扫描使用注解方式的servlet public class application { public static void main(string[] args) { springapplication.run(application.class, args); } }
若需要部署到外部的tomcat容器中,则添加下面类即可。
package com.zsx; import org.slf4j.logger; import org.slf4j.loggerfactory; import org.springframework.boot.springapplication; import org.springframework.boot.builder.springapplicationbuilder; import org.springframework.boot.context.web.springbootservletinitializer; /** * 修改启动类,继承 springbootservletinitializer 并重写 configure 方法 * @author zsx * */ public class springbootstartapplication extends springbootservletinitializer { private static final logger logger = loggerfactory.getlogger(springbootstartapplication.class); @override protected springapplicationbuilder configure(springapplicationbuilder builder) { return builder.sources(application.class); } }
五、数据库连接池druid的配置
package com.zsx.common.config; import java.sql.sqlexception; import javax.sql.datasource; import org.springframework.beans.factory.annotation.value; import org.springframework.context.annotation.bean; import org.springframework.context.annotation.configuration; import org.springframework.context.annotation.primary; import com.alibaba.druid.pool.druiddatasource; /** * druiddbconfig类被@configuration标注,用作配置信息; * datasource对象被@bean声明,为spring容器所管理, * @primary表示这里定义的datasource将覆盖其他来源的datasource。 * @author zsx *jdbc.url=${jdbc.url} *最新的支持方式如下: *jdbc.url=@jdbc.url@ */ @configuration public class druiddbconfig { // private logger logger = loggerfactory.getlogger(druiddbconfig.class); @value("${spring.datasource.url}") private string dburl; @value("${spring.datasource.username}") private string username; @value("${spring.datasource.password}") private string password; @value("${spring.datasource.driverclassname}") private string driverclassname; @value("${spring.datasource.initialsize}") private int initialsize; @value("${spring.datasource.minidle}") private int minidle; @value("${spring.datasource.maxactive}") private int maxactive; @value("${spring.datasource.maxwait}") private int maxwait; @value("${spring.datasource.timebetweenevictionrunsmillis}") private int timebetweenevictionrunsmillis; @value("${spring.datasource.minevictableidletimemillis}") private int minevictableidletimemillis; @value("${spring.datasource.validationquery}") private string validationquery; @value("${spring.datasource.testwhileidle}") private boolean testwhileidle; @value("${spring.datasource.testonborrow}") private boolean testonborrow; @value("${spring.datasource.testonreturn}") private boolean testonreturn; @value("${spring.datasource.poolpreparedstatements}") private boolean poolpreparedstatements; @value("${spring.datasource.maxpoolpreparedstatementperconnectionsize}") private int maxpoolpreparedstatementperconnectionsize; @value("${spring.datasource.filters}") private string filters; @value("{spring.datasource.connectionproperties}") private string connectionproperties; @bean // 声明其为bean实例 @primary // 在同样的datasource中,首先使用被标注的datasource public datasource datasource() { druiddatasource datasource = new druiddatasource(); datasource.seturl(this.dburl); datasource.setusername(username); datasource.setpassword(password); datasource.setdriverclassname(driverclassname); // configuration datasource.setinitialsize(initialsize); datasource.setminidle(minidle); datasource.setmaxactive(maxactive); datasource.setmaxwait(maxwait); datasource.settimebetweenevictionrunsmillis(timebetweenevictionrunsmillis); datasource.setminevictableidletimemillis(minevictableidletimemillis); datasource.setvalidationquery(validationquery); datasource.settestwhileidle(testwhileidle); datasource.settestonborrow(testonborrow); datasource.settestonreturn(testonreturn); datasource.setpoolpreparedstatements(poolpreparedstatements); datasource.setmaxpoolpreparedstatementperconnectionsize(maxpoolpreparedstatementperconnectionsize); try { datasource.setfilters(filters); } catch (sqlexception e) { } datasource.setconnectionproperties(connectionproperties); return datasource; } }
springboot里默认使用tomcat的上传文件大小限制,即1mb, 修改用下面的配置类:
import javax.servlet.multipartconfigelement; import org.springframework.boot.web.servlet.multipartconfigfactory; import org.springframework.context.annotation.bean; import org.springframework.context.annotation.configuration; @configuration public class multipartconfig { @bean public multipartconfigelement multipartconfigelement(){ multipartconfigfactory factory = new multipartconfigfactory(); factory.setmaxfilesize("10mb"); factory.setmaxrequestsize("10mb"); return factory.createmultipartconfig(); } }
六、开启druid的数据库监控配置
1、配置filter
import javax.servlet.annotation.webfilter; import javax.servlet.annotation.webinitparam; import com.alibaba.druid.support.http.webstatfilter; /** * 配置druid监控统计功能 * 配置filter * @author zsx * */ @webfilter(filtername = "druidwebstatfilter", urlpatterns = "/*", initparams = { @webinitparam(name="exclusions",value="*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*")// 忽略资源 } ) public class druidstatfilter extends webstatfilter { }
2、 配置web访问的servlet
import javax.servlet.annotation.webinitparam; import javax.servlet.annotation.webservlet; import com.alibaba.druid.support.http.statviewservlet; /** * 配置druid监控统计功能 * 在springboot项目中基于注解的配置,如果是web.xml配置,按规则配置即可 * @author zsx * */ @webservlet(urlpatterns = "/druid/*", initparams = { // @webinitparam(name = "allow", value = "192.168.16.110,127.0.0.1"), // ip白名单 (没有配置或者为空,则允许所有访问) // @webinitparam(name="deny",value="192.168.16.111"), // ip黑名单 (存在共同时,deny优先于allow) @webinitparam(name="loginusername",value="druid"),// 用户名 @webinitparam(name="loginpassword",value="druid"),// 密码 @webinitparam(name="resetenable",value="false")// 禁用html页面上的“reset all”功能 } ) public class druidstatviewservlet extends statviewservlet { }
这样启动项目后在浏览器中输入地址:端口/druid,就可以看到druid的监控web页面了
七、 拦截器配置
import org.springframework.context.annotation.configuration; import org.springframework.web.servlet.config.annotation.interceptorregistry; import org.springframework.web.servlet.config.annotation.resourcehandlerregistry; import org.springframework.web.servlet.config.annotation.webmvcconfigureradapter; @configuration public class webappconfigurer extends webmvcconfigureradapter { /** * 配置拦截器 */ @override public void addinterceptors(interceptorregistry registry) { // todo auto-generated method stub // 多个拦截器组成一个拦截器链 // addpathpatterns 用于添加拦截规则 // excludepathpatterns 用户排除拦截 registry.addinterceptor(new authinterceptor()).addpathpatterns("/**"); super.addinterceptors(registry); } /** * 添加自定义的静态资源映射 这里使用代码的方式自定义目录映射,并不影响spring boot的默认映射,可以同时使用。 */ @override public void addresourcehandlers(resourcehandlerregistry registry) { // registry.addresourcehandler("/new/**").addresourcelocations("classpath:/new/"); // registry.addresourcehandler("/**").addresourcelocations("/"); super.addresourcehandlers(registry); } }
八、swagger发布api测试配置(可忽略)
import org.springframework.context.annotation.bean; import org.springframework.context.annotation.configuration; import springfox.documentation.builders.apiinfobuilder; import springfox.documentation.builders.pathselectors; import springfox.documentation.builders.requesthandlerselectors; import springfox.documentation.service.apiinfo; import springfox.documentation.spi.documentationtype; import springfox.documentation.spring.web.plugins.docket; import springfox.documentation.swagger2.annotations.enableswagger2; @configuration @enableswagger2 public class swagger2 { @bean public docket createrestapi(){ return new docket(documentationtype.swagger_2) .apiinfo(apiinfo()) .select() .apis(requesthandlerselectors.basepackage("com.zsx.controller.api")) .paths(pathselectors.any()) .build(); } private apiinfo apiinfo(){ return new apiinfobuilder() .title("spring boot中使用swagger2构建restful apis") .description("描述") .termsofserviceurl("http://zsx.com.cn") .version("1.0") .build(); } }
至此,所有的配置已完成,下面是一个操作数据的简单demo
九、实体类
@entity @table(name = "t_user") public class tuser implements java.io.serializable { /** * */ private static final long serialversionuid = 1l; @id @generatedvalue(strategy=generationtype.identity) private long id; @column(name = "username") private string username; @column(name = "password") private string password; @column(name = "email") private string email; @column(name = "mobile") private string mobile; @column(name = "nickname") private string nickname; // 省略getter 和 setter }
十、dao层
1、使用jpa基本可以实现不写sql,(但实际开发中,业务逻辑会很复杂,一点不写sql完全不现实)
2、注意添加@repository注解, 添加jpaspecificationexecutor继承可以方便分页
3、 看些jpa的查询语法资料
import java.util.list; import java.util.map; import org.springframework.data.domain.pageable; import org.springframework.data.jpa.repository.jpaspecificationexecutor; import org.springframework.data.jpa.repository.query; import org.springframework.data.repository.pagingandsortingrepository; import org.springframework.data.repository.query.param; import org.springframework.stereotype.repository; @repository public interface tuserdao extends pagingandsortingrepository<tuser, long>, jpaspecificationexecutor<tuser> { tuser findbyusername(string username); @query("from tuser t where id = :id") list<tuser> queryfamilylist(@param("id") long id, pageable pageable); }
十一、service和controller没啥好说的,跟原先的一样,下面再提供一个单元测试的demo
import java.util.list; import javax.persistence.entitymanager; import org.junit.test; import org.junit.runner.runwith; import org.springframework.beans.factory.annotation.autowired; import org.springframework.boot.test.springapplicationconfiguration; import org.springframework.test.context.junit4.springjunit4classrunner; import org.springframework.test.context.web.webappconfiguration; import com.alibaba.fastjson.json; import com.golden.application; import com.golden.dao.tuserdao; import com.golden.entity.tuser; import com.golden.util.generatepageable; @runwith(springjunit4classrunner.class) //指定我们springboot工程的application启动类 @springapplicationconfiguration(classes = application.class) //由于是web项目,junit需要模拟servletcontext,因此我们需要给我们的测试类加上@webappconfiguration @webappconfiguration public class utiltest { @autowired private tuserdao dao; @autowired private entitymanager em; @test public void test1(){ dao.findbyusername("admin"); } @test public void test2(){ // 使用jpa提供的分页类 java.util.list<order> list = new arraylist<sort.order>(); order order = new order(direction.desc, "createtime"); list.add(order); sort sort = new sort(list); pageable pageable = new pagerequest(0, 10, sort); page<tuser> findall = dao.findall(pageable); } @test public void test3(){ entitymanager em = dao.getentitymanager(); query query = em.createnativequery("select * from t_user limit 1"); object singleresult = query.getsingleresult(); system.out.println(singleresult); } /* //执行原生sql query nativequery = em.createnativequery(string sql); //指定返回对象类型 nativequery.unwrap(sqlquery.class).setresulttransformer(transformers.aliastobean( class resulttype)); //返回对象 list<t> resultlist = nativequery.getresultlist(); */ }
后记:
不用druid的可以把有关druid的配置全部删掉,swagger的同理
这里没有使用hibernate.cfg.xml配置文件,主要习惯了在实体类里配置字段了,不怎么用hibernate的映xml文件了,但其实配置起来跟springmvc项目一样
说实话这里使用jpa操作数据库,没感觉有多方便,因为总有各种奇葩的需求,当然也可能是我没深入研究,所以建议改用mybatis,这个我会再写一篇springboot加mybatis的配置教程的,最后,还可以使用原生的sql查询,即使用单元测试里的entitymanager对象去执行sql,返回结果可以指定对象类型,也很方便
还需要注意的一个点是静态文件的存放位置,这个跟原先的项目不一样,原先是在webapp下,但springboot是默认放在resources下的static目录下的,还有其他默认目录和配置,自行搜索
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: vue设置浏览器顶部小图标
下一篇: 快应用页面带参数跳转