欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Spring Boot + Jpa(Hibernate) 架构基本配置详解

程序员文章站 2024-02-18 15:49:28
1、基于springboot-1.4.0.release版本测试 2、springboot + hibernate + druid + mysql + servlet(j...

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目录下的,还有其他默认目录和配置,自行搜索

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。