MacOS10.12+JDK8u133+Git2.10+Maven3.3.9+Tomcat8.5+MySQL5.7
SpringBoot1.5.4.RELEASE+SpringCloud Dalston.SRL
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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>com.ekeyfund.springcloudgroupId>
<artifactId>springcloud-eureka-serverartifactId>
<version>0.0.1-SNAPSHOTversion>
<packaging>jarpackaging>
<name>springcloud-eureka-servername>
<description>SpringCloud Eureka Serverdescription>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>1.5.4.RELEASEversion>
<relativePath/>
parent>
<properties>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8project.reporting.outputEncoding>
<java.version>1.8java.version>
<spring-cloud.version>Dalston.SR1spring-cloud.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-eureka-serverartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-dependenciesartifactId>
<version>${spring-cloud.version}version>
<type>pomtype>
<scope>importscope>
dependency>
dependencies>
dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
plugins>
build>
project>
application.properties
##定义注册中心服务的端口
server.port=8888
#定义注册中心服务的ip
eureka.instance.hostname=127.0.0.1
#不向注册中心注册自己
eureka.client.register-with-eureka=false
#注册中心的职责就是维护服务的实例,并不需要检索服务
eureka.client.fetch-registry=false
## 注册中心的访问地址
eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/
启动类
package com.ekeyfund.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@EnableEurekaServer //启用Eureka 注册中心
@SpringBootApplication
public class SpringcloudEurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(SpringcloudEurekaServerApplication.class, args);
}
}
访问地址:http://127.0.0.1:8888/eureka/
说明:为了保证项目的完整性,这里会使用SpringBoot的JPA,Web模块提供一个完整的RestFulAPI的例子。
包含User,Department,Role三个实体类
package com.ekeyfund.springcloud.entity;
import com.fasterxml.jackson.annotation.JsonBackReference;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.springframework.format.annotation.DateTimeFormat;
import javax.persistence.*;
import java.util.Date;
import java.util.List;
/**
* User Entity
*
* @author Liuguanglei [email protected]
* @create 2017-06-下午2:32
*/
@Entity
@Table(name = "springboot_user")
public class User {
@Id
@Column(name = "user_id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "user_name")
private String name;
@Column(name = "user_password")
private String password;
@Column(name = "user_create_date")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createDate;
@ManyToOne
@JoinColumn(name = "department_id")
@JsonBackReference
private Department department;
@ManyToMany(cascade = {},fetch = FetchType.EAGER)
@JoinTable(name = "springboot_user_role",joinColumns = {@JoinColumn(name="user_id")},
inverseJoinColumns = {@JoinColumn(name = "role_id")}
)
private List roleList;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Date getCreateDate() {
return createDate;
}
public void setCreateDate(Date createDate) {
this.createDate = createDate;
}
public Department getDepartment() {
return department;
}
public void setDepartment(Department department) {
this.department = department;
}
public List getRoleList() {
return roleList;
}
public void setRoleList(List roleList) {
this.roleList = roleList;
}
@Override
public String toString() {
return new ToStringBuilder(this)
.append("id", id)
.append("name", name)
.append("password", password)
.append("createDate", createDate)
.append("department", department)
.append("roleList", roleList)
.toString();
}
}
Department.java
package com.ekeyfund.springcloud.entity;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import javax.persistence.*;
/**
* Department Entity
*
* @author Liuguanglei [email protected]
* @create 2017-06-下午2:31
*/
@Entity
@Table(name = "springboot_department")
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class Department {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "department_id")
private Long id;
@Column(name = "department_name")
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return new ToStringBuilder(this)
.append("id", id)
.append("name", name)
.toString();
}
}
Role.java
package com.ekeyfund.springcloud.entity;
import javax.persistence.*;
/**
* Role Entity
*
* @author Liuguanglei [email protected]
* @create 2017-06-下午2:36
*/
@Entity
@Table(name = "springboot_role")
public class Role {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "role_id")
private Long id;
@Column(name = "role_name")
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return new org.apache.commons.lang3.builder.ToStringBuilder(this)
.append("id", id)
.append("name", name)
.toString();
}
}
主要是UserRepository和DepartmentRepository
UserRepository.java
package com.ekeyfund.springcloud.repository;
import com.ekeyfund.springcloud.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.Collection;
import java.util.Date;
import java.util.List;
/**
* User Repository
*
* @author Liuguanglei liugl@ekeyfund.com
* @create 2017-06-下午2:54
*/
@Repository
public interface UserRepository extends JpaRepository{
/**
* and
* @param id
* @param name
* @return
*/
User findByIdAndName(Long id, String name);
User findByNameAndPassword(String name, String password);
/**
* or
* @param id
* @param name
* @return
*/
User findByIdOrName(Long id, String name);
/**
* between
* @param start
* @param end
* @return
*/
List findByCreateDateBetween(Date start, Date end);
/**
* lessThan
* @param start
* @return
*/
List getByCreateDateLessThan(Date start);
/**
* Greater Than
* @param start
* @return
*/
List findByCreateDateGreaterThan(Date start);
/**
* is null
* @return
*/
List findByNameIsNull();
/**
* in
* @param nameList
* @return
*/
List findByNameIn(Collection nameList);
}
DepartmentRepository.java
package com.ekeyfund.springcloud.repository;
import com.ekeyfund.springcloud.entity.Department;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
/**
* Created by tony on 2017/6/19.
*/
@Repository
public interface DepartmentRepository extends JpaRepository {
}
主要包含UserService,UserServiceImpl,DepartmentService,DepartmentServiceImpl
UserService.java
package com.ekeyfund.springcloud.service;
import com.ekeyfund.springcloud.entity.User;
import java.util.List;
/**
* Created by tony on 2017/6/19.
*/
public interface UserService {
/**
* 登录
* @param name
* @param password
* @return
*/
public User login(String name, String password);
/**
* 注册
* @param user
* @return
*/
public User register(User user);
/**
* 注销
* @param user
* @return
*/
void writeOff(User user);
/**
* 当前用户是否已经存在
* @param user
* @return
*/
boolean isExists(User user);
List getAllUser();
User getUserById(Long id);
}
UserServiceImpl.java
package com.ekeyfund.springcloud.service.impl;
import com.ekeyfund.springcloud.entity.User;
import com.ekeyfund.springcloud.repository.UserRepository;
import com.ekeyfund.springcloud.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.transaction.Transactional;
import java.util.List;
/**
* User Service Impl
*
* @author Liuguanglei [email protected]
* @create 2017-06-下午3:34
*/
@Service
@Transactional
public class UserServiceImpl implements UserService {
@Autowired
private UserRepository userRepository;
@Override
public User login(String name, String password) {
return userRepository.findByNameAndPassword(name,password);
}
@Override
public User register(User user) {
return userRepository.save(user);
}
@Override
public void writeOff(User user) {
userRepository.delete(user);
}
@Override
public boolean isExists(User user) {
return userRepository.findOne(user.getId())!=null?true:false;
}
@Override
public List getAllUser() {
return userRepository.findAll();
}
@Override
public User getUserById(Long id) {
return userRepository.findOne(id);
}
}
DepartmentService.java
package com.ekeyfund.springcloud.service;
import com.ekeyfund.springcloud.entity.Department;
/**
* Created by tony on 2017/6/19.
*/
public interface DepartmentService {
Department saveDepartment(Department department);
Department getDepartmentById(Long id);
}
DepartmentServiceImpl.java
package com.ekeyfund.springcloud.service.impl;
import com.ekeyfund.springcloud.entity.Department;
import com.ekeyfund.springcloud.repository.DepartmentRepository;
import com.ekeyfund.springcloud.service.DepartmentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.transaction.Transactional;
/**
* Department Impl
*
* @author Liuguanglei [email protected]
* @create 2017-06-下午3:12
*/
@Transactional
@Service
public class DepartmentImpl implements DepartmentService {
@Autowired
private DepartmentRepository departmentRepository;
@Override
public Department saveDepartment(Department department) {
return departmentRepository.save(department);
}
@Override
public Department getDepartmentById(Long id) {
return departmentRepository.findOne(id);
}
}
UserController.java
package com.ekeyfund.springcloud.controller;
import com.ekeyfund.springcloud.entity.User;
import com.ekeyfund.springcloud.service.UserService;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.*;
import java.util.Date;
import java.util.List;
/**
* UserController
* Restful API
* @author Liuguanglei [email protected]
* @create 2017-06-下午11:24
*/
@RestController
public class UserController {
private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(UserController.class);
@Autowired
private DiscoveryClient discoveryClient;
@Autowired
private UserService userService;
@RequestMapping(value = "/user/list",method = RequestMethod.GET)
public List list(){
List serviceInstanceList= discoveryClient.getInstances("user-service");
ServiceInstance instance=discoveryClient.getLocalServiceInstance();
LOGGER.info("call user/list service host is "+instance.getHost()+"service_id is "+instance.getServiceId());
return userService.getAllUser();
}
@RequestMapping(value = "/user/register",method = RequestMethod.POST)
public String register(@ModelAttribute User user){
User result =userService.register(user);
return result!=null?"success":"fail";
}
@RequestMapping(value = "/user/get/{id}")
public User get(@PathVariable Long id){
return userService.getUserById(id);
}
@RequestMapping(value = "/user/update/{id}",method = RequestMethod.PUT)
public String update(@PathVariable Long id,@ModelAttribute User user){
User updatedUser =userService.getUserById(id);
updatedUser.setName(user.getName());
updatedUser.setPassword(user.getPassword());
updatedUser.setCreateDate(new Date());
User result= userService.register(updatedUser);
return result!=null?"success":"fail";
}
@RequestMapping(value = "/user/delete/{id}",method = RequestMethod.DELETE)
public String delete(@PathVariable Long id){
User user =new User();
user.setId(id);
userService.writeOff(user);
return "success";
}
}
JPAConfiguration.java
package com.ekeyfund.springcloud.configuration;
import com.alibaba.druid.pool.DruidDataSource;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaDialect;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.Properties;
/**
* JPA Persistence Configuration
*
* @author Liuguanglei [email protected]
* @create 2017-06-上午11:26
*/
@Order(Ordered.HIGHEST_PRECEDENCE)
@Configuration
@EnableTransactionManagement(proxyTargetClass = true) //启用JPA的事务管理
@EnableJpaRepositories(basePackages = "com.ekeyfund.springcloud.repository" )//启用JPA资源库并指定资源库接口位置
@EntityScan(basePackages = "com.ekeyfund.springcloud.entity")//指定实体的位置
public class JPAPersistenceConfiguration {
private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(JPAPersistenceConfiguration.class);
/*******************数据库和连接池配置信息,读取application.properties文件的属性值****************************/
@Value("${spring.datasource.driver-class-name}")
private String driverClass;
@Value("${spring.datasource.username}")
private String userName;
@Value("${spring.datasource.password}")
private String password;
@Value("${spring.datasource.url}")
private String url;
@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 long maxWait;
@Value("${spring.datasource.timeBetweenEvictionRunsMillis}")
private long timeBetweenEvictionRunsMillis;
@Value("${spring.datasource.minEvictableIdleTimeMillis}")
private long minEvictableIdleTimeMillis;
@Value("${spring.datasource.filters}")
private String filters;
@Value("${spring.datasource.connectionProperties}")
private String connectionProperties;
@Bean(name = "druidDataSource",initMethod = "init",destroyMethod = "close")
public DataSource dataSource(){
DruidDataSource druidDataSource =new DruidDataSource();
druidDataSource.setDriverClassName(driverClass);
druidDataSource.setUsername(userName);
druidDataSource.setPassword(password);
druidDataSource.setUrl(url);
druidDataSource.setInitialSize(initialSize);
druidDataSource.setMinIdle(minIdle);
druidDataSource.setMaxActive(maxActive);
druidDataSource.setMaxWait(maxWait);
druidDataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
druidDataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
druidDataSource.setConnectionProperties(connectionProperties);
try {
druidDataSource.setFilters(filters);
} catch (SQLException e) {
LOGGER.error("build datasoure exception ",e.getMessage());
}
return druidDataSource;
}
@Bean(name = "entityManagerFactory")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource druidDataSource){
LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBean =new LocalContainerEntityManagerFactoryBean();
localContainerEntityManagerFactoryBean.setDataSource(druidDataSource);
localContainerEntityManagerFactoryBean.setPackagesToScan("com.ekeyfund.springcloud.entity");
localContainerEntityManagerFactoryBean.setJpaProperties(buildHibernateProperties());
localContainerEntityManagerFactoryBean.setJpaDialect(new HibernateJpaDialect());
localContainerEntityManagerFactoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter(){
{
setDatabase(org.springframework.orm.jpa.vendor.Database.MYSQL);
setDatabasePlatform("org.hibernate.dialect.MySQL5Dialect");
}
});
return localContainerEntityManagerFactoryBean;
}
@Bean
public PlatformTransactionManager transactionManager(DataSource druidDataSource, EntityManagerFactory entityManagerFactory){
JpaTransactionManager jpaTransactionManager=new JpaTransactionManager();
jpaTransactionManager.setDataSource(druidDataSource);
jpaTransactionManager.setEntityManagerFactory(entityManagerFactory);
return jpaTransactionManager;
}
@Bean
PersistenceExceptionTranslationPostProcessor persistenceExceptionTranslationPostProcessor(){
return new PersistenceExceptionTranslationPostProcessor();
}
protected Properties buildHibernateProperties(){
Properties hibernateProperties =new Properties();
hibernateProperties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");
hibernateProperties.setProperty("hibernate.hbm2ddl.auto","update");
hibernateProperties.setProperty("hibernate.show_sql", "false");
hibernateProperties.setProperty("hibernate.use_sql_comments", "false");
hibernateProperties.setProperty("hibernate.format_sql", "true");
hibernateProperties.setProperty("hibernate.generate_statistics", "false");
hibernateProperties.setProperty("javax.persistence.validation.mode", "none");
//Audit History flags
hibernateProperties.setProperty("org.hibernate.envers.store_data_at_delete", "true");
hibernateProperties.setProperty("org.hibernate.envers.global_with_modified_flag", "true");
hibernateProperties.setProperty("hibernate.cache.use_second_level_cache", "true");
hibernateProperties.setProperty("hibernate.cache.region.factory_class", "org.hibernate.cache.ehcache.EhCacheRegionFactory");
hibernateProperties.setProperty("hibernate.cache.use_query_cache", "true");
return hibernateProperties;
}
}
主要包含application.properties和logback-spring.xml以及ehcache.xml
application.properties
##DataSource Config
##\u6570\u636e\u5e93\u8fde\u63a5\u6c60\u4fe1\u606f\u914d\u7f6e
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/springboot?characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=guanglei
# \u4e0b\u9762\u4e3a\u8fde\u63a5\u6c60\u7684\u8865\u5145\u8bbe\u7f6e\uff0c\u5e94\u7528\u5230\u4e0a\u9762\u6240\u6709\u6570\u636e\u6e90\u4e2d
# \u521d\u59cb\u5316\u5927\u5c0f\uff0c\u6700\u5c0f\uff0c\u6700\u5927
spring.datasource.initialSize=5
spring.datasource.minIdle=5
spring.datasource.maxActive=20
# \u914d\u7f6e\u83b7\u53d6\u8fde\u63a5\u7b49\u5f85\u8d85\u65f6\u7684\u65f6\u95f4
spring.datasource.maxWait=60000
# \u914d\u7f6e\u95f4\u9694\u591a\u4e45\u624d\u8fdb\u884c\u4e00\u6b21\u68c0\u6d4b\uff0c\u68c0\u6d4b\u9700\u8981\u5173\u95ed\u7684\u7a7a\u95f2\u8fde\u63a5\uff0c\u5355\u4f4d\u662f\u6beb\u79d2
spring.datasource.timeBetweenEvictionRunsMillis=60000
# \u914d\u7f6e\u4e00\u4e2a\u8fde\u63a5\u5728\u6c60\u4e2d\u6700\u5c0f\u751f\u5b58\u7684\u65f6\u95f4\uff0c\u5355\u4f4d\u662f\u6beb\u79d2
spring.datasource.minEvictableIdleTimeMillis=300000
spring.datasource.validationQuery=SELECT 1 FROM DUAL
spring.datasource.testWhileIdle=true
spring.datasource.testOnBorrow=false
spring.datasource.testOnReturn=false
# \u6253\u5f00PSCache\uff0c\u5e76\u4e14\u6307\u5b9a\u6bcf\u4e2a\u8fde\u63a5\u4e0aPSCache\u7684\u5927\u5c0f
spring.datasource.poolPreparedStatements=true
spring.datasource.maxPoolPreparedStatementPerConnectionSize=20
# \u914d\u7f6e\u76d1\u63a7\u7edf\u8ba1\u62e6\u622a\u7684filters\uff0c\u53bb\u6389\u540e\u76d1\u63a7\u754c\u9762sql\u65e0\u6cd5\u7edf\u8ba1\uff0c'wall'\u7528\u4e8e\u9632\u706b\u5899
spring.datasource.filters=stat,wall,log4j
# \u901a\u8fc7connectProperties\u5c5e\u6027\u6765\u6253\u5f00mergeSql\u529f\u80fd\uff1b\u6162SQL\u8bb0\u5f55
spring.datasource.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
# \u5408\u5e76\u591a\u4e2aDruidDataSource\u7684\u76d1\u63a7\u6570\u636e
#spring.datasource.useGlobalDataSourceStat=true
# druid \u8bbf\u95ee\u5730\u5740 http://host:port/druid/index.html
##Log Config
logging.config=classpath:logback-spring.xml
## SpringData JPA Config
spring.jpa.database=mysql
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
#设置服务名称
spring.application.name=user-service
#指定服务注册中心的地址 ###高可用改造后可以加上多个注册中心的地址
eureka.client.service-url.defaultZone=http://127.0.0.1:8888/eureka/,http://127.0.0.1:9999/eureka/
#指定服务提供者的端口
server.port=8080
logback-spring.xml
<configuration>
<property name="APP_ID" value="SpringCloud-Eureka-User-Service-Provider"/>
<property name="LOG_PATH" value="logs">property>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} %-4relative [%thread] %-5level %logger{35} - %msg %npattern>
encoder>
appender>
<appender name="FILE_LOG"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>DEBUGlevel>
filter>
<file>${LOG_PATH}/${APP_ID}/access.logfile>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_PATH}/${APP_ID}/access.log.%d{yyyy-MM-dd}.zip
fileNamePattern>
<maxHistory>10maxHistory>
rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} %-4relative [%thread] %-5level %logger{35} - %msg%npattern>
encoder>
appender>
<appender name="FILE_DEBUG"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>DEBUGlevel>
<onMatch>ACCEPTonMatch>
<onMismatch>DENYonMismatch>
filter>
<file>${LOG_PATH}/${APP_ID}/access_debug.logfile>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_PATH}/${APP_ID}/access_debug.log.%d{yyyy-MM-dd}.zip
fileNamePattern>
<maxHistory>10maxHistory>
rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} %-4relative [%thread] %-5level %logger{35} - %msg%npattern>
encoder>
appender>
<appender name="FILE_INFO"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFOlevel>
<onMatch>ACCEPTonMatch>
<onMismatch>DENYonMismatch>
filter>
<file>${LOG_PATH}/${APP_ID}/access_info.logfile>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_PATH}/${APP_ID}/access_info.log.%d{yyyy-MM-dd}.zip
fileNamePattern>
<maxHistory>10maxHistory>
rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} %-4relative [%thread] %-5level %logger{35} - %msg%npattern>
encoder>
appender>
<appender name="FILE_WARN"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>WARNlevel>
<onMatch>ACCEPTonMatch>
<onMismatch>DENYonMismatch>
filter>
<file>${LOG_PATH}/${APP_ID}/access_warn.logfile>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_PATH}/${APP_ID}/access_warn.log.%d{yyyy-MM-dd}.zip
fileNamePattern>
<maxHistory>10maxHistory>
rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} %-4relative [%thread] %-5level %logger{35} - %msg%npattern>
encoder>
appender>
<appender name="FILE_ERROR"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERRORlevel>
<onMatch>ACCEPTonMatch>
<onMismatch>DENYonMismatch>
filter>
<file>${LOG_PATH}/${APP_ID}/access_error.logfile>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_PATH}/${APP_ID}/access_error.log.%d{yyyy-MM-dd}.zip
fileNamePattern>
<maxHistory>10maxHistory>
rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} %-4relative [%thread] %-5level %logger{35} - %msg%npattern>
encoder>
appender>
<appender name="ASYNC_LOG" class="ch.qos.logback.classic.AsyncAppender">
<discardingThreshold>0discardingThreshold>
<queueSize>512queueSize>
<appender-ref ref="FILE_LOG"/>
appender>
<appender name="ASYNC_LOG" class="ch.qos.logback.classic.AsyncAppender">
<discardingThreshold>0discardingThreshold>
<queueSize>512queueSize>
<appender-ref ref="FILE_LOG"/>
appender>
<appender name="ASYNC_LOG_DEBUG" class="ch.qos.logback.classic.AsyncAppender">
<discardingThreshold>0discardingThreshold>
<queueSize>512queueSize>
<appender-ref ref="FILE_DEBUG"/>
appender>
<appender name="ASYNC_LOG_INFO" class="ch.qos.logback.classic.AsyncAppender">
<discardingThreshold>0discardingThreshold>
<queueSize>512queueSize>
<appender-ref ref="FILE_INFO"/>
appender>
<appender name="ASYNC_LOG_WARN" class="ch.qos.logback.classic.AsyncAppender">
<discardingThreshold>0discardingThreshold>
<queueSize>512queueSize>
<appender-ref ref="FILE_WARN"/>
appender>
<appender name="ASYNC_LOG_ERROR" class="ch.qos.logback.classic.AsyncAppender">
<discardingThreshold>0discardingThreshold>
<queueSize>512queueSize>
<appender-ref ref="FILE_ERROR"/>
appender>
<root level="INFO">
<appender-ref ref="STDOUT"/>
<appender-ref ref="ASYNC_LOG"/>
<appender-ref ref="ASYNC_LOG_DEBUG"/>
<appender-ref ref="ASYNC_LOG_INFO"/>
<appender-ref ref="ASYNC_LOG_WARN"/>
<appender-ref ref="ASYNC_LOG_ERROR"/>
root>
<logger name="org.springframework" level="INFO"/>
configuration>
ehcache.xml
-- Sets the path to the directory where cache .data files are created.
If the path is a Java System Property it is replaced by
its value in the running VM.
The following properties are translated:
user.home - User's home directory
user.dir - User's current working directory
java.io.tmpdir - Default temp file path -->
--
指定一个目录:当 EHCache 把数据写到硬盘上时, 将把数据写到这个目录下.
-->
"tempDirectory"/>
--Default Cache configuration. These will applied to caches programmatically created through
the CacheManager.
The following attributes are required for defaultCache:
maxInMemory - Sets the maximum number of objects that will be created in memory
eternal - Sets whether elements are eternal. If eternal, timeouts are ignored and the element
is never expired.
timeToIdleSeconds - Sets the time to idle for an element before it expires. Is only used
if the element is not eternal. Idle time is now - last accessed time
timeToLiveSeconds - Sets the time to live for an element before it expires. Is only used
if the element is not eternal. TTL is now - creation time
overflowToDisk - Sets whether elements can overflow to disk when the in-memory cache
has reached the maxInMemory limit.
-->
--
设置缓存的默认数据过期策略
-->
"10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
/>
--
设定具体的命名缓存的数据过期策略。每个命名缓存代表一个缓存区域
缓存区域(region):一个具有名称的缓存块,可以给每一个缓存块设置不同的缓存策略。
如果没有设置任何的缓存区域,则所有被缓存的对象,都将使用默认的缓存策略。即:
Hibernate 在不同的缓存区域保存不同的类/集合。
对于类而言,区域的名称是类名。如:com.ekeyfund.springboot.jpa.entity.User
对于集合而言,区域的名称是类名加属性名。如com.ekeyfund.springboot.jpa.entity.User.roleList
-->
--
name: 设置缓存的名字,它的取值为类的全限定名或类的集合的名字
maxElementsInMemory: 设置基于内存的缓存中可存放的对象最大数目
eternal: 设置对象是否为永久的, true表示永不过期,
此时将忽略timeToIdleSeconds 和 timeToLiveSeconds属性; 默认值是false
timeToIdleSeconds:设置对象空闲最长时间,以秒为单位, 超过这个时间,对象过期。
当对象过期时,EHCache会把它从缓存中清除。如果此值为0,表示对象可以无限期地处于空闲状态。
timeToLiveSeconds:设置对象生存最长时间,超过这个时间,对象过期。
如果此值为0,表示对象可以无限期地存在于缓存中. 该属性值必须大于或等于 timeToIdleSeconds 属性值
overflowToDisk:设置基于内存的缓存中的对象数目达到上限后,是否把溢出的对象写到基于硬盘的缓存中
-->
name="com.ekeyfund.springcloud.entity.Department"
maxElementsInMemory="1"
eternal="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
overflowToDisk="true"
/>
name="com.ekeyfund.springcloud.entity.User"
maxElementsInMemory="1000"
eternal="true"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
overflowToDisk="false"
/>
name="com.ekeyfund.springcloud.entity.Role"
maxElementsInMemory="1000"
eternal="true"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
overflowToDisk="false"
/>
启动类
package com.ekeyfund.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@EnableDiscoveryClient //启动服务发现
@SpringBootApplication
public class SpringcloudEurekaProviderApplication {
public static void main(String[] args) {
SpringApplication.run(SpringcloudEurekaProviderApplication.class, args);
}
}
运行该类,并刷新服务注册中心,会发现新增user-service服务,如下图:
高可用的实现主要在于配置文件,这里模拟高可用的场景是单台机器部署了两个服务注册中心。
这里使用了application.properties,application-master.properties和application-slave.properties,使用springboot的多环境配置特性来激活两个注册中心,其配置如下:
application-master.properties
spring.application.name=eureka-server
server.port=8888
eureka.instance.hostname=127.0.0.1
eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:9999/eureka/
application-slave.properties
spring.application.name=eureka-server
server.port=9999
eureka.instance.hostname=127.0.0.1
eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:8888/eureka/
application.properties
spring.profiles.active=master
##使用ip地址的形式定义注册中心的地址
eureka.instance.prefer-ip-address=true
服务注册提供者配置和之前的不同在于eureka.client.service-url.defaultZone增加了多个地址。
#设置服务名称
spring.application.name=user-service
#指定服务注册中心的地址 ###高可用改造后可以加上多个注册中心的地址
eureka.client.service-url.defaultZone=http://127.0.0.1:8888/eureka/,http://127.0.0.1:9999/eureka/
#指定服务提供者的端口
server.port=8080
为了模拟高可用,这里准备了两个启动类:
SpringcloudEurekaServerMasterApplication
package com.ekeyfund.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
/**
* Eureka高可用 Master Server
*/
@EnableEurekaServer //启用Eureka 注册中心
@SpringBootApplication
public class SpringcloudEurekaServerMasterApplication {
public static void main(String[] args) {
SpringApplication.run(SpringcloudEurekaServerMasterApplication.class, args);
}
}
SpringcloudEurekaServerSlaveApplication
package com.ekeyfund.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
/**
* Eureka高可用 Slave Server
*/
@EnableEurekaServer //启用Eureka 注册中心
@SpringBootApplication
public class SpringcloudEurekaServerSlaveApplication {
public static void main(String[] args) {
SpringApplication.run(SpringcloudEurekaServerSlaveApplication.class, args);
}
}
可以通过修改application.properties文件中的spring.profiles.active属性来分别启动,然后访问http://127.0.0.1:8888或者是127.0.0.1:9999,会看到eureka-service注册中心成功注册到两个注册中心上,如下图:
http://127.0.0.1:8888
当启动SpringcloudEurekaProviderApplication后
访问 http://127.0.0.1:8888
就可以看到应用USER-SERVICE注册到高可用的注册中心EUREKA-SERVICE上了。