目录
一.安全
1.Spring Security
简介
WebSecurityConfigurerAdapater 自定义security策略
AuthenticationManagerBuilder 自定义认证策略
@EnableWebSecrity 开启WebSecurity模式
Spring Security 的主要两个目标‘认证’Authentication,‘授权’Authorization
具体到Spring Security学习(一)查看
简单使用:
引入Spring Security
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
编写配置类
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
//指定请求规则
http.authorizeRequests().antMatchers("/").permitAll()
.antMatchers("/level1/**").hasRole("VIP1")
.antMatchers("/level2/**").hasRole("VIP2");
//开启自动配置的登录功能
//访问 /login 来到登录界面
//如果登录错误,重定向到 /login?error 表示登录失败
//还可以有更多设置,如登录的用户名,密码
http.formLogin();
//开启注销,并且设置注销后返回的地址
//访问/logout 表示用户注销,清空session
//注销成功会返回 /logout:?logout 页面
http.logout().logoutSuccessUrl("/");
//开启 记住我 功能
//登录成功后,将cookie发给浏览器保存,以后登录带上cookie,只要通过检查就可以免登陆
//点击注销后,会销毁这个cookie
http.rememberMe();
}
//定制认证规则
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("zhangsan").password("123456").roles("VIP1","VIP2")
.and()
.withUser("wangwu").password("123").roles("VIP1");
}
}
配合thymeleaf模板在前端使用
导入maven依赖
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--isAuthenticated()是否认证过(登录过) -->
<div sec:authorize="!isAuthenticated()">
<h1>请先登录!</h1>
</div>
<div sec:authorize="isAuthenticated()">
<form th:action="@{/logout}">
<input type="submit" value="注销"></input>
</form>
</div>
<div sec:authorize="hasRole('VIP1')">
<!--sec:authentication="name" 可以查看用户名 -->
<span sec:authentication="name"></span>,你的VIP1用户,你的角色有:
<!-- sec:authentication="principal.authorities" 可以查看权限角色 -->
<span sec:authentication="principal.authorities"></span>
</div>
</body>
</html>
前面都是用的系统给我们的页面,现在我们想用自己的页面怎么办?
只需要在formLogin()后面添加loginPage 访问页面,usernameParameter,passwordParameter 用户名,密码的传递名字
http.formLogin().loginPage("/userlogin").usernameParameter("user").passwordParameter("pwd");
这个时候,记住我 功能也需要自定义
添加rememberMeParameter参数,规定好名字,在前端使用name属性绑定记住我的选项
http.rememberMe().rememberMeParameter("remember");
二.分布式
1.zookeeper与Dubbo
zookeeper是注册中心,Dubbo是服务
简单使用:
Docker安装zookeeper
下载zookeeper
docker pull zookeeper
查看镜像id
docker images
运行容器
docker run --name zookeepper01 -p 2181:2181 --restart always -d ea93faa92337
开放对应端口的防火墙
firewall-cmd --zone=public --add-port=2181/tcp --permanent
开放后,需要重启一下防火墙
firewall-cmd --reload
如果你的阿里云,还需要去开放一下安全组
springboot简单整合
现在模拟一下购票流程,一个用户模块,一个购票模块。当用户调用购票功能时,会远程调用购票模块的购票功能。
两个模块都需要导入pom依赖
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>0.2.0</version>
</dependency>
生产者
购票模块的Service接口和实现类
public interface TickerService {
void buy();
}
@Service
@Component
public class TickerServiceImpl implements TickerService{
@Override
public void buy() {
System.out.println("买到票了");
}
}
配置文件
spring.application.name=provider-ticket
#如果指定了spring应用名称,可以缺省dubbo的应用名称,这2个至少要配置1个。缺省dubbo的应用名称时默认值是spring的应用名称
#dubbo.application.name=user-service
dubbo.application.name=provider-ticket
#注册中心地址
dubbo.registry.address=zookeeper://xxx.xxx.xxx:2181
#端口号可以写在address中,也可以单独写。实质是从address中获取的port是null,后面设置的port覆盖了null
#dubbo.registry.port=2181
dubbo.protocol.name=dubbo
dubbo.protocol.port=20880
#指定注册到zk上超时时间,ms
dubbo.registry.timeout=10000
#指定实现服务(提供服务)的包
dubbo.scan.base-packages=com.pt.zoodubbo2.service
最后在启动类上加上@EnableDubbo,启动即可
@EnableDubbo
public class ZooDubbo2Application {
消费者
配置类
spring.application.name=provider-user
#如果指定了spring应用名称,可以缺省dubbo的应用名称,这2个至少要配置1个。缺省dubbo的应用名称时默认值是spring的应用名称
#dubbo.application.name=user-service
dubbo.application.name=provider-ticket
#注册中心地址
dubbo.registry.address=zookeeper://xxx.xxx.xxx:2181
创建一个TickerService接口,包路径和接口内容需要和生产者一致。
public interface TickerService {
void buy();
}
消费者方法,只需要使用@Reference 就可以引入远程的TickerService
import com.alibaba.dubbo.config.annotation.Reference;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@Reference
TickerService tickerService;
public void hello(){
tickerService.buy();
}
}
现在运行hello(),调用的tickerService.buy()就是远程的生产者的方法。
2.SpringCloud之eureka
先查看对应的springcloud版本,进行导入
官方springboot与springcloud对应Json数据
简介
SpringCloud是一个分布式整体解决方案,
springcloud分布式开发五大常用组件:
1.服务发现,Netflix Eureke
2.客服端负载均衡 Netflix Ribbon
3.断路器 Netflix Hystrix
4.服务网关 Netflix Zuul
5.分布式配置 Spring Cloud Config
简单使用
1.建立3个模块,一个euraka-server 注册中心, euraka-ticket 服务生产者 , euraka-consumer 服务消费者
2.配置注册中心
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
<version>2.2.6.RELEASE</version>
</dependency>
配置文件application.yml
server:
port: 8761
eureka:
instance:
hostname: eureka-server #eureka实例的主机名
client:
register-with-eureka: false #不把自己注册到eureka上
fetch-registry: false #不从eureka上获取服务的注册信息
service-url: http://localhost:8761/eureka/
启动类上添加@EnableEurekaServer,启动即可
@EnableEurekaServer
public class EurekaServerApplication {
3.服务生产者:
maven依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>2.2.6.RELEASE</version>
</dependency>
yml配置
server:
port: 8001
spring:
application:
name: provider-ticket
eureka:
instance:
prefer-ip-address: true #注册服务的时候,使用的ip地址
client:
service-url: http://localhost:8761/eureka/
运行后就放到注册中心了
4.服务消费者
导入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>2.2.6.RELEASE</version>
</dependency>
编写配置文件
spring:
application:
name: consumer-uer
server:
port: 8200
eureka:
instance:
prefer-ip-address: true #注册服务的时候,使用的ip地址
client:
service-url: http://localhost:8761/eureka/
编写方法进行调用
启动类
@SpringBootApplication
@EnableDiscoveryClient //开启发现服务功能
public class EirakaConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(EirakaConsumerApplication.class, args);
}
@LoadBalanced //使用负载均衡机制
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
控制层方法;
@RestController
public class UserController {
@Autowired
RestTemplate restTemplate;
@RequestMapping("/hello")
public String Buy(){
//第一个参数:http://服务生产者的spring.application.name/xxx
// 第二个参数为返回值类型
return restTemplate.getForObject("http://PROVIDER-TICKET/ticket",String.class);
}
}
就可以实现了;
不过eureka现在已经停止更新了,所以估计以后也会用不着了
三.热部署
不重启应用的情况下,程序可以自动部署,叫做热部署
1.devtools
maven依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
导入后,修改了文件只需要编译一下,就能生效了
四.监控管理
准生产环境下的应用监控和管理功能
maven依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
监控管理端点:
配置文件中
## 启用端点 env
#management.endpoint.env.enabled=true
#
## 暴露端点 env 配置多个,隔开
#management.endpoints.web.exposure.include=env
#方式2:
#方式1中的暴露方式需要一个一个去开启需要暴露的端点,方式2直接开启和暴露所有端点
management.endpoints.web.exposure.include=*
#注意在使用Http访问端点时,需要加上默认/actuator 前缀
#开启shutdown,就可以远程使用post请求关闭应用
management.endpoint.shutdown.enabled=true
暴露端点后就可以访问上面的端点信息了
也可以修改这些端点的访问名字和访问路径
其中/health可以监听应用的健康状态,
其原理是使用了HealthIndicator
如配置了redis,会有一个RedisHealthIndicator,可以监听redis的监控状态。
如何自定义自己的HealthIndicator呢?
实现HealthIndicator 接口,并且放入容器即可。
使用/health查看的时候,会有My的信息
@Component
public class MyHealthIndicator implements HealthIndicator {
@Override
public Health health() {
//自定义检查方法
Health up = Health.up().build();//表示运行正常
Health down = Health.down().build();//表示运行异常
return up;
}
}