分类 java 下的文章

Spring中的synchronized容易出现不生效的情况,比如:在controller层加事物注解,内部代码块中含synchronized。

正确使用方式应当是:同步代码块在事物之前开启

为什么先调用@Transactional再调用synchronized会出现问题?

此处原文链接:https://blog.csdn.net/Rambo_Yang/article/details/119885524

1)事务开启在同步代码块之前
2)事务是 Spring 的 AOP 开启的,进入方法前,AOP 就开启了事务
3)事务开启以后才进入方法,再进入同步代码块加锁
4)当同步方法执行结束后,释放锁并提交事物(问题就出现在这里:如果在释放锁和提交事物之间有其它的线程请求,那么处理后的数据没有被提交,导致 synchronized 同步不生效的问题)

HttpSession 服务端的技术
服务器会为每一个用户 创建一个独立的HttpSession

HttpSession原理
当用户第一次访问Servlet时,服务器端会给用户创建一个独立的Session
并且生成一个SessionID,这个SessionID在响应浏览器的时候会被装进cookie中,从而被保存到浏览器中
当用户再一次访问Servlet时,请求中会携带着cookie中的SessionID去访问
服务器会根据这个SessionID去查看是否有对应的Session对象
有就拿出来使用;没有就创建一个Session(相当于用户第一次访问)

域的范围:

Context域 > Session域 > Request域
Session域 只要会话不结束就会存在 但是Session有默认的存活时间(30分钟)

  需要注意的是,一个Session的概念需要包括特定的客户端,特定的服务器端以及不中断的操作时间。A用户和C服务器建立连接时所处的Session同B用户和C服务器建立连接时所处的Session是两个不同的Session。

session进行身份验证的原理:

  当客户端第一次访问服务器的时候,此时客户端的请求中不携带任何标识给服务器,所以此时服务器无法找到与之对应的session,所以会新建session对象,当服务器进行响应的时候,服务器会将session标识放到响应头的Set-Cookie中,会以key-value的形式返回给客户端,例:JSESSIONID=7F149950097E7B5B41B390436497CD21;其中JSESSIONID是固定的,而后面的value值对应的则是给该客户端新创建的session的ID,之后浏览器再次进行服务器访问的时候,客户端会将此key-value放到cookie中一并请求服务器,服务器就会根据此ID寻找对应的session对象了;(当浏览器关闭后,会话结束,由于cookie消失所以对应的session对象标识消失,而对应的session依然存在,但已经成为报废数据等待GC回收了)对应session的ID可以利用此方法得到:session.getId();

1.client-server connection

先上一张图,如下

请输入图片描述

client与server建立一个连接,这种连接是底层的
client发送request到server,等待server的answer
server处理request,将处理结果返还给client,这个结果包括status code、其它data

在HTTP/1.1中,在步骤3执行完成后,connection不再被关闭,在connection有效的前提细,后面client不再需要执行步骤1,直接执行步骤2、3就可以。

为了进一步深入,如下图2,图2是我从国外的网上截下来的,建议读者阅读

请输入图片描述

       图2 HttpSession生成后会有个sessionID

Client第一次发送请求,web container生成唯一的session ID(生成session ID的源码,如有兴趣,可以看下tomcat源码, 随机数+时间+jvmid),并将其返回给client(在web container返回给client的response中),web container上的这个HttpSession是临时的。
后面Client在每次发送请求给服务器时,都将session ID发送给web container,这样web container就很容易区分出是哪个client.
Web container使用这个session ID,找到对应的HttpSession,并将此次request与这个HttpSession联系起来。  

HttpSession生命周期:

  1. 什么时候创建HttpSession

1).对于JSP:
  是否浏览器访问服务端的任何一个JSP或Servlet,服务器都会立即创建一个HttpSession对象呢? 不一定。
  ①.若当前的JSP或(Servlet)是客户端访问的当前WEB应用的第一个资源,且JSP的page指定的session属性为false,则服务器就不会为JSP创建一个HttpSession对象;
  ②.若当前JSP不是客户端访问的当前WEB应用的第一个资源,且其他页面已经创建一个HttpSession对象,则服务器也不会为当前JSP创建一个新的HttpSession对象,而会把和当前会话关联的那个HttpSession对象返回给当前的JSP页面。

2).page指令的session="false"到底表示什么意思:当前JSP页面禁用session隐含变量!但可以使用其他的显式的对象

