【Shiro】Shiro從小白到大神(三)-許可權認證(授權)
本節講許可權認證,也就是授權
基於角色的訪問控制和基於許可權的訪問控制的小例項
以及註解式授權和JSP標籤授權詳解
許可權認證
許可權認證核心要素
許可權認證,也就是訪問控制,即在應用中控制誰能訪問哪些資源
在許可權認證中,最核心的三個要素是:許可權,角色和使用者 (資源也算一個要素,但不是最核心的)
許可權,即操作資源的 許可權,比如訪問某個頁面,以及對某個模組的資料的新增,修改,刪除,檢視的權利(整合以後,其實就是一些對URL請求的許可權)
角色,是許可權的集合,一種角色可以包含多種許可權(將許可權賦給角色)
使用者,在Shiro中,代表訪問系統的使用者,即Subject(將角色賦給使用者)
英文好的,可以去看官方文件介紹:
授權
—-基於角色的訪問控制
首先配置ini檔案:
[users]
;基於角色的訪問控制的配置檔案
chx=123456,role1,role2
;加角色,密碼後面是擁有的角色
jack=123456,role1
測試類
package cn.chenhaoxiang.shiro;
import cn.chenhaoxiang.common.ShiroUtils;
import org.apache.shiro.subject.Subject;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Arrays;
/**
* 基於角色的訪問控制
*/
public class RoleTest {
private static Logger logger = LoggerFactory.getLogger(RoleTest.class);
/**
* hasRole(String roleName) Returns true if the Subject is assigned the specified role, false otherwise.
* hasRoles(List<String> roleNames) Returns a array of hasRole results corresponding to the indices in the method argument. Useful as a performance enhancement if many role checks need to be performed (e.g. when customizing a complex view)
* hasAllRoles(Collection<String> roleNames) Returns true if the Subject is assigned all of the specified roles, false otherwise.
* hasRole 判斷是否擁有某個角色
*
* hasRoles 判斷擁有某個角色 返回的是boolean[] 用來高效判斷對應角色擁有
* hasAllRoles 判斷擁有所有角色 擁有傳入的全部角色的話,才返回true
*
*/
@Test
public void testHasRole(){
Subject subject = ShiroUtils.login("classpath:shiro_role.ini","chx","123456");
logger.info(subject.hasRole("role1")?"有role1這個角色":"沒有role1這個角色");
logger.info(subject.hasRole("role2")?"有role2這個角色":"沒有role2這個角色");
Subject subject2 = ShiroUtils.login("classpath:shiro_role.ini","jack","123456");
logger.info(subject2.hasRole("role1")?"有role1這個角色":"沒有role1這個角色");
logger.info(subject2.hasRole("role2")?"有role2這個角色":"沒有role2這個角色");
// hasRoles 判斷擁有某個角色 返回的是boolean[] 用來高效判斷對應角色擁有
boolean[] results = subject.hasRoles(Arrays.asList("role1","role2","role3"));
logger.info(results[0]?"有role1這個角色":"沒有role1這個角色");
logger.info(results[1]?"有role2這個角色":"沒有role2這個角色");
logger.info(results[2]?"有role2這個角色":"沒有role3這個角色");
//hasAllRoles 判斷擁有所有角色 擁有傳入的全部角色的話,才返回true
logger.info(subject.hasAllRoles(Arrays.asList("role1","role2"))?"有role1和role2這兩個個角色":"role1,role2這兩個角色不全部有");
subject.logout();//退出
}
/**
* CheckRole
*/
@Test
public void testCheckRole(){
Subject subject = ShiroUtils.login("classpath:shiro_role.ini","chx","123456");
subject.checkRole("role1");//沒有返回值
//subject.checkRole("role3");//沒有這個角色會丟擲異常 //org.apache.shiro.authz.UnauthorizedException: Subject does not have role [role211]
//checkRoles(Collection<String> roleNames)
subject.checkRoles(Arrays.asList("role1","role2"));
//subject.checkRoles(Arrays.asList("role1","role2","role3"));//沒有全部角色會丟擲異常 //org.apache.shiro.authz.UnauthorizedException: Subject does not have role [role3]
//checkRoles(String... roleNames)和checkRoles(Collection<String> roleNames)意思一樣,傳入的引數型別不同
subject.checkRoles("role1","role2");
subject.logout();//退出
}
}
演示結果自己跑一遍就出來啦
—-基於許可權的訪問控制
配置ini檔案:
[users]
;基於許可權的訪問控制的配置檔案
chx=123456,role1,role2
;加角色,密碼後面是擁有的角色
jack=123456,role1
[roles]
;不判斷角色,直接判斷許可權
role1=user:select
;role1擁有select許可權 這裡的user:select許可權名字是自己定義的
role2=user:add,user:update,user:delete
;許可權無非就是增刪改查
測試類:
package cn.chenhaoxiang.shiro;
import cn.chenhaoxiang.common.ShiroUtils;
import org.apache.shiro.subject.Subject;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* 基於許可權的訪問控制
*/
public class PermissionTest {
private static Logger logger = LoggerFactory.getLogger(PermissionTest.class);
/**
* isPermitted(Permission p) isPermitted(String str) 如果是擁有訪問某個資源的許可權,返回true 單個許可權判斷
*
* isPermitted(String... var1); 分別判斷多個許可權 返回boolean[]
*
* isPermittedAll(String... var1); 擁有所有許可權才返回true
*/
@Test
public void testIsPermitted(){
//Subject subject = ShiroUtils.login("classpath:shiro_permission.ini","chx","123456");
Subject subject = ShiroUtils.login("classpath:shiro_permission.ini","jack","123456");
logger.info(subject.isPermitted("user:select")?"有user:select許可權":"沒有user:select許可權");
logger.info(subject.isPermitted("user:update")?"有user:update許可權":"沒有user:update許可權");
boolean results[] = subject.isPermitted("user:select","user:update","user:delete");
logger.info(results[0]?"有user:select許可權":"沒有user:select許可權");
logger.info(results[1]?"有user:update許可權":"沒有user:update許可權");
logger.info(results[2]?"有user:delete許可權":"沒有user:delete許可權");
logger.info(subject.isPermittedAll("user:select","user:update")?"有user:select和user:update許可權":"user:select和user:update許可權不全有");
subject.logout();//退出
}
/**
*
* checkPermission(String var1) 沒有這一個許可權就丟擲異常
* checkPermissions(String... var1) 沒有這些許可權就丟擲異常
*/
@Test
public void testCheckPermitted(){
//Subject subject = ShiroUtils.login("classpath:shiro_permission.ini","chx","123456");
Subject subject = ShiroUtils.login("classpath:shiro_permission.ini","jack","123456");
subject.checkPermission("user:select");//檢查是否有某個許可權 沒有許可權則丟擲異常
//subject.checkPermission("user:delete");//org.apache.shiro.authz.UnauthorizedException: Subject does not have permission [user:delete]
subject.checkPermissions("user:select","user:update");
subject.logout();//退出
}
}
講了幾個org.apache.shiro.subject.Subject的函式。
其實官方文件都有介紹的
註解式授權
首先你的Java版本5+才能整合shiro的註解
RequiresAuthentication註解
RequiresAuthentication註解需要在當前會話中對當前的Subject進行身份驗證,以便訪問或呼叫該註解的類/例項/方法。
也就是要求當前Subject已經在當前的Session中被驗證通過才能被訪問或呼叫
比如:
@RequiresAuthentication //判斷驗證有沒有通過
public void updateAccount(Account userAccount) {
//this method will only be invoked by a
//Subject that is guaranteed authenticated
...
}
基本等同於下面的程式碼:
public void updateAccount(Account userAccount) {
if (!SecurityUtils.getSubject().isAuthenticated()) {
throw new AuthorizationException(...);
}
//Subject is guaranteed authenticated here
...
}
RequiresGuest註解
要求當前的Subject是一個’guest’(遊客),也就是說,必須是在之前的session中沒有被驗證或被記住才能被訪問和呼叫
例如:
@RequiresGuest
public void signUp(User newUser) {
//this method will only be invoked by a
//Subject that is unknown/anonymous
...
}
基本等價於下面的程式碼:
public void signUp(User newUser) {
Subject currentUser = SecurityUtils.getSubject();
PrincipalCollection principals = currentUser.getPrincipals();
if (principals != null && !principals.isEmpty()) {
//known identity - not a guest:
throw new AuthorizationException(...);
}
//Subject is guaranteed to be a 'guest' here
...
}
RequiresPermissions註解
RequiresPermissions註解要求當前Subject允許一個或多個許可權來執行帶註釋的方法。
也就是說,必須有這個許可權才能訪問
例如:
@RequiresPermissions("account:create") //必須有account:create許可權,多個許可權之間用逗號隔開
public void createAccount(Account account) {
//this method will only be invoked by a Subject
//that is permitted to create an account
...
}
基本等價於:
public void createAccount(Account account) {
Subject currentUser = SecurityUtils.getSubject();
if (!subject.isPermitted("account:create")) {
throw new AuthorizationException(...);
}
//Subject is guaranteed to be permitted here
...
}
RequiresRoles註解
RequiresRoles註解要求當前Subject擁有所有指定的角色。如果它們沒有所有的角色,則不會執行該方法,並丟擲AuthorizationException
例如:
@RequiresRoles("administrator")
public void deleteUser(User user) {
//this method will only be invoked by an administrator
...
}
基本等同於以下程式碼:
public void deleteUser(User user) {
Subject currentUser = SecurityUtils.getSubject();
if (!subject.hasRole("administrator")) {
throw new AuthorizationException(...);
}
//Subject is guaranteed to be an 'administrator' here
...
}
RequiresUser註解
RequiresUser註解 需要當前的Subject是一個應用程式的使用者 才能被所註解的類/例項/方法訪問或者呼叫。
一個”應用程式使用者”被定義一個擁有已知身份,或在當前session中通過驗證被確認,或者在之前的session中的”RememberMe”服務被記住
也就是說,必須是某個使用者
例如:
@RequiresUser
public void updateAccount(Account account) {
//this method will only be invoked by a 'user'
//i.e. a Subject with a known identity
...
}
基本等同於下面程式碼:
public void updateAccount(Account account) {
Subject currentUser = SecurityUtils.getSubject();
PrincipalCollection principals = currentUser.getPrincipals();
if (principals == null || principals.isEmpty()) {
//no identity - they're anonymous, not allowed:
throw new AuthorizationException(...);
}
//Subject is guaranteed to have a known identity here
...
}
JSP標籤授權
必須新增shiro-web.jar
在jsp頁面中引入:
<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
guest標籤
使用者沒有身份驗證時顯示相應資訊,即遊客訪問資訊
例如:
<shiro:guest>
Hi there! Please <a href="login.jsp">Login</a> or <a href="signup.jsp">Signup</a> today!
</shiro:guest>
在這裡標籤內的文字,如果使用者沒有登入才會顯示出來,也就是遊客
user標籤
只有在當前Subject被認為是“使用者”時,使用者標記才會顯示其包裝內容。
在這個上下文中,“使用者”被定義為一個具有已知身份的主題,要麼是成功的身份驗證,要麼是來自“記住我”的服務。
注意,這個標記與經過身份驗證的標記有語義上的不同,它比這個標記更加嚴格。
例如:
<shiro:user>
Welcome back John! Not John? Click <a href="login.jsp">here<a> to login.
</shiro:user>
user標籤和guest標籤邏輯相反
authenticated標籤
僅噹噹前使用者在當前會話中成功驗證時才顯示正文內容。
它比“使用者”標籤更具限制性。它在邏輯上與“notAuthenticated”標記相反。
只有在當前Subject在當前會話中成功驗證的情況下,經過身份驗證的標記才會顯示其包裝內容。
它是一個比使用者更嚴格的標記,用來保證敏感工作流中的標識。也就是說,通過記住我登入的無法訪問到!!!
例如:
<shiro:authenticated>
<a href="updateAccount.jsp">Update your contact information</a>.
</shiro:authenticated>
notAuthenticated標籤
如果當前Subject在當前會話中尚未成功驗證,則未驗證標記將顯示其包裝內容。
也就是使用者沒有身份驗證通過,即沒有呼叫Subject.login進行登入,包括記住我自動登入的也屬於未進行身份驗證這個notAuthenticated標籤!
例如:
<shiro:notAuthenticated>
Please <a href="login.jsp">login</a> in order to update your credit card information.
</shiro:notAuthenticated>
principal標籤
輸出使用者資訊,會呼叫toString()方法
例如:
Hello, <shiro:principal/>, how are you today?
相當於呼叫以下程式碼:
Hello, <%= SecurityUtils.getSubject().getPrincipal().toString() %>, how are you today?
通過型別
如果你不想獲取所有的,比如在使用者名稱和使用者id之間,我想獲取使用者id,可以通過下面這種方式:
User ID: <principal type="java.lang.Integer"/>
等同於:
User ID: <%= SecurityUtils.getSubject().getPrincipals().oneByType(Integer.class).toString() %>
通過屬性名
但是,當遇到複雜的情況時,上面的就不行了,畢竟可能不止一個Integer,這個時候就可以通過屬性名了。
通過getter方法獲取的
例如:
Hello, <shiro:principal property="firstName"/>, how are you today?
相當於下面的程式碼:
Hello, <%= SecurityUtils.getSubject().getPrincipal().getFirstName().toString() %>, how are you today?
或者說,可以結合type屬性:
Hello, <shiro:principal type="com.foo.User" property="firstName"/>, how are you today?
也就是如下程式碼的邏輯:
Hello, <%= SecurityUtils.getSubject().getPrincipals().oneByType(com.foo.User.class).getFirstName().toString() %>, how are you today?
hasRole標籤
只有噹噹前Subject被分配指定角色時,hasRole標記才會顯示其包裝內容
例如:
<shiro:hasRole name="administrator">
<a href="admin.jsp">Administer the system</a>
</shiro:hasRole>
lacksRole標籤
如果當前Subject沒有分配指定的角色,則將顯示其包裝內容。
<shiro:lacksRole name="administrator">
Sorry, you are not allowed to administer the system.
</shiro:lacksRole>
lacksRole標籤與hasRole標籤的邏輯相反。
hasAnyRole標籤
如果當前Subject從一個由逗號分隔的角色名稱列表中具有了任一指定的角色,那麼hasAnyRole標記將顯示其包裝內容。
<shiro:hasAnyRoles name="developer, project manager, administrator">
You are either a developer, project manager, or administrator.
</shiro:hasAnyRoles>
只要有其中一個角色,即顯示主體內容
hasPermission標籤
如果當前Subject有許可權則顯示其包裝的內容
<shiro:hasPermission name="user:create">
<a href="createUser.jsp">Create a new User</a>
</shiro:hasPermission>
lacksPermission標籤
如果當前Subject沒有該許可權則顯示其包裝的內容
<shiro:lacksPermission name="user:delete">
Sorry, you are not allowed to delete user accounts.
</shiro:lacksPermission>
lacksPermission標籤與hasPermission標籤的邏輯相反
深入理解Apache Shiro的Permissions
萬用字元的許可權
單個許可權: 直接起一個字串名即可
例如: queryPrinter許可權-查詢許可權
subject.isPermitted("queryPrinter")
基本等同於:
subject.isPermitted( new WildcardPermission("queryPrinter") )
第二種方式基本不用,用第一種方式即可
多個許可權: 萬用字元許可權支援多個級別或部分的概念。
下面使用”:”用於分隔許可權字串下一部分的特殊字元。
printer:query
printer:print
printer:manage
即可配置多個許可權
也可以用多值來配置:
printer:print,query
驗證查詢許可權:
subject.isPermitted("printer:query")
單個資源的所有許可權
比如我們有這些許可權:
printer:query,print,manage
相當於:
printer:*
使用第二種方法使用萬用字元比顯式地列出動作要更好,因為如果以後嚮應用程式添加了一個新操作,則不需要更新在該部分中使用萬用字元的許可權。
所有資源的某個許可權
還可以在萬用字元許可權字串的任何部分使用萬用字元令牌
*:view
所有資源的view許可權
也就是說對“foo:view”(或其他的:view)的任何許可權檢查將返回true
例項級別的許可權控制
萬用字元許可權的另一個常見用法是建立例項級訪問控制列表。
在這個許可權中,您將使用三個部分——第一個是域,第二個是動作,第三個是被執行的例項(標識)。
單個例項的單個許可權
printer:query:lp7200
printer:print:epsoncolor
比如你擁有printer的query許可權,印表機的id為lp7200,也就是擁有這類printer的query許可權
如果您將這些許可權授予使用者,那麼它們就可以在特定的例項上執行特定的行為。然後你可以在程式碼中做一個檢查:
if ( SecurityUtils.getSubject().isPermitted("printer:query:lp7200") {
// Return the current jobs on printer lp7200 }
}
所有例項的單個許可權
printer:print:*
也就是說,具有所有printer的print許可權,相當於前面的單個資源的多個許可權
所有例項的所有許可權
printer:*:*
單個例項的所有許可權
printer:*:lp7200
單個例項的多個許可權
printer:query,print:lp7200
query和print之間用逗號隔開
在實際開發中,基本上用不到例項級別的許可權控制
關於許可權分配的最後一件事是:末尾丟失的部分意味著使用者可以訪問與該部分對應的所有值。換句話說,
printer:print
就相當於:
printer:print:*
printer
單個許可權相當於
printer:*:*
但是注意!
printer:lp7200
和
printer:*:lp7200
是不同的!!!
因為這不是末尾的*
檢查許可權
雖然許可權分配使用萬用字元構造相當多(“printer:*”=列印到任何printer),但在執行時的許可權檢查應該始終基於可能的最特定的許可權字串。
比如:如果使用者有一個使用者介面,他們想要列印一個文件到lp7200印表機,你應該檢查使用者是否允許執行這個程式碼
if ( SecurityUtils.getSubject().isPermitted("printer:print:lp7200") ) {
//print the document to the lp7200 printer }
}
這個檢查非常具體,並且明確地反映了使用者在那個時候正在嘗試做什麼。
但是,如下程式碼是不對的:
if ( SecurityUtils.getSubject().isPermitted("printer:print") ) {
//print the document }
}
因為第二個示例說“您必須能夠列印到任何印表機,以便執行以下程式碼塊”。但請記住,“printer:print”等同於“printer:print:*”!
因此,這是一個不正確的檢查。
如果當前使用者沒有能力列印到任何印表機,但他們確實有列印的能力,比如lp7200和epsoncolor印表機。
然而,上面的第二個例子永遠不會允許他們列印到lp7200印表機,即使他們已經獲得了這種能力!
因此,經驗法則是在執行許可權檢查時使用最特殊的許可權字串。
當然,如果您真的只想執行程式碼塊,如果使用者被允許列印到任何印表機(可能),那麼第二個方法可能是應用程式中的另一個有效的檢查。
您的應用程式將決定什麼檢查是有意義的,但是一般來說,越具體越好。
為什麼執行時許可權檢查應該儘可能具體,但是許可權分配可以更通用一些呢?
這是因為許可權檢查是由隱含邏輯計算的,而不是平等檢查。
也就是說,如果使用者被分配給”user:“許可權,這意味著使用者可以執行”user:view”操作。字串”user:“顯然不等於”user:view”,但前者暗示後者。”user:*”描述了由”user:view”定義的功能的超集。
為了支援隱含規則,所有許可權都被翻譯到實現org.apache.shiro.authz的物件例項的許可權介面中。
這就是說,隱含邏輯可以在執行時執行,而且隱含邏輯通常比簡單的字串等式檢查更復雜。
本文件中描述的所有萬用字元行為實際上都是由org.apache.shiro.authz.permission.WildcardPermission類實現
下面是一些萬用字元的許可權字串,它顯示了訪問的含義:
user:*
暗指還能刪除使用者的能力:
user:delete
但是:
user:*:12345
也就是說,還可以使用例項12345更新使用者帳戶:
user:update:12345
printer
暗示了印表機的任何功能,比如:
printer:print
授權流程
授權其實就是檢視有沒有許可權,有就授權給它
授權步驟:
Step 1: Application or framework code invokes any of the Subject hasRole*, checkRole*, isPermitted*, or checkPermission* method variants, passing in whatever permission or role representation is required.
Step 2: The Subject instance, typically a DelegatingSubject (or a subclass) delegates to the application’s SecurityManager by calling the securityManager’s nearly identical respective hasRole*, checkRole*, isPermitted*, or checkPermission* method variants (the securityManager implements the org.apache.shiro.authz.Authorizer interface, which defines all Subject-specific authorization methods).
Step 3: The SecurityManager, being a basic ‘umbrella’ component, relays/delegates to its internal org.apache.shiro.authz.Authorizer instance by calling the authorizer’s respective hasRole*, checkRole*, isPermitted*, or checkPermission* method. The authorizer instance is by default a ModularRealmAuthorizer instance, which supports coordinating one or more Realm instances during any authorization operation.
Step 4: Each configured Realm is checked to see if it implements the same Authorizer interface. If so, the Realm’s own respective hasRole*, checkRole*, isPermitted*, or checkPermission* method is called.
原始碼下載地址:
GITHUB原始碼下載地址:
本文章由[諳憶]編寫, 所有權利保留。
歡迎轉載,分享是進步的源泉。
相關推薦
【Shiro】Shiro從小白到大神(三)-許可權認證(授權)
本節講許可權認證,也就是授權 基於角色的訪問控制和基於許可權的訪問控制的小例項 以及註解式授權和JSP標籤授權詳解 許可權認證 許可權認證核心要素 許可權認證,也就是訪問控制,即在應用中控制誰能訪問哪些資源 在許可權認證中,最核心的三
【Shiro】Shiro從小白到大神(五)-自定義Realm
用資料庫的話,至少會涉及到這幾張表: 使用者表,角色表,許可權表 角色和使用者是一對多的關係 多個使用者可以擁有同一個角色 角色和許可權在這裡也是一對多的關係 一個角色可以擁有很多個許可權 資料庫表名: t_role 角色表 並插入如下資料
【 分類 】- Shiro
專欄達人 授予成功建立個人部落格專欄
【筆記】shiro中的session設定:
1.匯入依賴包<dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-guartz</artifactId><version>
【Shiro】Shiro登入驗證失敗問題
shiro登入驗證一直失敗: 原因: 在使用者註冊時,採用如下加密方法: /** * md5加密工具 * @param var * 要加密的字串 * @param iterations * 加密次數 * @return */ public
【筆記】shiro中的RememberMe設定:
修改spring-shiro.xml檔案<bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie"><property name="name" value="m
【shiro】shiro學習筆記1-shiro初識
認證流程 環境 程式碼 總結 認證流程 Created with Raphaël 2.1.0Start構造SecurityManager環境Subject.login
【Apache-Shiro】shiro配置詳解
Apache-Shiro旨在簡化身份驗證和授權,為企業應用提供安全解決方案。 1.配置web.xml <filter> <filter-name>shiroFilter</filter-name>
洛谷P3376【模板】網絡最大流 Dinic模板
span -c -s blog name sca print 技術 pop 之前的Dinic模板照著劉汝佳寫的vector然後十分鬼畜跑得奇慢無比,雖然別人這樣寫也沒慢多少但是自己的就是令人捉急。 改成鄰接表之後快了三倍,雖然還是比較慢但是自己比較滿意了。雖然一開始ecnt
【hive】hive表很大的時候查詢報錯問題
一段時間 partition 查詢 query order exception concat 使用 小時 線上hive使用環境出現了一個奇怪的問題,跑一段時間就報如下錯誤: FAILED: SemanticException MetaException(message
洛谷P3376 【模板】網絡最大流
規模 ostream style 一次 ios 分層 nic i++ %d P3376 【模板】網絡最大流 題目描述 如題,給出一個網絡圖,以及其源點和匯點,求出其網絡最大流。 輸入輸出格式 輸入格式: 第一行包含四個正整數N
luogu3376 【模板】網絡最大流 dinic
truct out ios div std main pty stream add 當前弧優化、單路增廣 #include <iostream> #include <cstring> #include <cstdio> #include
【CF913F】Strongly Connected Tournament 概率神題
左右 sca str names a* int tmp 一場 過程 【CF913F】Strongly Connected Tournament 題意:有n個人進行如下錦標賽: 1.所有人都和所有其他的人進行一場比賽,其中標號為i的人打贏標號為j的人(i<j)的概率
洛谷 P3376 【【模板】網絡最大流】
mem oid div pty ack turn color print from 題目描述 如題,給出一個網絡圖,以及其源點和匯點,求出其網絡最大流。 輸入 第一行包含四個正整數N、M、S、T,分別表示點的個數、有向邊的個數、源點序號、匯點序號。 接下來M行每行包含三個
【NOIP2013】貨車運輸 最大生成樹+倍增
nbsp get 最小值 每次 pac def tin map math 題目大意:給你一張n個點m條邊的圖,有q次詢問,每次讓你找出一條從x至y的路徑,使得路徑上經過的邊的最小值最大,輸出這個最大的最小值。 顯然,經過的路徑必然在這張圖的最大生成樹上。 我們求出這個圖
網路程式設計基礎【day09】:socket接收大資料(五)
本節內容 1、概述 2、socket接收大資料 3、中文字元的坑 一、概述 上篇部落格寫到了,就是說當伺服器傳送至客戶端的資料,大於客戶端設定的資料,則就會把資料服務端發過來的資料剩餘資料存在IO緩衝區中,那我們如何解決這個問題呢? 有的同學就說了: 改大客戶端接收的資料的大小=&
【分治】輸出前k大的數
描述 給定一個數組,統計前k大的數並且把這k個數從大到小輸出。 輸入第一行包含一個整數n,表示陣列的大小。n < 100000。第二行包含n個整數,表示陣列的元素,整數之間以一個空格分開。每個整數的絕對值不超過100000000。第三行包含一個整數k。k < n。輸出從大到小輸出前k大的數,每
【筆記】生成函式與大揹包問題
網頁崩了。。。具體內容心情好了再貼。。。 1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 ll p[100005]; 5 ll q[200005];
【 P3952】 時間複雜度 大模擬題解
題目連結 完全模擬 1.模擬結果 當我們的模擬程式執行結束時,直接執行模擬結果函式,用於比對我們的結果和資料給出的結果。 1 bool yes(char a[],char b[]) 2 { 3 for(int i=0;
(轉)Spring事務異常回滾機制(出處在文末,轉自李慕白大神)
Spring事務異常回滾,捕獲異常不丟擲就不會回滾 推薦:Spring transaction 事務 --Isolation & Progation Java異常處理主要通過5個關鍵字控制:try、catch、throw、throws和finally。try的意思是試試它所包含的