SpringBoot
@SpringBootAplication 表示主程序类 或者说是主配置类,表示这是一个sprongboot应用
SpringAplication.run(主程序类名.class,args)启动spring程序
start启动器,直接引入了版本和版本号,可以防止版本冲突。
spring-boot-start-xxx:场景启动器
springboot项目下的扫描的组件必须在主配置类包下,这样才能扫描到容器中
@EnableAutoConfiguration 通过spring.properties文件获取 自动配置类
resource目录结构
static:保存静态资源
templates:保存模板,不支持jsp,但支持模板引擎
application.properties:应用的配置文件 固定文件名
YAML:
1.注意语法,以空格表示层级
2.值有三种:字变量 ” 不会转义,对象,数组
@ConfigurationProperties(prefix=“xxx”):这个注解的作用是将本类的属性与配置文件中属性互相绑定,而且必须使用@Component注册到容器中
添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
@Value注解,注入值 ¥{xxx},从配置文件中获取值,#{SpEL}比如#{11*2}
@Valid 用在类名上用于校验启动JSR303,@Email用于邮箱校验
@PropertySource(value = {"classpath:person.properties"})作用于改变加载默认配置文件
@ImportResource( locations = {"classpath:person.xml"})这个用于主配置类下,用于将配置加入容器中
@Configuration :表明这是一个配置类
profiles作用是在不同条件下使用不同配置:在配置文件中这么设置spring.profiles.active=xxx,配置文件命名规则application-xxx.properties
日志,logging.file=xxx.log
中文编码问题:
spring.http.encoding.force=true
spring.http.encoding.charset=UTF-8
spring.http.encoding.enabled=true
server.tomcat.uri-encoding=UTF-8
SpringBoot对静态资源的映射规则:
1)、webjars,以jar包的形式引入所有都在webjars/,在classpath:/META-INF/resources/webjars。搜索webjar,引入对应的maven坐标
2)、“/”访问当前项目下的所有资源,查找路径,“classpath:/META-INF/resources”,"classpath:/resources/","classpath:/static/","classpath:/public/"
3)、欢迎页面为index.html
4)、所有的**/favicon.ico都是在静态资源文件下
Thymeleaf
1)、引入坐标
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
2)、导入命名空间
<html lang="en" xmlns:th="http://www.thymeleaf.org">
3)、使用语法
th:text:指定文本内容
th:任意html元素
${...}:1.获取对象的属性、调用方法、
2.使用内置对象
3.内置的一些工具对象
/ #{...}:获得国际化内容
@{...}:定义URL链接的
~{...}:片段引用的表达式
视图解析器,只需要自己编写一个视图解析器,容器就会将他加入进来
自动注册Converter:转换器,Formatter:格式化器,
修改SpringBoot默认配置,先看容器中有没有用户自己配置的组件,如果有则导入用户自己配置的组件
1)、WebMvcAutoConfiguration是SpringBoot的自动配置类
2)、在做其他配置时自动导入
3)、WebMvcConfigurer会一起作用
4)、自己写的配置类也会被调用
@EnableMVC 全面接管SpringMVC
WebMvcConfigurerAdapter组件都会一起起作用
@Configuration//配置类
public class MyConfiguration implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/hello").setViewName("index");
}
}
国际化
1)、抽取国际化配置文件,抽取页面需要显示的国际化消息
2)、创建文件i18n,
xxx.properties;
xxx_zh_CN.properties;
person_zh_CN.properties
3)、点击下列Resource Bundle,添加KV
4)、设置国际化资源位置spring.messages.basename=i18n.xxx
5)、去页面获取国际化的值,thymeleaf使用#{xxx}取得国际化的值
MessageSourceAutoConfiguration
国际化原理:获取区域信息对象,localeResolver ,根据request的获取区域信息进行国际化
通过按钮实现语言切换功能@{/index}:,继承LocalResolver,
public class MyLocalResolver implements LocaleResolver {
@Override
public Locale resolveLocale(HttpServletRequest httpServletRequest) {
String i = httpServletRequest.getParameter("l");
Locale locale =Locale.getDefault();
if (!StringUtils.isEmpty(i))
{
String[] split = i.split("_");
locale = new Local(split[0], split[1]);
return locale;
}
return locale;
}
@Override
public void setLocale(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Locale locale) {
}
}
@RequestParam("xxx") 必须提交的参数
spring.thymeleaf.cache=false 将thymeleaf缓存取消。然后按Crtl+F9,更新页面
#xxx使用内置对象
拦截器机制
public class LoginHandleIntercepter implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
Object s = request.getSession().getAttribute("loginUser");
if (s==null)
{
request.setAttribute("msg","没有权限");
request.getRequestDispatcher("/").forward(request,response);
return false;
}else {
return true;
}
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
需要在配置类中添加组件
RestfulCRUD与普通CRUD的区别是,使用特定的请求方式来完成数据操作
spring.mvc.date-format=yyyy-MM-dd HH:mm
指定date格式
@PathVariable("xxx") 获取路径变量的值
<input type = "hidden" name ="_method" value='put" th:if="${emp != null}">
用于修改action请求方式
th:attr="xx=xx" 设置属性创建值
错误处理机制
ErrorMvcAutoConfiguration
BasicErrorController:处理默认的/error请求
ErrorPageCustomizer:作用出现错误以后来到/error请求
DefaultErrorAttributes:作用帮我调用共享页面属性,
timestamp:时间戳
status:状态码
error:错误的提示
exception:异常
message:异常的消息
errors:JSR303数据校验的错误
DefaultErrorViewResolver:解析视图名,定位到/error目录下,根据错误码返回页面。如果模板引擎可以用,就是用模板引擎,如果不行就使用静态路径下的资源。定制错误页面,就把定制页面的名字写为错误状态吗,放在templates下的error文件下,或者命名为4xx或者5xx来代替一类错误页面
总结:一旦系统出现4xx或者5xx之类的错误,ErrorPageCustomizer会生效来到/error请求,而一来到/error请求,就会被BasicErrorController处理请求 (两种请求方式,浏览器和客户端请求,根据请求头区别),响应页面是由DefaultErrorViewResolver解析,
@ControllerAdvice
public class MyEceptionHandler {
@ResponseBody
@ExceptionHandler(MyException.class)
public Map<String, Object> handlerException(Exception e)
{
Map<String, Object> map = new HashMap<>();
map.put("name","zheng");
return map;
}
}
2、错误码页面
@ControllerAdvice
public class MyEceptionHandler {
@ExceptionHandler(MyException.class)
public String handlerException(Exception e, HttpServletRequest request)
{
Map<String, Object> map = new HashMap<>();
request.setAttribute("javax.servlet.error.status_code",400);
map.put("name","zheng");
request.setAttribute("ext",map);
return "forward:/error";
}
}
json数据重建
@Component
public class MyErrorAttribute extends DefaultErrorAttributes {
@Override
public Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean includeStackTrace) {
Map<String, Object> map = super.getErrorAttributes(webRequest, includeStackTrace);
Map<String, Object> map1 = (Map<String, Object>)webRequest.getAttribute("ext", 0);
map.put("ext",map1);
return map;
}
}
注册三大组件
@Configuration
public class MyConfiguration implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/hello").setViewName("index");
}
@Bean
public ServletRegistrationBean myServlet()
{
ServletRegistrationBean<MyServlet> servlet = new ServletRegistrationBean<MyServlet>(new MyServlet(), "/exception");
return servlet;
}
@Bean
public FilterRegistrationBean myFilter()
{
FilterRegistrationBean<MyFilter> filter = new FilterRegistrationBean<MyFilter>();
filter.setFilter(new MyFilter());
filter.setUrlPatterns(Arrays.asList("/exception"));
return filter;
}
@Bean
public ServletListenerRegistrationBean myListener()
{
ServletListenerRegistrationBean<MyListener> listener = new ServletListenerRegistrationBean<>(new MyListener());
return listener;
}
}
docker:提供镜像发布,直接下载容器启用
docker(主机);安装了docker程序的机器
docker(客户端):连接主机进行操作
docker(仓库);用来保存各种软件镜像的地方
docker(镜像):打包好的镜像,放在仓库中
docker(容器):镜像一启动就会创建一个容器
docker命令:
检索 docker search 关键字
下载 docker pull 镜像名
列表:查看本地所有镜像 docker images
删除 docker rmi image-id
容器操作
运行 docker run --name(定义名字) container-name -d(后台运行) image-name(指定镜像模板)
查看容器运行列表:docker ps
查看所有容器列表:docker ps -a
停止容器:docker stopt container-name/container-id
启动容器:docker start container-name/container-id
删除容器:docker rm container-name/container-id
端口映射:-p xxx:xxx 主机端口:容器内部端口
容器日志:docker logs container-name/container-id
使用mysql5.5,创建了容器重启一次服务器
mybatis
spring.datasource.username=root
spring.datasource.password=zheng
spring.datasource.url=jdbc:mysql://207.148.95.94/jdbc
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
@RunWith(SpringRunner.class)
@SpringBootTest
class FirstbootApplicationTests {
@Autowired
DataSource dataSource;
@Test
void contextLoads() throws SQLException {
System.out.println(dataSource.getClass());
Connection connection = dataSource.getConnection();
System.out.println(connection);
connection.close();
}
}
指定数据源类型
spring.datasource.type=org.springframework.jdbc.datasource.DriverManagerDataSource
运行建表语句,运行插入数据语句:schama-.sql, data-.sql
使用druid数据源
第一引入坐标
<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.16</version>
</dependency>
第二,参数设置
spring.datasource.username=root
spring.datasource.password=zheng
spring.datasource.url=jdbc:mysql://207.148.95.94/jdbc
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
第三druid配置
@Configuration
public class DruidConfiguration {
@ConfigurationProperties("spring.datasource")
@Bean
public DruidDataSource dataSource(){
return new DruidDataSource();
}
//配置Durid监控管理
@Bean
public ServletRegistrationBean statViewServlet(){
ServletRegistrationBean<StatViewServlet> bean = new ServletRegistrationBean<>(new StatViewServlet(),"/druid/*");
Map<String,String > map = new HashMap<>();
map.put("loginUsername","admin");
map.put("loginPassword","123456");
map.put("deny","");
map.put("allow","");
bean.setInitParameters(map);
return bean;
}
//web监控的filter
@Bean
public FilterRegistrationBean webStatFilter(){
FilterRegistrationBean<WebStatFilter> bean = new FilterRegistrationBean<>();
bean.setFilter(new WebStatFilter());
Map<String, String> initParams = new HashMap<>();
initParams.put("exclusions","*.js,*.css,/druid/*");
bean.setInitParameters(initParams);
bean.setUrlPatterns(Arrays.asList("/*"));
return bean;
}
}
定位sql的文件
spring.datasource.schema=xx.sql
使用mybatis
导入依赖
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.1</version>
</dependency>
导入配置
spring.datasource.username=root
spring.datasource.password=zheng
spring.datasource.url=jdbc:mysql://207.148.95.94/jdbc
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
编写mapper
@Mapper
@Repository
public interface MyMapper {
@Select("select * from test where id =#{id}")
public testDomain findById(Integer integer);
@Delete("delete from test where id=#{id}")
public Integer deleteById(Integer id);
@Options(useGeneratedKeys = true, keyProperty = "id")
@Insert("insert into test(name) values(#{name})")
public Integer insertTest(testDomain t);
}
编写控制层
@RestController
public class testController {
@Autowired
MyMapper testMapper;
@GetMapping("/find/{id}")
public testDomain findById(@PathVariable("id") Integer id){
testDomain testDomain = testMapper.findById(id);
System.out.println(testDomain);
return testDomain;
}
@GetMapping("/delete/{id}")
public Integer deleteById(@PathVariable("id") Integer id){
return testMapper.deleteById(id);
}
@GetMapping("/insert")
public Integer deleteById(testDomain testDomain){
return testMapper.insertTest(testDomain);
}
}
解决扫描mapper包
@MapperScan("com.example.firstboot.Mapper")
@SpringBootApplication
public class FirstbootApplication {
public static void main(String[] args) {
SpringApplication.run(FirstbootApplication.class, args);
}
}
mybatis xml文件mapper
mybatis.config-location=classpath:mybatis/mybatis-config.xml
mybatis.mapper-locations=classpath:mybatis/mapper/*.xml
SpringData 是SpringBoot底层默认采用的访问数据库的技术,简化数据库的操作,统一数据访问的API,提供了各种temple类
SpringBoot启动配置原理
启动流程
1、创建SpringApplication对象,扫描初始化器ApplicationContextInitializer和监听器ApplicationListener
2、运行run方法
SpringApplicationRunListeners获取监听器执行
SpringBoot 场景启动器
启动器只用来导入依赖
https://blog.csdn.net/sgl520lxl/article/details/102495443
缓存JSR107
CachingProvider :控制和管理多个CachingManager,一个应用可以有多个CachingProvider
CacheManager:控制多个唯一命名的Cache、这些Cache存于CacheManager的上下文中
Cache是一个类似Map的数据结构。一个Cache只能被一个CacheManager使用
Entry:是一个存储在Cache中的KV对
Enpiry是一个存储在Cache条目中的一个有效期
springboot为了简化开发保留了:Cache和CacheManager
注解
@Cacheable:主要针对方法配置,能够根据方法的请求参数对其结果进行缓存
@CacheEvict:清空缓存
@CachePut:保证方法被调用,又希望结果被缓存
@EnableCaching:开启注解的缓存
@Caching可以使用Cacheable,CacheEvict,CachePut这三种的组合的缓存规则
keyGenerator:缓存数据时key的生成策略
serialize:缓存数据时value序列化的策略
使用
@SpringBootApplication
@EnableCaching//开启注解的缓存
public class Spring01DataApplication {
public static void main(String[] args) {
SpringApplication.run(Spring01DataApplication.class, args);
}
}
持久层
@Mapper
@Repository
public interface testMapper {
@Select("select * from test where id = #{id}")
public testDomain findById(Integer id);
@Delete("delete from test where id = #{id}")
public Integer deleteById(Integer id);
@Update("update test set name = #{name} where id =#{id}")
public Integer updateById(testDomain domain);
@Insert("insert into test(name) values(#{name})")
public Integer insert(testDomain domain);
}
业务层
//这个类的默认设置
@CacheConfig(cacheNames = "person")
@Service
public class TestService {
@Autowired
com.zheng.spring_01_data.Mapper.testMapper testMapper;
/**
* key :主键#root
* keyGenerator主键生成器,
* cacheManager:指定缓存管理器
* condition:指定符合条件的情况下才缓存
* unless:当符合条件返回值不会为true
* sync是否使用异步表达式
*/
@Cacheable(cacheNames = {"person"})//,keyGenerator = "myKeyGenerator")
public String findById(Integer id){
System.out.println("查询");
testDomain domain = testMapper.findById(id);
if (domain == null)
{
return "不存在";
}
return domain.toString();
}
/**
* allEntries:指删除所有person的cache中的缓存
* @param id
* @return
*/
@CacheEvict(cacheNames = "person")
public String deleteById(Integer id){
System.out.println("删除");
return testMapper.deleteById(id).toString();
}
public String insert(){
System.out.println("添加");
testDomain domain = new testDomain();
domain.setName("TEST1");
return testMapper.insert(domain).toString();
}
@CachePut(cacheNames = "person")
public String update(Integer id){
System.out.println("更改");
testDomain domain = new testDomain();
domain.setId(id);
domain.setName("2323");
return testMapper.updateById(domain).toString();
}
}
控制层
@RestController
public class TestController {
@Autowired
TestService testMapper;
@GetMapping("/findById")
public String findById(){
return testMapper.findById(5);
}
@GetMapping("/delete")
public String deleteById(){
return testMapper.deleteById(5);
}
@GetMapping("/insert")
public String insert(){
return testMapper.insert();
}
@GetMapping("/update")
public String update(){
return testMapper.update(5);
}
}
自定义key生成器
@Configuration
public class CacheConfig {
@Bean("myKeyGenerator")
public KeyGenerator keyGenerator(){
return new KeyGenerator() {
@Override
public Object generate(Object o, Method method, Object... objects) {
return method.getName()+'['+ Arrays.asList(objects)+']';
}
};
}
}
redis
append msg hello
get msg
http://www.redis.cn/
使用
1、在docker中安装redis
2、在pom文件中引入redis的坐标
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
3、配置redis
spring:
redis:
host: 207.148.95.94
4.配置类,如果使用对象存储到redis中会被序列化
@ConfigurationProperties(prefix = "spring.cache.redis")
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<Object, testDomain> testRedisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
RedisTemplate<Object, testDomain> template = new RedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
Jackson2JsonRedisSerializer<testDomain> testDomainJackson2JsonRedisSerializer;
testDomainJackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<testDomain>(testDomain.class);
template.setDefaultSerializer(testDomainJackson2JsonRedisSerializer);
return template;
}
private Duration timeToLive = Duration.ZERO;
public void setTimeToLive(Duration timeToLive) {
this.timeToLive = timeToLive;
}
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
RedisSerializer<String> redisSerializer = new StringRedisSerializer();
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
//解决查询缓存转换异常的问题
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
// 配置序列化(解决乱码的问题)
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(timeToLive)
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
.disableCachingNullValues();
RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
.cacheDefaults(config)
.build();
return cacheManager;
}
}
自己设置主键规则
@Configuration
public class CacheConfig {
@Bean("myKeyGenerator")
public KeyGenerator keyGenerator(){
return new KeyGenerator() {
@Override
public Object generate(Object o, Method method, Object... objects) {
return method.getName()+'['+ Arrays.asList(objects)+']';
}
};
}
}
5.一些基本使用
@SpringBootTest
class Spring01DataApplicationTests {
@Autowired
TestController testController;
@Autowired
DataSource dataSource;
@Autowired
StringRedisTemplate stringRedisTemplate;
@Autowired
RedisTemplate redisTemplate;
@Autowired
RedisTemplate<Object, testDomain> testRedisTemplate;
@Test
public void test01(){
//操作字符串的
//stringRedisTemplate.opsForValue().append("msg","hello");
//System.out.println(stringRedisTemplate.opsForValue().get("msg"));
//操作列表的
stringRedisTemplate.opsForList().leftPush("myList", "1");
stringRedisTemplate.opsForList().leftPush("myList", "2");
}
@Test
public void test02(){
testDomain domain = new testDomain();
//默认保存对象是序列化的效果
redisTemplate.opsForValue().set("myObject",domain);
}
@Test
public void test03(){
testDomain domain = new testDomain();
//默认保存对象是序列化的效果
testRedisTemplate.opsForValue().set("myObject2",domain);
}
@Test
void contextLoads() throws SQLException {
System.out.println(testController.insert());
}
}
cacheManager配置
@Configuration
@ConfigurationProperties(prefix = "spring.cache.redis")
public class RedisCacheConfig {
private Duration timeToLive = Duration.ZERO;
public void setTimeToLive(Duration timeToLive) {
this.timeToLive = timeToLive;
}
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
RedisSerializer<String> redisSerializer = new StringRedisSerializer();
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
//解决查询缓存转换异常的问题
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
// 配置序列化(解决乱码的问题)
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(timeToLive)
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
.disableCachingNullValues();
RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
.cacheDefaults(config)
.build();
return cacheManager;
}
}
消息服务
在应用中引入消息服务中间件提升系统异步通讯能力
消息服务两个重要概念消息代理(message broker)和目的地
方式:
点对点:消息只能有唯一的接受者和发送者,但并不是只能有一个接收者
发布订阅:发送者发送消息到主题,多个接收者监听这个主题,那么就会在消息到达时同时接受到这个消息
JMS:是java基于JVM的消息规范
AMQP:高级消息队列协议,是一个消息代理的规范,兼容JMS
Message:消息,消息是不具名的,他由消息头和消息体组成。
publisher:消息的生产者,也是一个向交换器发布消息的客户端应用程序
exchange:交换器,用来接收生产者发送的消息并将这些消息路由给服务器中的队列
Queue:消息队列,用来保存消息知道发送给消费者
Binding:绑定,用于消息队列和交换器之间的关联。绑定就是基于路由键将交换器和消息队列连接起来的路由规则,可以将交换器理解成一个由绑定构成的路由表。
Connection:网络连接
Channel:信道,多路复用连接中的一条独立的双向数据流通表。
Consumer:消费者
Virtual Host:虚拟主机,表示一批交换器、消息队列和相关对象。虚拟主机是共享相同的身份认证和加密环境的独立服务域。
Broker:表示消息队列服务器实体。
Excahge类型:
direct:直连型
fanout:广播模式
topic:对路由建进行模糊匹配,#0个或者多个单词,*匹配一个单词
在docker中下载rabbitmq
docker pull rabbitmq:3-management
在docker中创建rabbitmq
docker run -d ---name myrabbit -p 5672:5672 -p 15672:15672 a64a4ae7bc1f
rabbitmq
1、RabbitAutoConfiguration
2、有自动配置连接工厂ConnectionFactory
3、RabbitProperties封装了RabbitMQ的配置
4、RabbitTemple:给RabbitMQ发送和接受配置
5、AmqpAdmin:RabbitMQ系统管理功能组件
pom文件
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
application.yml
spring:
rabbitmq:
host: 207.148.95.94
username: guest
password: guest
测试类
@SpringBootTest
class SpringAmqpApplicationTests {
@Autowired
RabbitTemplate rabbitTemplate;
@Test
void contextLoads() {
//HashMap<String, String> map = new HashMap<>();
//map.put("hello","hello2");
rabbitTemplate.convertAndSend("exchange.direct","zheng",new Book("浩",55));
}
@Test
public void test01(){
Object o = rabbitTemplate.receiveAndConvert("zheng");
System.out.println(o.getClass());
System.out.println(o);
}
}
Message序列化配置
@Configuration
public class MyConfigAMQP {
@Bean
public MessageConverter messageConverter(){
return new Jackson2JsonMessageConverter();
}
}
队列监听器
@Service
public class BookService {
// @RabbitListener( queues = "zheng")
// public void receive(Book book){
// System.out.println("收到消息:"+book);
// }
@RabbitListener( queues = "zheng")
public void receive2(Message message){
System.out.println(message.getBody() +"++++++++"+ message.getMessageProperties());
}
}
主配置文件
@EnableRabbit//开启rabbit注解
@SpringBootApplication
public class SpringAmqpApplication {
public static void main(String[] args) {
SpringApplication.run(SpringAmqpApplication.class, args);
}
}
ElasticSearch添加检索功能,提供了Restful API,底层基于Lucene,采用shard方式保证了数据安全。
在docker中创建elasticsearch
拉取镜像
docker pull elasticsearch:5.6.8
启动容器
docker run --name my_es -d -e ES_JAVA_OPTS="-Xms512m -Xmx512m" -p 9200:9200 -p 9300:9300 docker.io/elasticsearch:5.6.8
查看容器境况
docker ps
添加数据
官方文档
https://www.elastic.co/guide/cn/elasticsearch/guide/current/_indexing_employee_documents.html
发送PUT请求
http://207.148.95.94:9200/test/employee/1
body
{
"first_name" : "John",
"last_name" : "Smith",
"age" : 26,
"about" : "I love to go rock climbing",
"interests": [ "sports", "music" ]
}
使用GET请求得到检索
http://207.148.95.94:9200/test/employee/_search
springboot默认支持两种技术来和ES交互
1、Jest(默认不生效,需要导入JEST工具包)
2、SpringBoot ElasticSearch
1)、Elasticsearch操作es
2)、ElasticsearchRepository的子接口操作ES
出现问题9200能打开,9300不能打开
异步的使用
在主程序中
@SpringBootApplication
@EnableAsync//开启异步注解
public class ElasticsearchApplication {
public static void main(String[] args) {
SpringApplication.run(ElasticsearchApplication.class, args);
}
}
在业务层使用
@Service
public class HelloService {
@Async
public void hello() {
try {
Thread.sleep(Long.parseLong("3000"));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("处理数据");
}
}
控制层
@RestController
public class HelloController {
@Autowired
HelloService service;
@GetMapping("hello")
public String Hello(){
service.hello();
return "hello";
}
}
定时任务
主配置文件
@SpringBootApplication
@EnableScheduling//开启定时任务
public class ElasticsearchApplication {
public static void main(String[] args) {
SpringApplication.run(ElasticsearchApplication.class, args);
}
}
实例
@Service
public class ScheduleService {
//second,minute,hour,day of month,month,day of week
@Scheduled(cron = "0 * * * * MON-SAT")
public void hello(){
System.out.println("zzzz");
}
}
邮件
pom文件依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
配置文件
spring:
mail:
password: qwwcmljtmxxzchbh
username: xxxxxx@qq.com
host: smtp.qq.com
properties:
mail:
smtp:
ssl:
enable: true
测试使用
@SpringBootTest
class ElasticsearchApplicationTests {
@Autowired
JavaMailSenderImpl sender;
@Test
void contextLoads() {
SimpleMailMessage message = new SimpleMailMessage();
message.setSubject("测试");
message.setText("success");
message.setTo("1071877529@qq.com");
message.setFrom("3479554785@qq.com");
sender.send(message);
}
//复杂的消息邮件
@Test
void contextLoads2() throws Exception {
MimeMessage mimeMessage = sender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage,true);
helper.setSubject("测试");
helper.setText("<b>success2</b>",true);
helper.setTo("1071877529@qq.com");
helper.setFrom("3479554785@qq.com");
helper.addAttachment("zheng.jpg",new File("D:\\myproject\\elasticsearch\\src\\main\\resources\\截图.PNG"));
sender.send(mimeMessage);
}
}
安全
认证(认证自己的身份)和授权(你能干什么)
第一步导入依赖
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
第二步 编写密码编码
@Component
public class PasswordEncoder implements org.springframework.security.crypto.password.PasswordEncoder {
@Override
public String encode(CharSequence charSequence) {
return charSequence.toString();
}
@Override
public boolean matches(CharSequence charSequence, String s) {
return s.equals(charSequence);
}
}
第三步,编写配置类
@EnableWebSecurity
public class MySecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
//super.configure(http);
//定制请求的授权规则
http.authorizeRequests().antMatchers("/").permitAll()
.antMatchers("/level1/**").hasRole("VIP1")
.antMatchers("/level2/**").hasRole("VIP2")
.antMatchers("level3").hasRole("VIP3");
//开启自动配置登陆功能
//1、/login来到登陆页面
//2、重定向到/login?error来到错误页面
http.formLogin().usernameParameter("user").passwordParameter("pwd").loginPage("/userlogin");
//开启自动配置的注销
http.logout().logoutSuccessUrl("/");
//记住账号密码
http.rememberMe();
}
//定义认证规则
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//super.configure(auth);
auth.inMemoryAuthentication().passwordEncoder(new PasswordEncoder()).withUser("zheng").password("123456")
.roles("VIP1","VIP2")
.and().withUser("hao").password("hao")
.roles("VIP3","VIP2");
}
}
第四步,编写控制类
@Controller
public class TestController {
private final String preffix = "/pages/";
@GetMapping("/")
public String index(){
return "welcome";
}
@GetMapping("/level1/{path}")
public String level1(@PathVariable("path")String path){
return preffix+"level1/path"+path;
}
@GetMapping("/level2/{path}")
public String level2(@PathVariable("path")String path){
return preffix+"level2/path"+path;
}
@GetMapping("/level3/{path}")
public String level3(@PathVariable("path")String path){
return preffix+"level3/path"+path;
}
@GetMapping("/userlogin")
public String login(){
return preffix+"login/login";
}
}
欢迎页面
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1 align="center">欢迎光临武林秘籍管理系统</h1>
<div sec:authorize="!isAuthenticated()">
<h2 align="center">游客您好,如果想查看武林秘籍 <a th:href="@{/userlogin}">请登录</a></h2>
</div>
<div sec:authorize="isAuthenticated()">
<h2><span sec:authentication="name"></span>,您好,您的角色有:
<span sec:authentication="principal.authorities"></span></h2>
<form th:action="@{/logout}" method="post">
<input type="submit" value="注销"/>
</form>
</div>
<hr>
<div sec:authorize="hasRole('VIP1')">
<h3>普通武功秘籍</h3>
<ul>
<li><a th:href="@{/level1/1}">罗汉拳</a></li>
<li><a th:href="@{/level1/2}">武当长拳</a></li>
<li><a th:href="@{/level1/3}">全真剑法</a></li>
</ul>
</div>
<div sec:authorize="hasRole('VIP2')">
<h3>高级武功秘籍</h3>
<ul>
<li><a th:href="@{/level2/1}">太极拳</a></li>
<li><a th:href="@{/level2/2}">七伤拳</a></li>
<li><a th:href="@{/level2/3}">梯云纵</a></li>
</ul>
</div>
<div sec:authorize="hasRole('VIP3')">
<h3>绝世武功秘籍</h3>
<ul>
<li><a th:href="@{/level3/1}">葵花宝典</a></li>
<li><a th:href="@{/level3/2}">龟派气功</a></li>
<li><a th:href="@{/level3/3}">独孤九剑</a></li>
</ul>
</div>
</body>
</html>
注册页面
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1 align="center">欢迎登陆武林秘籍管理系统</h1>
<hr>
<div align="center">
<form th:action="@{/userlogin}" method="post">
用户名:<input name="user"/><br>
密码:<input name="pwd"><br/>
<input type="checkbox" name="remeber"> 记住我<br/>
<input type="submit" value="登陆">
</form>
</div>
</body>
</html>
SpringBoot分布式
在分布式中国内常见的是ZooKeeper + Dubbo,SpringBoot推荐使用全栈的Spring Boot + Spring Cloud
ZooKeeper是一个分布式的,开源的分布式应用程序协调服务。用作注册中心。
Dubbo:Dubbo是Alibaba开源的分布式服务框架,他最大的特点就是按照分层的方式来架构,使用这种方式可以使各个层之间解耦,可以作为消费者和提供者。
docker run --name my_zk -p 2181:2181 --restart always -d zookeeper
使用dubbo
1.将服务提供者注册到注册中心
1、引入dubbo和zkclient相关依赖
2、配置dubbo的扫描包和注册中心地址
3、使用dubbo的@Service发布服务
出现问题注意
消费者使用
1、引入依赖
2、配置dubbo注册中心
3、引用服务
SpringCloud是一个解决分布式的整体方案。
五大组件
Netflix Eureka --服务发现
Netflix Ribbon——服务端负载均衡
Netflix Hystrix——断路器
Netflix Zuul——服务网关
Spring Cloud Config——分布式配置
热部署
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
Crtl+F9