springboot+kotlin+springcloud+java+grade+maven混编?
springboot + maven + java vs springboot + gradle + kotlin
springclould:netflix:
java:
pom.xml:
<?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.fly</groupId>
<artifactId>springboot01</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.1.RELEASE</version>
<relativePath/>
</parent>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--能通过注解的方式,在编译时自动为属性生成构造器、getter/setter、equals、hashcode、toString方法-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!--通用mapper
已包含jdbc mybatis
-->
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
<version>2.0.3</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
kotlin:
build.gradle:
buildscript {
ext {
kotlinVersion = '1.2.71'
springBootVersion = '2.1.1.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlinVersion}")
classpath("org.jetbrains.kotlin:kotlin-allopen:${kotlinVersion}")
}
}
apply plugin: 'kotlin'
apply plugin: 'kotlin-spring'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
compileKotlin {
kotlinOptions {
freeCompilerArgs = ["-Xjsr305=strict"]
jvmTarget = "1.8"
}
}
compileTestKotlin {
kotlinOptions {
freeCompilerArgs = ["-Xjsr305=strict"]
jvmTarget = "1.8"
}
}
repositories {
mavenCentral()
}
dependencies {
implementation('org.springframework.boot:spring-boot-starter-web')
implementation('com.fasterxml.jackson.module:jackson-module-kotlin')
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("tk.mybatis:mapper-spring-boot-starter:2.0.3")
implementation("mysql:mysql-connector-java:5.1.6")
testImplementation('org.springframework.boot:spring-boot-starter-test')
}
java:8088
kotlin:8089
application.yml:
server:
port: 8088
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/mybatisdemo
username: root
password: root
hikari: # jdbc默认连接池
maximum-pool-size: 20
minimum-idle: 10
mybatis:
type-aliases-package: com.fly.pojo
logging:
level:
com.fly.service: error
App:
java:
@SpringBootApplication
@MapperScan("com.fly.mapper")
public class App {
public static void main(String[] args){
SpringApplication.run(App.class,args);
}
} kotlin: @SpringBootApplication
@MapperScan("com.fly.mapper")
class Application{
@Bean
fun restTemplate():RestTemplate = RestTemplate()
} fun main(args: Array<String>) {
// SpringApplication.run(Application::class.java,*args)
runApplication<Application>(*args)
}
pojo.User:
java:
@Data
@Table(name = "user")
public class User {
@Id
@KeySql(useGeneratedKeys = true)//插入的表以自增列为主键
@GeneratedValue(strategy = GenerationType.IDENTITY)//主键生成策略
@Column(name = "id")
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
}
kotlin:
@Table(name = "user")
data class User(
@Id
@KeySql(useGeneratedKeys = true)
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
var id: Int? = null,
var username: String? = null,
var birthday: Date? = null,
var sex: String? = null,
var address: String? = null
)
UserMapper:
java:
public interface UserMapper extends Mapper<User> {
}
kotlin:
interface UserMapper:Mapper<User>
UserService:
java:
@Service
public class UserService {
@Resource
private UserMapper userMapper; public List<User> selectAll(){
return userMapper.selectAll();
} @Transactional
public void insert(User user){
userMapper.insert(user);
}
}
kotlin:
@Service
class UserService {
@Resource
lateinit var userMapper:UserMapper
fun selectAll():List<User> = userMapper.selectAll()
@Transactional
fun insert(user: User) = userMapper.insert(user)
}
UserController:
java:
@RestController
public class UserController {
@Resource
private UserMapper userMapper; private final UserService userService;
@Autowired
public UserController(UserService userService) {
this.userService = userService;
} @GetMapping("/")
public List<User> selectAll(){
return userService.selectAll();
}
@GetMapping("/{id}")
public User selectById(@PathVariable("id")int id){
return userMapper.selectByPrimaryKey(id);
}
}
kotlin:
@RestController
class UserController {
@Autowired
lateinit var userService: UserService
@Autowired
lateinit var restTemplate:RestTemplate
@GetMapping
fun selectAll(): List<User> = userService.selectAll()
@GetMapping("/{id}")
fun httpSelectAll(@PathVariable("id") id:Int):User?{
return restTemplate.getForObject("http://localhost:8088/"+id, User::class.java)
}
}
MyInterceptor:
java:
/**
* 拦截器
*/
@Slf4j
public class MyInterceptor implements HandlerInterceptor {
// private Logger log = LoggerFactory.getLogger(MyInterceptor.class);
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.info("preHandle......");
return true;
} @Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
log.info("postHandle.....");
} @Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
log.info("afterCompletion.....");
}
}
kotlin:
class MyInterceptor :HandlerInterceptor{
var log:Logger = LoggerFactory.getLogger(MyInterceptor::class.java)
override fun preHandle(request: HttpServletRequest, response: HttpServletResponse, handler: Any): Boolean {
log.info("preHandle......")
return true
}
override fun postHandle(request: HttpServletRequest, response: HttpServletResponse, handler: Any, modelAndView: ModelAndView?) {
log.info("postHandle......")
}
override fun afterCompletion(request: HttpServletRequest, response: HttpServletResponse, handler: Any, ex: Exception?) {
log.info("afterCompletion......")
}
}
MvcConfig:
java:
/**
* 注册拦截器
*/
@Configuration
public class MvcConfig implements WebMvcConfigurer {
@Bean
public MyInterceptor myInterceptor(){
return new MyInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
//注册拦截器,添加拦截路径
registry.addInterceptor(myInterceptor()).addPathPatterns("/**");
}
}
kotlin:
@Configuration
class MvcConfig :WebMvcConfigurer{
@Bean
fun myInterceptor():MyInterceptor = MyInterceptor()
override fun addInterceptors(registry: InterceptorRegistry) {
registry.addInterceptor(myInterceptor()).addPathPatterns("/**")
}
}
测试:
java:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = App.class)//()内容可省略
public class UserServiceTest {
@Autowired
private UserService userService;
@Test
public void test() {
List<User> list = userService.selectAll();
for (User user : list) {
System.out.println(user);
}
}
@Test
public void test1(){
User user = new User();
user.setUsername("测试a");
user.setBirthday(new Date());
user.setSex("1");
user.setAddress("A");
userService.insert(user);
}
}
kotlin:
@RunWith(SpringRunner::class)
@SpringBootTest(classes = arrayOf(Application::class))
class UserServiceTest {
@Autowired
lateinit var userService:UserService
@Test
fun test(){
val list:List<User> = userService.selectAll()
for (user in list) {
println(user)
}
}
@Test
fun test1(){
val user = User()
user.username = "Kotlin111"
user.address = "K"
user.sex = "1"
user.birthday = Date()
userService.insert(user)
}
}
netflix:
Eureka:注册中心
grade+java搭建eureka服务,客户端分别为上面的java+kotlin
eureka服务端:
build.gradle:
buildscript {
ext {
springBootVersion = '2.1.1.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
group = 'com.fly'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
mavenCentral()
maven { url "https://repo.spring.io/milestone" }
}
ext['springCloudVersion'] = 'Greenwich.RC2'
dependencies {
implementation('org.springframework.cloud:spring-cloud-starter-netflix-eureka-server')
testImplementation('org.springframework.boot:spring-boot-starter-test')
}
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}
}
application.yml:
server:
port: 8761 # 默认8761
spring:
application:
name: eureka-server
eureka:
client:
register-with-eureka: false # 注册自己的信息到EurekaServer
fetch-registry: false # 拉取其它服务的信息
service-url:
defaultZone: http://127.0.0.1:${server.port}/eureka
server:
eviction-interval-timer-in-ms: 60000 # 扫描失效服务的间隔时间 失效剔除 单位是毫秒,生成环境不要修改
enable-self-preservation: false # 关闭自我保护 默认为true
EurekaApplication:
@SpringBootApplication
@EnableEurekaServer
public class EurekaApplication {
public static void main(String[] args){
SpringApplication.run(EurekaApplication.class,args);
}
}
客户端:
java:
pom.xml:
<!--Eureka客户端-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
application.yml:
server:
port: 8088
spring:
application:
name: springboot01
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/mybatisdemo
username: root
password: root
hikari: # jdbc默认连接池
maximum-pool-size: 20
minimum-idle: 10
mybatis:
type-aliases-package: com.fly.pojo
logging:
level:
com.fly.service: error
eureka:
client:
service-url: # EurekaServer地址
defaultZone: http://127.0.0.1:8761/eureka
registry-fetch-interval-seconds: 30 # 默认值 获取服务列表
instance:
prefer-ip-address: true # 当其它服务获取地址时提供ip而不是hostname
ip-address: 127.0.0.1 # 指定自己的ip信息,不指定的话会自己寻找
# 修改服务续约的行为
lease-expiration-duration-in-seconds: 90 # 服务失效时间,默认值90秒
lease-renewal-interval-in-seconds: 30 # 服务续约(renew)的间隔,默认为30秒
instance-id: ${spring.application.name} + ${server.port} # 默认显示的信息${hostname}:${spring.application.name}:${server.port}
App部分:
@SpringBootApplication
//@EnableEurekaClient //开启eureka客户端
@EnableDiscoveryClient //客户端,支持多种
@MapperScan("com.fly.mapper")
public class App {
服务的消费方:
build.gradle:
implementation('org.springframework.cloud:spring-cloud-starter-netflix-eureka-client:2.0.2.RELEASE')
application.yml:
server:
port: 8089
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/mybatisdemo
username: root
password: root
application:
name: demo
main:
allow-bean-definition-overriding: true # 同名bean覆盖
mybatis:
type-aliases-package: com.fly.pojo
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:8761/eureka
registry-fetch-interval-seconds: 30 # 默认值 获取服务列表
instance:
prefer-ip-address: true
ip-address: 127.0.0.1
Application.kt:
@SpringBootApplication
@EnableEurekaClient
@MapperScan("com.fly.mapper")
class Application{
@Bean
fun restTemplate():RestTemplate = RestTemplate()
}
fun main(args: Array<String>) {
// SpringApplication.run(Application::class.java,*args)
runApplication<Application>(*args)
}
UserService:
@Autowired
lateinit var restTemplate: RestTemplate
@Autowired
lateinit var discoveryClient:DiscoveryClient
fun queryUserById(id: Int):User?{
// 根据服务名称,获取服务实例
// 因为只有一个UserService,因此我们直接get(0)获取
val instances = discoveryClient.getInstances("springboot01").get(0)
// 获取ip和端口信息
val url:String = "http://"+instances.host + ":" + instances.port +"/"+ id
return restTemplate.getForObject(url, User::class.java)
}
UserController:
@GetMapping("/user/{id}")
fun eurekaQueryUserById(@PathVariable("id") id: Int):User?{
return userService.queryUserById(id)
}
Ribbon:负载均衡:
负载均衡:
spring-cloud 的 netfix已经包含,无需再导入
org.springframework.cloud:spring-cloud-starter-netflix-ribbon
Application.kt:
@Bean
@LoadBalanced // 开启负载均衡
fun restTemplate():RestTemplate = RestTemplate()
UserService:
// 负载均衡 使用 @LoadBalanced
fun queryUserById(id: Int):User?{
// url直接写服务名,LoadBalancerInterceptor会根据服务名获取服务实例的ip与端口
val url = "http://springboot01/"
return restTemplate.getForObject(url+id, User::class.java)
}
重试机制
build.gradle:
// 重试机制
implementation('org.springframework.retry:spring-retry:1.2.2.RELEASE')
application.yml部分:
server:
port: 8089
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/mybatisdemo
username: root
password: root
application:
name: demo
main:
allow-bean-definition-overriding: true # 同名bean覆盖
cloud:
loadbalancer:
retry:
enabled: true # 开启Spring Cloud的重试功能
springboot01: # 服务名称 负载均衡规则的配置入口
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 默认轮训 值为IRule的实现类
ConnectTimeout: 250 # Ribbon的连接超时时间
ReadTimeout: 1000 # Ribbon的数据读取超时时间
OkToRetryOnAllOperations: true # 是否对所有操作都进行重试
MaxAutoRetriesNextServer: 1 # 切换实例的重试次数
MaxAutoRetries: 1 # 对当前实例的重试次数
Hystix:熔断器:
熔断器:
build.gradle:
//熔断器
implementation('org.springframework.cloud:spring-cloud-starter-netflix-hystrix:2.0.2.RELEASE')
Application.kt:
//@SpringBootApplication
//@EnableCircuitBreaker //熔断
//@EnableDiscoveryClient //注册客户端
//@EnableEurekaClient
@SpringCloudApplication //包含上面前3
UserService部分:
@Service
//@DefaultProperties(defaultFallback = "queryUserByIdFallBack")
class UserService {
@Autowired
lateinit var restTemplate: RestTemplate
// 负载均衡 使用 @LoadBalanced
@HystrixCommand(fallbackMethod = "queryUserByIdFallBack") //失败回滚 默认是1000毫秒
// @HystrixCommand(commandProperties =
// [HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1000")] //超时时间
// )
// @HystrixCommand
fun queryUserById(id: Int):User?{
val begin:Long = System.currentTimeMillis()
// url直接写服务名,LoadBalancerInterceptor会根据服务名获取服务实例的ip与端口
val url = "http://springboot01/"
val user:User? = restTemplate.getForObject(url+id, User::class.java)
val end:Long = System.currentTimeMillis()
val t:Long = end - begin
println("访问时间:$t")
return user
}
fun queryUserByIdFallBack():User?{
val user = User()
user.username = "服务器太拥挤了!!!"
return user
}
fun queryUserByIdFallBack(id: Int):User?{
val user = User()
user.username = "服务器太拥挤了!!!"
return user
}
配置文件方式配置:
application.yml:
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 3000 # 设置hystrix的超时时间为3000ms
服务提供方模拟超时:
@GetMapping("/")
public List<User> selectAll(){
return userService.selectAll();
}
@GetMapping("/{id}")
public User selectById(@PathVariable("id")int id) throws InterruptedException {
Thread.sleep(2000L); //模拟超时
return userMapper.selectByPrimaryKey(id);
}
断路器配置:
@HystrixCommand(commandProperties =
[
//具体参数位置 HystrixCommandProperties.java
/* 状态机的三种状态
* Closed:关闭状态(断路器关闭),所有请求都正常访问
* Open:打开状态(断路器打开),所有请求都被降级,hystix会对请求情况进行计数,当失败的百分比达到阀值
* ,则触发熔断,断路器完全关闭
* Half Open:半开状态,Closed状态不是永久的,关闭后会进入休眠,随后断路器自动进入半开状态,
* 此时会释放部分请求通过。若请求是健康的,则会完全打开断路器,否则保持关闭,再进行休眠计时
*
* */
HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1000"), //执行超时时间 默认1000
HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"), // 触发熔断器的最小请求次数 默认20
HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "10000"), // 休眠时长 默认5000毫秒
HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "50") //触发熔断的失败请求最小占比 默认50%
] //超时时间
)
Feign:服务调用:
Feign:(伪装)
build.gradle:
// feign
implementation('org.springframework.cloud:spring-cloud-starter-openfeign:2.0.2.RELEASE')
Application.kt:
@EnableFeignClients // 开启Feign功能
feign,熔断器设置:
UserFeignClient:
@FeignClient(value = "springboot01",fallback = UserFeignClientFallback::class,configuration = [FeignConfig::class])
interface UserFeignClient {
@GetMapping("/{id}")
fun feignQueryUserById(@PathVariable("id")id:Int): User
}
UserFeignClientFallback:
@Component
class UserFeignClientFallback:UserFeignClient {
override fun feignQueryUserById(id: Int): User {
val user = User()
user.username = "未知用户???"
return user
}
}
UserController:
@Resource
lateinit var userFeignClient: UserFeignClient
@GetMapping("/feignUser/{id}")
fun feignQueryUserById(@PathVariable("id") id: Int):User{
return userFeignClient.feignQueryUserById(id)
}
负载均衡,熔断器,日志设置:
application.yml:
feign:
hystrix:
enabled: true # 开启Feign的熔断功能 默认关闭
ribbon: # feign的ribbon的配置 也可以使用上面ribbon的配置方式
ConnectTimeout: 250 # 连接超时时间(ms)
ReadTimeout: 3000 # 通信超时时间(ms)
# OkToRetryOnAllOperations: true # 是否对所有操作都进行重试
# MaxAutoRetriesNextServer: 1 # 同一服务不同实例的重试次数
# MaxAutoRetries: 1 # 同一实例的重试次数
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 4000 # 设置hystrix的超时时间为 ms
logging: # 日志级别
level:
com.fly: debug
请求压缩:
feign:
compression:
request:
enabled: true # 开启请求压缩
mime-types: text/html,application/xml,application/json # 设置压缩的数据类型 默认
min-request-size: 2048 # 设置触发压缩的大小下限 默认
response:
enabled: true # 开启响应压缩
Zuul:服务网关:
面向服务:
pom.xml:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.1.RELEASE</version>
</parent>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
<!--Eureka客户端依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
</dependencies>
ZuulApplication:
@SpringBootApplication
@EnableZuulProxy //开启Zuul的功能
@EnableDiscoveryClient
public class ZuulApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulApplication.class, args);
}
}
application.yml:
server:
port: 9901
spring:
application:
name: zuul
#zuul:
# routes:
# springboot01: # 路由id,随意写 将 /user/**开头的请求,代理到http://127.0.0.1:8087
# path: /user/** # 这里是映射路径
## url: http://127.0.0.1:8087 # 映射路径对应的实际url地址
# serviceId: springboot01 # 指定服务名称 ,会利用Ribbon进行负载均衡访问
# 简化的路由配置
#zuul:
# routes:
# springboot01: springboot01/** # 服务名与映射地址相同可以省略
# 路由前缀
zuul:
# prefix: /api # 添加路由前缀
routes:
springboot01:
path: /user/**
serviceId: springboot01
retryable: true # 重试 默认false
# ignored-services: # 忽略的服务
# - springboot02
# - springboot03
# 熔断
ribbon: # ribbon的配置 详见 AbstractRibbonCommand.java
ConnectTimeout: 250 # 连接超时时间(ms) 默认1000
ReadTimeout: 2000 # 通信超时时间(ms) 默认1000
OkToRetryOnAllOperations: true # 是否对所有操作重试
MaxAutoRetriesNextServer: 1 # 同一服务不同实例的重试次数 默认1
MaxAutoRetries: 0 # 同一实例的重试次数 默认0
# 负载均衡
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 6000 # 熔断超时时长:6000ms > (ReadTimeout+ConnectTimeout)*2,ribbon默认重试1次
# ribbonTimeout = (ribbonReadTimeout + ribbonConnectTimeout) * (maxAutoRetries + 1) * (maxAutoRetriesNextServer + 1)
# (250 + 2000)* (0+1)*(1+1)
eureka:
client:
service-url: # EurekaServer地址
defaultZone: http://127.0.0.1:8761/eureka
registry-fetch-interval-seconds: 30 # 默认值 获取服务列表
instance:
prefer-ip-address: true # 当其它服务获取地址时提供ip而不是hostname
ip-address: 127.0.0.1 # 指定自己的ip信息,不指定的话会自己寻找
自定义过滤器:
/**
* 自定义过滤器
*/
@Component
public class LoginFilter extends ZuulFilter {
@Override
public String filterType() {//返回字符串,代表过滤器的类型
/**
* - pre:请求在被路由之前执行
* - routing:在路由请求时调用
* - post:在routing和errror过滤器之后调用
* - error:处理请求时发生错误调用
*/
// return "pre";
return FilterConstants.PRE_TYPE;
}
@Override
public int filterOrder() {//通过返回的int值来定义过滤器的执行顺序,数字越小优先级越高
return FilterConstants.PRE_DECORATION_FILTER_ORDER - 1;//4
}
@Override
public boolean shouldFilter() {//返回一个`Boolean`值,判断该过滤器是否需要执行。返回true执行,返回false不执行
return true;
}
@Override
public Object run() throws ZuulException {//过滤器的具体业务逻辑
// 获取Zuul提供的请求上下文对象
RequestContext context = RequestContext.getCurrentContext();
// 从上下文中获取request对象
HttpServletRequest request = context.getRequest();
String token = request.getParameter("user-token");
//判断是否存在
if (StringUtils.isBlank(token)){
context.setSendZuulResponse(false);
context.setResponseStatusCode(HttpStatus.FORBIDDEN.value());//403
}
return null;
}
}
springboot+kotlin+springcloud+java+grade+maven混编?的更多相关文章
- Java与groovy混编 —— 一种兼顾接口清晰和实现敏捷的开发方式
有大量平均水平左右的"工人"可被选择.参与进来 -- 这意味着好招人 有成熟的.大量的程序库可供选择 -- 这意味着大多数项目都是既有程序库的拼装,标准化程度高而定制化场景少 开发 ...
- Processing与Java混编初探
Processing其实是由Java开发出的轻量级JAVA开发语言,主要用于做原型,有setup.draw两个主接口和几个消息相应接口 Processing和Java混编很简单...在Java中引入外 ...
- Android与JS混编(js调用java)
项目中需要使用android与js的混编来开发app. 下面就介绍一下吧. 有时候我们需要用js调用native控件,要想实现这个功能,我们需要做的就只有三步: 1.允许webview执行js脚本 2 ...
- springboot与springcloud版本不对应导致报错java.lang.NoSuchMethodError: org.springframework.boot.builder.SpringApplicationBuilder.<init>([Ljava/lang/Object;)V
springboot启动报错: 10:31:50.221 [main] ERROR org.springframework.boot.SpringApplication - Application r ...
- spring-boot+spring-cloud+maven-module 一个 maven多模块的微服务架构模版
spring-boot-cloud-module spring-boot+spring-cloud+maven-module 一个 maven多模块的微服务架构模版. 新手上路的绝佳模版,只有必要的配 ...
- 使用Java类加载SpringBoot、SpringCloud配置文件
我们都知道平常在使用SpringBoot和SpringCloud的时候,如果需要加载一两个配置文件的话我们通常使用@Value("${属性名称}")注解去加载.但是如果配置文件属性 ...
- springboot集成springcloud,启动时报错java.lang.AbstractMethodError: null
出现这个问题是springboot和springcloud的版本不匹配. 我此处使用了springboot 2.0.4.RELEASE,springcloud 使用了Finchley.SR2. 修改方 ...
- springboot与springcloud的关系
1 . 问题描述 随着springboot.springcloud的不断迭代升级,开发效率不断提升,越来越多的开发团队加入到spring的大军中,今天用通俗的语言,介绍下什么是springboot,s ...
- 什么是微服务,SpringBoot和SpringCloud的关系和区别
什么是微服务? 就目前而言对于微服务业界没有一个统一的,标准的定义.但通常而言,微服务是一种架构模式或者说是一种架构风格,它提倡单一应用程序划分为一组小的服务,每个服务在其独立的自己的进程中,服务之间 ...
随机推荐
- ubuntu16.10安装网易云音乐
首先去官网(https://music.163.com/#/download)下载安装包:netease-cloud-music_1.1.0_amd64_ubuntu.deb 下载好以后,执行安装命令 ...
- OO Summary Ⅲ
规格化设计的发展历史 (这一部分并没有找到答案,于是参考了好黄和温莎莎的blogs) 1950年代,第一次分离,主程序和子程序的分离程序结构模型是树状模型,子程序可先于主程序编写.通过使用库函数来简化 ...
- [整理]Kadane算法
仅能操作一次时,需每次观察是否有为负情况置零.多次操作时,仅需判断是否后者大于前者. leetcode 53.121.122 [代码] class Solution { public int maxS ...
- vsts 管理 持续集成 跟自动化测试
1.代理池: 在服务器上,打开你的TFS Web站点,并转到管理页的代理池页面.如: https://www.cnblogs.com/atwind/p/5486881.html 低版本无法生成高版本. ...
- CentOS7调整home盘空间到根目录
1:解除挂载 umount /home 如报错: [root@zabbix-hk-01 home]# umount /home umount: /home:目标忙. (有些情况下通过 lsof(8) ...
- 「版本升级」MyEclipse CI 2018.12.0正式发布
新版本MyEclipse为WildFly 14新增一个新的服务器连接器,改进性能并新增一些Java 10修复程序.新版本为IDE做了几个核心修复,这是MyEclipse 2018一个更棒的升级. [M ...
- 缓存一致性协议 mesi
m : modified e : exlusive s : shared i : invalid 四种状态的转换略过,现在讨论为什么有了这个协议,i++在多线程上还不是安全的. 两个cpu A B同时 ...
- uiautomator2 获取APP Toast内容
前言:appium必须是1.6以上的版本 环境(安装和安装都可以运行成功,我也不确定要不要这个): 1.抓到toast需要安装uiautomator2,安装npm:npm install -g cnp ...
- array_multisort
项目中用到这个函数了 ,起初对这个函数一直是懵逼状态,文档都看的朦朦胧胧的 网上无意间看到这篇文章 ,写的超级详细,收藏了 . 当然要先放原地址:https://www.cnblogs.com/WuN ...
- Python pandas快速入门
Python pandas快速入门2017年03月14日 17:17:52 青盏 阅读数:14292 标签: python numpy 数据分析 更多 个人分类: machine learning 来 ...