Spring Boot + Jpa(Hibernate) 架构基本配置详解
1、基于springboot-1.4.0.RELEASE版本测试
2、springBoot+hibernate+Druid+MySQL+servlet(jsp)
不废话,直接上代码
一、maven的pom文件
4.0.0 com.zsx demo war 0.0.1 zsxMavenWebapp http://maven.apache.org UTF-8 1.7 7.0.69 org.springframework.boot spring-boot-starter-parent 1.4.0.RELEASE org.apache.tomcat.embed tomcat-embed-jasper javax.servlet jstl org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-data-jpa mysql mysql-connector-java org.springframework.boot spring-boot-starter-tomcat provided org.springframework.boot spring-boot-devtools com.alibaba fastjson 1.2.16 com.alibaba druid 1.0.25 org.apache.poi poi 3.14 org.springframework.boot spring-boot-starter-test test io.springfox springfox-swagger2 2.6.0 io.springfox springfox-swagger-ui 2.6.0 / org.springframework.boot spring-boot-maven-plugin org.springframework springloaded 1.2.6.RELEASE ali aliRepository http://maven.aliyun.com/nexus/content/groups/public/ false
二、项目架构
想想还是介绍一下项目的目录结构,这样方便梳理整体的架构配置
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=SELECT1FROMDUAL 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 #JPAConfiguration: spring.jpa.database=MYSQL #Showornotlogforeachsqlquery spring.jpa.show-sql=false spring.jpa.generate-ddl=true #Hibernateddlauto(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
packagecom.zsx; importorg.springframework.boot.SpringApplication; importorg.springframework.boot.autoconfigure.SpringBootApplication; importorg.springframework.boot.web.servlet.ServletComponentScan; @SpringBootApplication @ServletComponentScan//扫描使用注解方式的servlet publicclassApplication{ publicstaticvoidmain(String[]args){ SpringApplication.run(Application.class,args); } }
若需要部署到外部的tomcat容器中,则添加下面类即可。
packagecom.zsx; importorg.slf4j.Logger; importorg.slf4j.LoggerFactory; importorg.springframework.boot.SpringApplication; importorg.springframework.boot.builder.SpringApplicationBuilder; importorg.springframework.boot.context.web.SpringBootServletInitializer; /** *修改启动类,继承SpringBootServletInitializer并重写configure方法 *@authorZSX * */ publicclassSpringBootStartApplicationextendsSpringBootServletInitializer{ privatestaticfinalLoggerlogger=LoggerFactory.getLogger(SpringBootStartApplication.class); @Override protectedSpringApplicationBuilderconfigure(SpringApplicationBuilderbuilder){ returnbuilder.sources(Application.class); } }
五、数据库连接池Druid的配置
packagecom.zsx.common.config; importjava.sql.SQLException; importjavax.sql.DataSource; importorg.springframework.beans.factory.annotation.Value; importorg.springframework.context.annotation.Bean; importorg.springframework.context.annotation.Configuration; importorg.springframework.context.annotation.Primary; importcom.alibaba.druid.pool.DruidDataSource; /** *DruidDBConfig类被@Configuration标注,用作配置信息; *DataSource对象被@Bean声明,为Spring容器所管理, *@Primary表示这里定义的DataSource将覆盖其他来源的DataSource。 *@authorZSX *jdbc.url=${jdbc.url} *最新的支持方式如下: *jdbc.url=@jdbc.url@ */ @Configuration publicclassDruidDBConfig{ //privateLoggerlogger=LoggerFactory.getLogger(DruidDBConfig.class); @Value("${spring.datasource.url}") privateStringdbUrl; @Value("${spring.datasource.username}") privateStringusername; @Value("${spring.datasource.password}") privateStringpassword; @Value("${spring.datasource.driverClassName}") privateStringdriverClassName; @Value("${spring.datasource.initialSize}") privateintinitialSize; @Value("${spring.datasource.minIdle}") privateintminIdle; @Value("${spring.datasource.maxActive}") privateintmaxActive; @Value("${spring.datasource.maxWait}") privateintmaxWait; @Value("${spring.datasource.timeBetweenEvictionRunsMillis}") privateinttimeBetweenEvictionRunsMillis; @Value("${spring.datasource.minEvictableIdleTimeMillis}") privateintminEvictableIdleTimeMillis; @Value("${spring.datasource.validationQuery}") privateStringvalidationQuery; @Value("${spring.datasource.testWhileIdle}") privatebooleantestWhileIdle; @Value("${spring.datasource.testOnBorrow}") privatebooleantestOnBorrow; @Value("${spring.datasource.testOnReturn}") privatebooleantestOnReturn; @Value("${spring.datasource.poolPreparedStatements}") privatebooleanpoolPreparedStatements; @Value("${spring.datasource.maxPoolPreparedStatementPerConnectionSize}") privateintmaxPoolPreparedStatementPerConnectionSize; @Value("${spring.datasource.filters}") privateStringfilters; @Value("{spring.datasource.connectionProperties}") privateStringconnectionProperties; @Bean//声明其为Bean实例 @Primary//在同样的DataSource中,首先使用被标注的DataSource publicDataSourcedataSource(){ DruidDataSourcedatasource=newDruidDataSource(); 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(SQLExceptione){ } datasource.setConnectionProperties(connectionProperties); returndatasource; } }
springboot里默认使用tomcat的上传文件大小限制,即1MB,修改用下面的配置类:
importjavax.servlet.MultipartConfigElement; importorg.springframework.boot.web.servlet.MultipartConfigFactory; importorg.springframework.context.annotation.Bean; importorg.springframework.context.annotation.Configuration; @Configuration publicclassMultipartConfig{ @Bean publicMultipartConfigElementmultipartConfigElement(){ MultipartConfigFactoryfactory=newMultipartConfigFactory(); factory.setMaxFileSize("10MB"); factory.setMaxRequestSize("10MB"); returnfactory.createMultipartConfig(); } }
六、开启Druid的数据库监控配置
1、配置Filter
importjavax.servlet.annotation.WebFilter; importjavax.servlet.annotation.WebInitParam; importcom.alibaba.druid.support.http.WebStatFilter; /** *配置druid监控统计功能 *配置Filter *@authorZSX * */ @WebFilter(filterName="druidWebStatFilter",urlPatterns="/*", initParams={ @WebInitParam(name="exclusions",value="*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*")//忽略资源 } ) publicclassDruidStatFilterextendsWebStatFilter{ }
2、配置web访问的servlet
importjavax.servlet.annotation.WebInitParam; importjavax.servlet.annotation.WebServlet; importcom.alibaba.druid.support.http.StatViewServlet; /** *配置druid监控统计功能 *在SpringBoot项目中基于注解的配置,如果是web.xml配置,按规则配置即可 *@authorZSX * */ @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页面上的“ResetAll”功能 } ) publicclassDruidStatViewServletextendsStatViewServlet{ }
这样启动项目后在浏览器中输入地址:端口/druid,就可以看到druid的监控web页面了
七、拦截器配置
importorg.springframework.context.annotation.Configuration; importorg.springframework.web.servlet.config.annotation.InterceptorRegistry; importorg.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; importorg.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; @Configuration publicclassWebAppConfigurerextendsWebMvcConfigurerAdapter{ /** *配置拦截器 */ @Override publicvoidaddInterceptors(InterceptorRegistryregistry){ //TODOAuto-generatedmethodstub //多个拦截器组成一个拦截器链 //addPathPatterns用于添加拦截规则 //excludePathPatterns用户排除拦截 registry.addInterceptor(newAuthInterceptor()).addPathPatterns("/**"); super.addInterceptors(registry); } /** *添加自定义的静态资源映射 这里使用代码的方式自定义目录映射,并不影响SpringBoot的默认映射,可以同时使用。 */ @Override publicvoidaddResourceHandlers(ResourceHandlerRegistryregistry){ //registry.addResourceHandler("/new/**").addResourceLocations("classpath:/new/"); //registry.addResourceHandler("/**").addResourceLocations("/"); super.addResourceHandlers(registry); } }
八、swagger发布api测试配置(可忽略)
importorg.springframework.context.annotation.Bean; importorg.springframework.context.annotation.Configuration; importspringfox.documentation.builders.ApiInfoBuilder; importspringfox.documentation.builders.PathSelectors; importspringfox.documentation.builders.RequestHandlerSelectors; importspringfox.documentation.service.ApiInfo; importspringfox.documentation.spi.DocumentationType; importspringfox.documentation.spring.web.plugins.Docket; importspringfox.documentation.swagger2.annotations.EnableSwagger2; @Configuration @EnableSwagger2 publicclassSwagger2{ @Bean publicDocketcreateRestApi(){ returnnewDocket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) .select() .apis(RequestHandlerSelectors.basePackage("com.zsx.controller.api")) .paths(PathSelectors.any()) .build(); } privateApiInfoapiInfo(){ returnnewApiInfoBuilder() .title("SpringBoot中使用Swagger2构建RESTfulAPIs") .description("描述") .termsOfServiceUrl("http://zsx.com.cn") .version("1.0") .build(); } }
至此,所有的配置已完成,下面是一个操作数据的简单demo
九、实体类
@Entity @Table(name="t_user") publicclassTuserimplementsjava.io.Serializable{ /** * */ privatestaticfinallongserialVersionUID=1L; @Id @GeneratedValue(strategy=GenerationType.IDENTITY) privateLongid; @Column(name="username") privateStringuserName; @Column(name="password") privateStringpassWord; @Column(name="email") privateStringemail; @Column(name="mobile") privateStringmobile; @Column(name="nickname") privateStringnickName; //省略getter和setter }
十、dao层
1、使用jpa基本可以实现不写sql,(但实际开发中,业务逻辑会很复杂,一点不写sql完全不现实)
2、注意添加@Repository注解,添加JpaSpecificationExecutor继承可以方便分页
3、看些jpa的查询语法资料
importjava.util.List; importjava.util.Map; importorg.springframework.data.domain.Pageable; importorg.springframework.data.jpa.repository.JpaSpecificationExecutor; importorg.springframework.data.jpa.repository.Query; importorg.springframework.data.repository.PagingAndSortingRepository; importorg.springframework.data.repository.query.Param; importorg.springframework.stereotype.Repository; @Repository publicinterfaceTuserDaoextendsPagingAndSortingRepository,JpaSpecificationExecutor { TuserfindByUserName(StringuserName); @Query("fromTusertwhereid=:id") List queryFamilyList(@Param("id")Longid,Pageablepageable); }
十一、service和controller没啥好说的,跟原先的一样,下面再提供一个单元测试的demo
importjava.util.List; importjavax.persistence.EntityManager; importorg.junit.Test; importorg.junit.runner.RunWith; importorg.springframework.beans.factory.annotation.Autowired; importorg.springframework.boot.test.SpringApplicationConfiguration; importorg.springframework.test.context.junit4.SpringJUnit4ClassRunner; importorg.springframework.test.context.web.WebAppConfiguration; importcom.alibaba.fastjson.JSON; importcom.golden.Application; importcom.golden.dao.TUserDao; importcom.golden.entity.Tuser; importcom.golden.util.GeneratePageable; @RunWith(SpringJUnit4ClassRunner.class) //指定我们SpringBoot工程的Application启动类 @SpringApplicationConfiguration(classes=Application.class) //由于是Web项目,Junit需要模拟ServletContext,因此我们需要给我们的测试类加上@WebAppConfiguration @WebAppConfiguration publicclassUtilTest{ @Autowired privateTUserDaodao; @Autowired privateEntityManagerem; @Test publicvoidtest1(){ dao.findByUserName("admin"); } @Test publicvoidtest2(){ //使用jpa提供的分页类 java.util.Listlist=newArrayList (); Orderorder=newOrder(Direction.DESC,"createTime"); list.add(order); Sortsort=newSort(list); Pageablepageable=newPageRequest(0,10,sort); Page findAll=dao.findAll(pageable); } @Test publicvoidtest3(){ EntityManagerem=dao.getEntityManager(); Queryquery=em.createNativeQuery("select*fromt_userlimit1"); ObjectsingleResult=query.getSingleResult(); System.out.println(singleResult); } /* //执行原生SQL QuerynativeQuery=em.createNativeQuery(Stringsql); //指定返回对象类型 nativeQuery.unwrap(SQLQuery.class).setResultTransformer(Transformers.aliasToBean(ClassresultType)); //返回对象 List resultList=nativeQuery.getResultList(); */ }
后记:
不用Druid的可以把有关Druid的配置全部删掉,swagger的同理
这里没有使用hibernate.cfg.xml配置文件,主要习惯了在实体类里配置字段了,不怎么用hibernate的映xml文件了,但其实配置起来跟springmvc项目一样
说实话这里使用jpa操作数据库,没感觉有多方便,因为总有各种奇葩的需求,当然也可能是我没深入研究,所以建议改用Mybatis,这个我会再写一篇springboot加mybatis的配置教程的,最后,还可以使用原生的sql查询,即使用单元测试里的EntityManager对象去执行sql,返回结果可以指定对象类型,也很方便
还需要注意的一个点是静态文件的存放位置,这个跟原先的项目不一样,原先是在webapp下,但springboot是默认放在resources下的static目录下的,还有其他默认目录和配置,自行搜索
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。