3).对于Servlet而言:
  若Servlet是客户端访问的第一个WEB应用的资源,则只有调用了request.getSession()或request.getSession(true) 才会创建HttpSession对象

4). 在Servlet中如何获取HttpSession对象?
  request.getSession(boolean create):create为false,若没有和当前JSP页面关联的HttpSession对象,则返回null;
  若有返回true create为true一定返回一个HTTPSession对象。若没有和昂前JSP页面关联的HttpSession对象,则服务器创建一个新的HttpSession对象返回,若有,则直接返回关联。
  request.getSession()等同于request.getSession(true)

  1. 什么时候销毁HttpSession对象:

1).直接调用HttpSession的invalidate()方法:使HttpSession失效
2).服务器卸载了当前Web应用。
3).超出HttpSession的过期时间。

设置HttpSession的过期时间:单位为S

session.setMaxInactiveInterval(5);
out.print(session.getMaxInactiveInterval());

<!--在web.xml文件中设置HttpSession过期时间。 -->

<session-config>
    <session-timeout>30</session-timeout>
</session-config>

<!--系统默认30分钟 -->

  由于会有越来越多的用户访问服务器,因此Session也会越来越多。为防止内存溢出,服务器会把长时间内没有活跃的Session从内存删除。这个时间就是Session的超时时间。如果超过了超时时间没访问过服务器,Session就自动失效了。

Session具有以下特点:
(1)Session中的数据保存在服务器端;
(2)Session中可以保存任意类型的数据;
(3)Session默认的生命周期是30分钟,可以手动设置更长或更短的时间。

1:session进行身份验证的原理:

当客户端第一次访问服务器的时候,此时客户端的请求中不携带任何标识给服务器,所以此时服务器无法找到与之对应的

session,所以会新建session对象,当服务器进行响应的时候,服务器会将session标识放到响应头的Set-Cookie中,会以

key-value的形式返回给客户端,例:JSESSIONID=7F149950097E7B5B41B390436497CD21;其中JSESSIONID是固定的,

而后面的value值对应的则是给该客户端新创建的session的ID,之后浏览器再次进行服务器访问的时候,客户端会将此key-value

放到cookie中一并请求服务器,服务器就会根据此ID寻找对应的session对象了;(当浏览器关闭后,会话结束,由于cookie消

失所以对应的session对象标识消失,而对应的session依然存在,但已经成为报废数据等待GC回收了)

对应session的ID可以利用此方法得到:session.getId();

创建独立spring boot 应用

引入依赖

spring cloud spirng

   <!--       consul  client-->
    <!--       引入依赖-->
       <dependency>
           <groupId>org.springframework.cloud</groupId>
           <artifactId>spring-cloud-starter-consul-discovery</artifactId>
       </dependency>

配置application.properties

server.port=8082

指定服务名称

spring.application.name=CONSULCLIENT

consul server 服务注册地址

spring.cloud.consul.host=localhost
spring.cloud.consul.port=8500
spring.cloud.consul.discovery.service-name=${spring.application.name}

加注解在入口类上面

@EnableDiscoveryClient //通用服务注解

启动成功后 连上服务会一直显示,红XX,添加下面健康检查依赖即可

<!-- 健康依赖检查-->

   <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-actuator</artifactId>
   </dependency>

consul 服务注册中心
简介:consul 基于go 语言开发的服务注册中心 轻量级服务注册中心 google开发
作用: 管理微服务中所有的服务 注册 发现 管理 服务元数据信息存储(服务名 地址列表) 心跳健康检测

consul 服务中心安装
下载地consul

https://www.consul.io/downloads

在指定目录解压,注意:不建议目录包含中文

E:\consul\consul.exe

启动服务注册中心 在consul 安装目录打开cmd

consul agent -dev 

访问consul 管理界面

浏览器输入:http://localhost:8500

管理界面基本介绍

 dc1:数据中心名称:datacenter 默认为:dc1
 指定数据中心启动 consul agent -dev -datacenter=sss
 services :当前consul 服务中注册服务列表 ,默认:client server 同时启动自己注册自己 会出现一个consul 一个服务
 nodes 查看集群的节点
 key/value  存储 数据
 ACL 版本集成控制
 Intentions 集成其他第三方组件

推荐 配置环境变量

path:Econsul(自己安装consul目录)