今天给各位同学带来的是如何搭建多Module的springboot项目的实现步骤。这篇文章会比基础篇相对复杂,如果是第一次接触springboot的同学建议先阅读 java 搭建基于springboot的ssh(spring + springmvc + hibernate)的gradle项目(基础篇) 或java 搭建基于springboot的ssm(spring + springmvc + mybatis)的maven项目 做一个初步的了解。好了,废话不多说。直接切入正题。
在实际开发中,为了降低耦合性,提高代码复用性,我们一般会将web层与service分开。将web层看做一个war, 再将service以及dao层的后面一系列操作看做一个jar。这样即降低了耦合性(当web层挂掉不会影响到service层使用,反之也成立),也提高了代码复用性(即多个web都需要使用同一套service到dao中的某一个功能,只要web层对该jar进行依赖即可,无需重复写同一个功能N遍)。好了,解释一下为什么要这样做,进入操作步骤。
操作步骤
最终实现效果
创建三个Module分别为Teacher、Student以及SchoolInfo-Service。Teacher和Student同时依赖SchoolInfo-Service分别取出所需数据。**
创建父类
好了 创建出了一个最原始的gradle项目,如下图所示
我们来将无用的文件进行删除,清理后如下图所示
创建Teacher
首先在springbootmodules右键创建module
此时我们可以看一下settings中的内容,会发现将新创建的teacher自动添加到了其中
接下来 我们将teacher改造成springboot格式,改造后如下图所示(如果不懂为什么要这样改造,可阅读我上面提到文章,里面有详细的解释)
build.gradle
group 'com.beyondli'
version '1.0-SNAPSHOT'
apply plugin: 'java'
apply plugin: 'war'
buildscript {
ext {
//指定版本
springBootVersion = '1.5.4.RELEASE'
}
repositories {
//选择远程仓库
mavenCentral()
}
dependencies {
//springboot核心jar
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
//springboot所需jar
compile('org.springframework.boot:spring-boot-starter-web')
//测试
testCompile('org.springframework.boot:spring-boot-starter-test')
}
TeacherApplication
package com.beyondli;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class TeacherApplication {
public static void main(String[] args) {
SpringApplication.run(TeacherApplication.class, args);
}
}
application.properties(因为一会要开启两个controller,防止端口相同冲突,所以自定义一下端口,在这里啰嗦一句,springboot默认会读取application.properties中的内容,所以配置文件名字一定要是这个,当然也可以我们来自定义,这个等以后的文章中我们会讲到)
#定义服务器端口
server.port=8086
TeacherController
package com.beyondli.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* Created by beyondLi on 2017/7/26.
*/
@RestController
@RequestMapping(value = "/teacher")
public class TeacherController {
@RequestMapping(value = "/getInfo")
public String getInfo(){
return "success";
}
}
我们来测试一下第一个Module,测试结果如下
第一个Module创建成功,现在让我们来快速创建Student,因为不存在业务逻辑且与Teacher基本相似,不做过多赘述。
创建Student
与Teacher一样,不做赘述。修改成不同端口即可。
创建SchoolInfo-Service
创建后结构如下
config中是自定义读取application-schoolinfo.properties文件中的配置。因为需要配置数据源,但是最终我们是需要student和teacher都依赖schoolservice的,如果我们将数据源配置写在controller层需要在每一个controller Module中都添加这份配置,很是麻烦,但是如果service中我们还使用默认的application.properties也是无法读取到的。因为我们不是直接启动的service,所以需要多一个LoadProperties来读取我们本身service的配置文件。
各代码如下
LoadProperties
package com.beyondli.config;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
//加载时读取某配置文件配置
@PropertySource(value = "application-schoolinfo.properties")
@Component
public class LoadProperties {
}
SchoolRepository
package com.beyondli.dao;
import com.beyondli.domain.Student;
import com.beyondli.domain.Teacher;
/**
* Created by beyondLi on 2017/7/26.
*/
public interface SchoolRepository {
/**
* 获取学生信息
* @return
*/
Student getStudentInfo();
/**
* 获取老师信息
* @return
*/
Teacher getTeacherInfo();
}
SchoolRepositoryImpl
package com.beyondli.dao;
import com.beyondli.domain.Student;
import com.beyondli.domain.Teacher;
import org.springframework.stereotype.Repository;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
/**
* Created by beyondLi on 2017/7/26.
*/
@Repository
public class SchoolRepositoryImpl implements SchoolRepository {
@PersistenceContext
EntityManager entityManager;
@Override
public Student getStudentInfo() {
return (Student) entityManager.createQuery("FROM Student").getResultList().get(0);
}
@Override
public Teacher getTeacherInfo() {
return (Teacher) entityManager.createQuery("FROM Teacher").getResultList().get(0);
}
}
SchoolService
package com.beyondli.service;
import com.beyondli.domain.Student;
import com.beyondli.domain.Teacher;
/**
* Created by beyondLi on 2017/7/26.
*/
public interface SchoolService {
/**
* 获取学生信息
* @return
*/
Student getStudnetInfo();
/**
* 获取老师信息
* @return
*/
Teacher getTeacherInfo();
}
SchoolServiceImpl
package com.beyondli.service;
import com.beyondli.dao.SchoolRepository;
import com.beyondli.domain.Student;
import com.beyondli.domain.Teacher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* Created by beyondLi on 2017/7/26.
*/
@Service
public class SchoolServiceImpl implements SchoolService{
@Autowired
SchoolRepository schoolRepository;
/**
* 获取学生信息
* @return
*/
@Override
public Student getStudnetInfo() {
return schoolRepository.getStudentInfo();
}
/**
* 获取老师信息
* @return
*/
@Override
public Teacher getTeacherInfo() {
return schoolRepository.getTeacherInfo();
}
}
Teacher
package com.beyondli.domain;
import javax.persistence.*;
/**
* Created by beyondLi on 2017/7/25.
*/
@Entity
@Table(name = "teacher")
public class Teacher {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Integer id;
@Column(name = "name")
private String name;
@Column(name = "age")
private Integer age;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
Student
package com.beyondli.domain;
import javax.persistence.*;
/**
* Created by beyondLi on 2017/7/25.
*/
@Entity
@Table(name = "teacher")
public class Teacher {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Integer id;
@Column(name = "name")
private String name;
@Column(name = "age")
private Integer age;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
application-schoolinfo.properties
spring.datasource.url=jdbc:mysql://localhost:3306/modules
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driverClassName=com.mysql.jdbc.Driver
此时要将之间创建的两个Module(student和teacher)进行微调
StudentController
package com.beyondli.controller;
import com.beyondli.domain.Student;
import com.beyondli.service.SchoolService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* Created by beyondLi on 2017/7/26.
*/
@RestController
@RequestMapping(value = "/student")
public class StudentController {
@Autowired
SchoolService schoolService;
@RequestMapping(value = "/getInfo")
public Student getInfo(){
return schoolService.getStudnetInfo();
}
}
application.properties
#定义服务器端口
server.port=8087
spring.jpa.database = mysql
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
TeacherController
package com.beyondli.controller;
import com.beyondli.domain.Teacher;
import com.beyondli.service.SchoolService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* Created by beyondLi on 2017/7/26.
*/
@RestController
@RequestMapping(value = "/teacher")
public class TeacherController {
@Autowired
SchoolService schoolService;
@RequestMapping(value = "/getInfo")
public Teacher getInfo(){
return schoolService.getTeacherInfo();
}
}
application.properties
#定义服务器端口
server.port=8086
spring.jpa.database = mysql
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
各自的build.gradle添加依赖
测试结果如下,先分别在两个表中插入一条数据。之后进行测试,结果如下
好了 大功告成了。我们以后会进行例如多数据源、aop、redis等一系列功能的添加,都会使用现在这种分布式来搭建项目,所以还是希望各位同学可以自己将这套简单的demo搭建成功,因为文件较多,怕博客中有疏漏,这个demo的代码下载链接为:http://pan.baidu.com/s/1pLqfDwv 密码:k1i0。
以上观点均属个人理解,如有错误或不足,望指出,共同成长。