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的关系和区别
什么是微服务? 就目前而言对于微服务业界没有一个统一的,标准的定义.但通常而言,微服务是一种架构模式或者说是一种架构风格,它提倡单一应用程序划分为一组小的服务,每个服务在其独立的自己的进程中,服务之间 ...
随机推荐
- web service简述,通俗易懂----转
一.Web Service简介 1.1.Web Service基本概念 Web Service也叫XML Web Service WebService是一种可以接收从Internet或者Intrane ...
- Android 音视频深入 二 AudioTrack播放pcm(附源码下载)
本篇项目地址,名字是录音和播放PCM,求starhttps://github.com/979451341/Audio-and-video-learning-materials 1.AudioTrack ...
- Django+Xadmin+Echarts动态获取数据legend颜色显示灰色问题已解决
前段时间做的使用Django的Xadmin后台和百度Echarts进行后台数据可视化,功能虽然实现,展示出来的legend图例,都是灰色的,只有鼠标放上去才会显示彩色的.百度都快被我刨穿了,看到有类似 ...
- Kafka.net使用编程入门(三)
这个世界既不是有钱人的世界,也不是有权人的世界,它是有心人的世界. 一些有用的命令 1.列出主题:kafka-topics.bat --list --zookeeper localhost:2181 ...
- ural1517
题解: 后缀数组 求一下最长公共字串 代码: #include<cstdio> #include<cmath> #include<algorithm> #inclu ...
- 【原创】<Debug> QT头文件
[Error] No such file or directory [Solution] 参考: http://blog.csdn.net/donglynn/article/details/21804 ...
- Ant在Java项目中的使用(一眼就看会)
参考:http://www.cnblogs.com/zhengqiang/p/5557155.html Ant是跨平台的构建工具,它可以实现项目的自动构建和部署等功能.在本文中,主要让读者熟悉怎样将A ...
- Python Select模型(程序流程)(转)
缘由 之前写socket的CS模型代码,都是利用最原始的多线程方式.服务端是主线程,接到客户端的连接请求就从线程池中获取一个线程去处理整个socket连接的所有操作,虽然在连接数较短的情况下没有什么影 ...
- 50个常用的Linux命令
1.tar tar -xvf archive_name.tar 解压文件 tar -cvf archive_name.tar file 把文件file压缩成archive_name.tar tar ...
- mac下python2.7升级到3.6
1. 前言 Mac系统自带python2.7,本文目的是将自带的python升级到3.6版本. 网上有本多的做法是让python2.7和python3.X两个版本共存,博主并不知道,是两版本共存好,还 ...