当前位置: 首页 > 编程日记 > 正文

Shiro源码学习之二

接上一篇 Shiro源码学习之一

3.subject.login



进入login

public void login(AuthenticationToken token) throws AuthenticationException {clearRunAsIdentitiesInternal();Subject subject = securityManager.login(this, token);PrincipalCollection principals;String host = null;if (subject instanceof DelegatingSubject) {DelegatingSubject delegating = (DelegatingSubject) subject;//we have to do this in case there are assumed identities - we don't want to lose the 'real' principals:principals = delegating.principals;host = delegating.host;} else {principals = subject.getPrincipals();}if (principals == null || principals.isEmpty()) {String msg = "Principals returned from securityManager.login( token ) returned a null or " +"empty value.  This value must be non null and populated with one or more elements.";throw new IllegalStateException(msg);}this.principals = principals;this.authenticated = true;if (token instanceof HostAuthenticationToken) {host = ((HostAuthenticationToken) token).getHost();}if (host != null) {this.host = host;}Session session = subject.getSession(false);if (session != null) {this.session = decorate(session);} else {this.session = null;}}

private void clearRunAsIdentitiesInternal() {//try/catch added for SHIRO-298try {clearRunAsIdentities();} catch (SessionException se) {log.debug("Encountered session exception trying to clear 'runAs' identities during logout.  This " +"can generally safely be ignored.", se);}}

private void clearRunAsIdentities() {Session session = getSession(false);if (session != null) {session.removeAttribute(RUN_AS_PRINCIPALS_SESSION_KEY);}}


Session接口
public interface Session {
Serializable getId();
...


第一次直接return null

public Session getSession(boolean create) {
...
if (this.session == null && create) {
...
SessionContext sessionContext = createSessionContext();Session session = this.securityManager.start(sessionContext);this.session = decorate(session);}return this.session;

回到clearRunAsIdentitiesInternal



回到login



securityManager是DelegatingSubject声明的protected transient SecurityManager无序序列化



java的transient关键字为我们提供了便利,你只需要实现Serilizable接口,将不需要序列化的属性前添加关键字transient,序列化对象的时候,这个属性就不会序列化到指定的目的地中。

java transient简介


进入public Subject login(Subject subject, AuthenticationToken token)



进入public AuthenticationInfo authenticate(AuthenticationToken token)

public AuthenticationInfo authenticate(AuthenticationToken token) throws AuthenticationException {return this.authenticator.authenticate(token);}


进入public final AuthenticationInfo authenticate(AuthenticationToken token)

public final AuthenticationInfo authenticate(AuthenticationToken token) throws AuthenticationException {if (token == null) {throw new IllegalArgumentException("Method argumet (authentication token) cannot be null.");}log.trace("Authentication attempt received for token [{}]", token);AuthenticationInfo info;try {info = doAuthenticate(token);if (info == null) {String msg = "No account information found for authentication token [" + token + "] by this " +"Authenticator instance.  Please check that it is configured correctly.";throw new AuthenticationException(msg);}} catch (Throwable t) {AuthenticationException ae = null;if (t instanceof AuthenticationException) {ae = (AuthenticationException) t;}if (ae == null) {//Exception thrown was not an expected AuthenticationException.  Therefore it is probably a little more//severe or unexpected.  So, wrap in an AuthenticationException, log to warn, and propagate:String msg = "Authentication failed for token submission [" + token + "].  Possible unexpected " +"error? (Typical or expected login exceptions should extend from AuthenticationException).";ae = new AuthenticationException(msg, t);}try {notifyFailure(token, ae);} catch (Throwable t2) {if (log.isWarnEnabled()) {String msg = "Unable to send notification for failed authentication attempt - listener error?.  " +"Please check your AuthenticationListener implementation(s).  Logging sending exception " +"and propagating original AuthenticationException instead...";log.warn(msg, t2);}}throw ae;}log.debug("Authentication successful for token [{}].  Returned account [{}]", token, info);notifySuccess(token, info);return info;}



进入protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken)


protected void assertRealmsConfigured() throws IllegalStateException {



IllegalStateException异常:


protected Collection<Realm> getRealms() {return this.realms;}


回到doAuthenticate



进入doSingleRealmAuthentication




进入getCachedAuthenticationInfo


getAvailableAuthenticationCache返回null



回到getCachedAuthenticationInfo返回info是null

回到getAuthenticationInfo


进入doGetAuthenticationInfo



进入getUser用到了lock与unlock

USERS_LOCK.readLock().lock();try {return this.users.get(username);} finally {USERS_LOCK.readLock().unlock();}



参考:Java中锁的应用之-Lock



public boolean isCredentialsExpired() {return credentialsExpired;}
account.isCredentialsExpired()返回flase

doGetAuthenticationInfo返回account


回到getAuthenticationInfo

cacheAuthenticationInfoIfPossible

private void cacheAuthenticationInfoIfPossible(AuthenticationToken token, AuthenticationInfo info) {if (!isAuthenticationCachingEnabled(token, info)) {log.debug("AuthenticationInfo caching is disabled for info [{}].  Submitted token: [{}].", info, token);//return quietly, caching is disabled for this token/info pair:return;}Cache<Object, AuthenticationInfo> cache = getAvailableAuthenticationCache();if (cache != null) {Object key = getAuthenticationCacheKey(token);cache.put(key, info);log.trace("Cached AuthenticationInfo for continued authentication.  key=[{}], value=[{}].", key, info);}}
回到getAuthenticationInfo

进入assertCredentialsMatch

进入doCredentialsMatch

进入protected boolean equals(Object tokenCredentials, Object accountCredentials)

顺便提到一点public static boolean equals(byte[] a, byte[] a2)已经是java.util的class Arrays了

public static boolean equals(byte[] a, byte[] a2) {if (a==a2)return true;if (a==null || a2==null)return false;int length = a.length;if (a2.length != length)return false;for (int i=0; i<length; i++)if (a[i] != a2[i])return false;return true;}

回到getAuthenticationInfo


回到doSingleRealmAuthentication


回到protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken)


回到public final AuthenticationInfo authenticate(AuthenticationToken token)


代码走到notifySuccess(token, info);



protected void notifySuccess(AuthenticationToken token, AuthenticationInfo info)因为listeners的size=0所以直接跳出此方法



回到public final AuthenticationInfo authenticate(AuthenticationToken token)


回到public AuthenticationInfo authenticate(AuthenticationToken token)



回到public Subject login(Subject subject, AuthenticationToken token)


进入protected Subject createSubject(AuthenticationToken token, AuthenticationInfo info, Subject existing)


进入public Subject createSubject(SubjectContext subjectContext)


protected SubjectContext copy(SubjectContext subjectContext) {return new DefaultSubjectContext(subjectContext);}

public DefaultSubjectContext(SubjectContext ctx) {super(ctx);}


运行到this.backingMap.putAll(map);


回到public Subject createSubject(SubjectContext subjectContext)


protected SubjectContext ensureSecurityManager(SubjectContext context)


回到public Subject createSubject(SubjectContext subjectContext)


进入protected SubjectContext resolveSession(SubjectContext context)


protected SessionKey getSessionKey(SubjectContext context) {Serializable sessionId = context.getSessionId();if (sessionId != null) {return new DefaultSessionKey(sessionId);}return null;}
Serializable sessionId =null直接返回。

回到protected SubjectContext resolveSession(SubjectContext context)


又回到public Subject createSubject(SubjectContext subjectContext)



进入protected SubjectContext resolvePrincipals(SubjectContext context)由于principals不为空直接返回了


 @SuppressWarnings({"unchecked"})protected SubjectContext resolvePrincipals(SubjectContext context) {PrincipalCollection principals = context.resolvePrincipals();if (CollectionUtils.isEmpty(principals)) {log.trace("No identity (PrincipalCollection) found in the context.  Looking for a remembered identity.");principals = getRememberedIdentity(context);if (!CollectionUtils.isEmpty(principals)) {log.debug("Found remembered PrincipalCollection.  Adding to the context to be used " +"for subject construction by the SubjectFactory.");context.setPrincipals(principals);} else {log.trace("No remembered identity found.  Returning original context.");}}return context;}


又回到public Subject createSubject(SubjectContext subjectContext)


protected Subject doCreateSubject(SubjectContext context) {return getSubjectFactory().createSubject(context);}
public SubjectFactory getSubjectFactory() {return subjectFactory;}


进入public Subject createSubject(SubjectContext context)

public DelegatingSubject(PrincipalCollection principals, boolean authenticated, String host,Session session, boolean sessionCreationEnabled, SecurityManager securityManager)


回到createSubject,回到doCreateSubject,最后回到public Subject createSubject(SubjectContext subjectContext)


protected void save(Subject subject) {this.subjectDAO.save(subject);}

protected void saveToSession(Subject subject) {//performs merge logic, only updating the Subject's session if it does not match the current state:mergePrincipals(subject);mergeAuthenticationState(subject);}
protected void mergePrincipals(Subject subject) {//merge PrincipalCollection state:PrincipalCollection currentPrincipals = null;//SHIRO-380: added if/else block - need to retain original (source) principals//This technique (reflection) is only temporary - a proper long term solution needs to be found,//but this technique allowed an immediate fix that is API point-version forwards and backwards compatible////A more comprehensive review / cleaning of runAs should be performed for Shiro 1.3 / 2.0 +if (subject.isRunAs() && subject instanceof DelegatingSubject) {try {Field field = DelegatingSubject.class.getDeclaredField("principals");field.setAccessible(true);currentPrincipals = (PrincipalCollection)field.get(subject);} catch (Exception e) {throw new IllegalStateException("Unable to access DelegatingSubject principals property.", e);}}if (currentPrincipals == null || currentPrincipals.isEmpty()) {currentPrincipals = subject.getPrincipals();}Session session = subject.getSession(false);if (session == null) {if (!CollectionUtils.isEmpty(currentPrincipals)) {session = subject.getSession();session.setAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY, currentPrincipals);}//otherwise no session and no principals - nothing to save} else {PrincipalCollection existingPrincipals =(PrincipalCollection) session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);if (CollectionUtils.isEmpty(currentPrincipals)) {if (!CollectionUtils.isEmpty(existingPrincipals)) {session.removeAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);}//otherwise both are null or empty - no need to update the session} else {if (!currentPrincipals.equals(existingPrincipals)) {session.setAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY, currentPrincipals);}//otherwise they're the same - no need to update the session}}}
protected void mergeAuthenticationState(Subject subject) {Session session = subject.getSession(false);if (session == null) {if (subject.isAuthenticated()) {session = subject.getSession();session.setAttribute(DefaultSubjectContext.AUTHENTICATED_SESSION_KEY, Boolean.TRUE);}//otherwise no session and not authenticated - nothing to save} else {Boolean existingAuthc = (Boolean) session.getAttribute(DefaultSubjectContext.AUTHENTICATED_SESSION_KEY);if (subject.isAuthenticated()) {if (existingAuthc == null || !existingAuthc) {session.setAttribute(DefaultSubjectContext.AUTHENTICATED_SESSION_KEY, Boolean.TRUE);}//otherwise authc state matches - no need to update the session} else {if (existingAuthc != null) {//existing doesn't match the current state - remove it:session.removeAttribute(DefaultSubjectContext.AUTHENTICATED_SESSION_KEY);}//otherwise not in the session and not authenticated - no need to update the session}}}
public void setAttribute(Object attributeKey, Object value)




private Session lookupSession(SessionKey key) throws SessionException {if (key == null) {throw new NullPointerException("SessionKey argument cannot be null.");}return doGetSession(key);}


protected void validate(Session session, SessionKey key) throws InvalidSessionException {try {doValidate(session);} catch (ExpiredSessionException ese) {onExpiration(session, ese, key);throw ese;} catch (InvalidSessionException ise) {onInvalidation(session, ise, key);throw ise;}}
protected void doValidate(Session session) throws InvalidSessionException {if (session instanceof ValidatingSession) {((ValidatingSession) session).validate();} else {String msg = "The " + getClass().getName() + " implementation only supports validating " +"Session implementations of the " + ValidatingSession.class.getName() + " interface.  " +"Please either implement this interface in your session implementation or override the " +AbstractValidatingSessionManager.class.getName() + ".doValidate(Session) method to perform validation.";throw new IllegalStateException(msg);}}

回到public void setAttribute(SessionKey sessionKey, Object attributeKey, Object value)


protected void onChange(Session session) {sessionDAO.update(session);}
public void update(Session session) throws UnknownSessionException {storeSession(session.getId(), session);}

这已经是系统级的代码了java.util.concurrent

参考:HashMap和ConcurrentHashMap研究

回到protected void mergeAuthenticationState(Subject subject)


回到saveToSession

回到public Subject save(Subject subject)


回到protected void save(Subject subject)


回到public Subject createSubject(SubjectContext subjectContext)


回到protected Subject createSubject(AuthenticationToken token, AuthenticationInfo info, Subject existing)


回到public Subject login(Subject subject, AuthenticationToken token)


进入protected void onSuccessfulLogin(AuthenticationToken token, AuthenticationInfo info, Subject subject)


进入protected void rememberMeSuccessfulLogin(AuthenticationToken token, AuthenticationInfo info, Subject subject)

RememberMeManager rmm =null直接返回了


又回到public Subject login(Subject subject, AuthenticationToken token)


回到外层public void login(AuthenticationToken token)


继续往下


进入protected Session decorate(Session session)


进入private StoppingAwareProxiedSession(Session target, DelegatingSubject owningSubject)


回到public void login(AuthenticationToken token)


终于回到最外层调用代码



4.subject.getPrincipal()

logger.info("登录成功!Hello " + subject.getPrincipal());
public Object getPrincipal() {return getPrimaryPrincipal(getPrincipals());}


5.subject.logout();

public void logout() {try {clearRunAsIdentitiesInternal();this.securityManager.logout(this);} finally {this.session = null;this.principals = null;this.authenticated = false;//Don't set securityManager to null here - the Subject can still be//used, it is just considered anonymous at this point.  The SecurityManager instance is//necessary if the subject would log in again or acquire a new session.  This is in response to//https://issues.apache.org/jira/browse/JSEC-22//this.securityManager = null;}}
private void clearRunAsIdentitiesInternal() {//try/catch added for SHIRO-298try {clearRunAsIdentities();} catch (SessionException se) {log.debug("Encountered session exception trying to clear 'runAs' identities during logout.  This " +"can generally safely be ignored.", se);}}
private void clearRunAsIdentities() {Session session = getSession(false);if (session != null) {session.removeAttribute(RUN_AS_PRINCIPALS_SESSION_KEY);}}
public Object removeAttribute(Object key) throws InvalidSessionException {return delegate.removeAttribute(key);}
public Object removeAttribute(Object attributeKey) throws InvalidSessionException {return sessionManager.removeAttribute(this.key, attributeKey);}

调用系统级的remove方法。



相关文章:

Widgets 整理

1.滑动条 http://www.newnaw.com/pub/sl/031.html <--!grid中的内容--> <Grid x:Name"slidergrid" HorizontalAlignment"Left" VerticalAlignment"Center" Background"Azure" Margin"20"> <StackPane…

黑客用上机器学习你慌不慌?这 7 种窃取数据的新手段快来认识一下!

作者 | IrrfanAk译者 | 天道酬勤、Carol 责编 | Carol出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;机器学习以分析大型数据集和模式识别的能力而闻名。它基本上属于人工智能的一个子集。而机器学习使用的算法&#xff0c;是利用了先前的数据集和统计分析来做出假设…

ServletResponse-中文名的下载

2019独角兽企业重金招聘Python工程师标准>>> package com.httpServletResponse; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.net.URLEncoder; import javax.servlet.ServletException; import javax.se…

Linux环境编译安装OpenJDK

Centos6.5 AMD64位机器 Java的源码是C,C和Java实现的&#xff0c;所以还需要有一个安装好的java建议选OracleJDK参考文末 安装OracleJDK Linux环境安装卸载JDK以及安装Tomcat和发布Java的web程序 安装依赖 | Install dependence # yum -y install gcc gcc-c alsa-lib alsa-…

最快69秒逆向DRAM地址映射,百度设计的这款逆向工具如何做到快速可靠?

来源 | 百度安全实验室出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;导读&#xff1a;近日&#xff0c;国际顶级设计自动化大会DAC大会公布DAC 2020会议议程和论文名单&#xff0c;由百度安全发表的《DRAMDig: AKnowledge-assisted Tool to Uncover DRAM Address M…

国外厂商在行业客户上输单的原因

这两天听一个朋友聊天发泄&#xff0c;他在一家总代J公司工作&#xff0c;代理业内排行第一的国外厂商C公司的产品&#xff0c;他负责D行业在南方某几个省的销售业务&#xff0c;工作中需要与C公司的销售紧密配合。经过接近一年的工作&#xff0c;他拿到一些项目&#xff0c;但…

[android] 从gallery获取图片

效果就是点击按钮&#xff0c;打开系统图库应用&#xff0c;可以选择一张里面的图片展示出来 设置隐式意图 获取Intent对象&#xff0c;通过new出来 调用Intent对象的setAction()方法&#xff0c;设置动作&#xff0c;参数&#xff1a;Intent.ACTION_PICK 调用Intent对象的setT…

调试JDK源码-HashSet实现原理

调试JDK源码-一步一步看HashMap怎么Hash和扩容 调试JDK源码-ConcurrentHashMap实现原理 调试JDK源码-HashSet实现原理 调试JDK源码-调试JDK源码-Hashtable实现原理以及线程安全的原因 代码 Set<String> snew HashSet<String>();s.add("http://blog.csdn.ne…

Python 炫技操作:海象运算符的三种用法

作者 | 明哥来源 | Python编程时光&#xff08;ID:Cool-Python&#xff09;Python 版本发展非常快&#xff0c;如今最新的版本已经是 Pyhton 3.9&#xff0c;即便如此&#xff0c;有很多人甚至还停留在 3.6 或者 3.7&#xff0c;连 3.8 还没用上。很多 Python 3.8 的特性还没来…

2010.10.30 OA 项目组一周工作报告

本周基本上实现了上周的目标&#xff0c;但和计划相比有落后。 进度&#xff1a;55 本周提交了3.0任务评估的第一个版本&#xff0c;一共为1003小时&#xff0c;客户收到该评估后&#xff0c;对3.0任务进行了调整&#xff0c;将部分任务移到2011.2版本中&#xff0c;同时添加了…

继承log4.net的类

using System; using System.Diagnostics;[assembly: log4net.Config.XmlConfigurator(Watch true)] namespace Hbl.Core {public static class Log{/// <summary>/// 一般错误/// </summary>/// <param name"message">消息</param>public …

调试JDK源码-Hashtable实现原理以及线程安全的原因

调试JDK源码-一步一步看HashMap怎么Hash和扩容 调试JDK源码-ConcurrentHashMap实现原理 调试JDK源码-HashSet实现原理 调试JDK源码-调试JDK源码-Hashtable实现原理以及线程安全的原因 Hashtable是线程安全的&#xff0c;我们从源码来分析 代码很简单 Hashtable<String, …

源代码查看工具 Source Navigator 使用心得

在ubuntu 10.04下试用了Source Navigator&#xff0c;有条件还是装Source insight吧&#xff0c;不是一个级别的&#xff0c;非常不方便。 Source Navigator 是Red Hat出品的一款查看源代码的工具&#xff0c;非常好用&#xff0c;与Windows下的Source Insight有一敌。但是它的…

那个分分钟处理10亿节点图计算的Plato,现在怎么样了?

受访者 | 于东海记者 | 夕颜出品 | CSDN&#xff08;ID:CSDNnews&#xff09;「AI 技术生态论」 人物访谈栏目是 CSDN 发起的百万人学 AI 倡议下的重要组成部分。通过对 AI 生态顶级大咖、创业者、行业 KOL 的访谈&#xff0c;反映其对于行业的思考、未来趋势的判断、技术的实践…

android TextView里边实现图文混配效果

做的游戏攻略中的图文载入已经用TextView实现。但看到网易新闻里的内容。点击图片能够调到一个新的Activity &#xff0c;感觉也像Textview 实现的&#xff0c;但不知道怎么弄&#xff0c;想想能够通过动态载入Textview和ImageView 布局实现&#xff0c;但当量大的时候回事很复…

《异步处理在分布式系统中的优化作用》学习笔记

原文地址&#xff1a;http://www.infoq.com/cn/presentations/optimization-of-asynchronous-processing-in-distributed-systems 视频地址&#xff1a;http://v.qq.com/boke/page/l/0/6/l0196plsvp6.html 主讲人&#xff1a;赵海平 Facebook hiphop HHVM 阿里巴巴技术保障部…

CISCO设备上DHCP实例

Cisco设备上设置DHCP实例 -------------------------------------------------------------------------------- 一位客户想把DHCP SERVER迁移到6509交换机的MSFC上,要求还挺复杂: 1.同时为多个VLAN的客户机分配地址 2.VLAN内有部分地址采用手工分配的…

360金融翟政:科技成就金融场景零容错

翟政&#xff0c;拥有超过20年的互联网经验&#xff0c;我国第三方支付第一批从业者&#xff0c;是多个知名第三方支付公司产品研发团队的组建者&#xff0c;核心系统的主设计师&#xff0c;管理层核心成员。设计搭建的支付系统过去这十年来一直在服务着各行各业的在线支付需求…

OSSIM平台安全事件关联分析实践

OSSIM平台安全事件关联分析实践在《开源安全运维平台OSSIM最佳实践》一书中叙述到&#xff0c;事件关联是整个OSSIM关联分析的核心&#xff0c;对于OSSIM的事件关联需要海量处理能力&#xff0c;主要便于现在需要及时存储从设备采集到的日志&#xff0c;并能关联匹配和输出&…

《Apache Kafka》学习笔记

1.什么是Kafka Kafka是一个高通过率的分布式消息系统 2.消息队列&#xff08;Message Queue)MQ的模型 消息队列的简单架构图 3个核心概念&#xff1a; Sender Application&#xff1a;消息队列的发送者&#xff0c;也叫生产者producer Message Queue Receiver Application…

4 月 24 日开播!基于神经网络建模的信息传播预测

信息传播在我们的日常生活中无处不在&#xff0c;例如谣言的扩散、产品的推广以及新思想和新技术的普及等等&#xff0c;其建模和预测已经在多个重要领域内得到了广泛的研究。近年来&#xff0c;很多研究者利用以循环神经网络为主的深度学习模型对信息传播过程进行建模&#xf…

并行计算圆周率

看到这个题目&#xff0c;俗了&#xff0c;大家都在计算圆周率。不过咱们的目的是看一下并行计算的基本流程。 书上计算PI用的是精确的数值计算方法&#xff0c;我这里再给出一种概率计算方法。 OpenMP和MPI将同时亮相。 计算PI的方法 1.tan(PI/4)1 > PI4arctan1。知…

kafka-manager 的编译和使用(附安装包)

2019独角兽企业重金招聘Python工程师标准>>> kafka-manager是一个非常好用的kafka web管理工具&#xff0c;yahoo开源。 地址&#xff1a;github.com/yahoo/kafka-manager 1、编译过程比较简单&#xff0c;重点是能翻墙&#xff0c;如果网络环境不允许&#xff0c;可…

匿名函数应用-多线程测试代码

多线程测试代码&#xff0c;不用单独再写一个类&#xff0c;比较方面而已。 public class MainThread { static int a0; for (int x 0;x<100;x){ Thread t new Thread(new Runnable() { Override public void run() { while(true){ try { a;System.out.println(a);…

YOLOv4来了,大型调优现场,速度和准确率俱佳

作者 | VincentLee来源 | 晓飞的算法工程笔记简介论文提出YOLOv4&#xff0c;从图1的结果来看&#xff0c;相对于YOLOv3在准确率上提升了近10个点&#xff0c;然而速度并几乎没有下降&#xff0c;论文主要贡献如下&#xff1a;提出速度更快、精度更好的检测模型&#xff0c;仅需…

关于对J2EE几点误解和错误认识的澄清

转自&#xff1a;http://www.jdon.com .Net和J2EE的争论一直没有停止&#xff0c;我也参加过“程序员”杂志主持的“.Net和Java之争”之类的讨论&#xff0c;本来这两种技术都是为用户提供了竞争性的选择&#xff0c;对于用户来说是一件好事&#xff0c;多种选择远胜于单一选择…

org.springframework.dao.InvalidDataAccessApiUsageException: Write operations are not allowed in r...

2019独角兽企业重金招聘Python工程师标准>>> Struts Problem Report Struts has detected an unhandled exception: Messages: Write operations are not allowed in read-only mode (FlushMode.NEVER/MANUAL): Turn your Session into FlushMode.COMMIT/AUTO or re…

Java的Redis连接池代码性能不错

其实这个是引用自网友http://blog.csdn.net/tuposky/article/details/45340183&#xff0c;有2个版本&#xff0c;差别就是ReentrantLock和synchronized。另外原作者使用了断言&#xff0c;我觉得这个还是不用为好。 ReentrantLock版 import java.util.concurrent.locks.Reent…

降低预测过程计算成本,这些NLP模型压缩方法要知道

编译 | 凯隐出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;近年来&#xff0c;基于谷歌Transformer的语言模型在神经机器翻译&#xff0c;自然语言推理和其他自然语言理解任务上取得了长足进展。通过多种语言模型的平均损失进行自我监督预训练&#xff0c;使得在大范…

政府要尽快对应用商店出台管理办法

前两天联想的开发者大会&#xff0c;我和联想的CTO贺志强先生联合接受了一个视频访谈&#xff0c;贺先生谈到联想的乐园软件商店&#xff0c;组织大量的人力对于软件进行检测&#xff0c;以保证软件是合格产品&#xff0c;不会给用户一路带来侵害&#xff0c;对于联想这种负责态…