</span><span style="color: #0000ff">import</span><span style="color: #000000"> java.util.List;</br> </span><span style="color: #0000ff">import</span><span style="color: #000000"> javax.persistence.Column;</br> </span><span style="color: #0000ff">import</span><span style="color: #000000"> javax.persistence.Entity;</br> </span><span style="color: #0000ff">import</span><span style="color: #000000"> javax.persistence.FetchType;</br> </span><span style="color: #0000ff">import</span><span style="color: #000000"> javax.persistence.GeneratedValue;</br> </span><span style="color: #0000ff">import</span><span style="color: #000000"> javax.persistence.Id;</br> </span><span style="color: #0000ff">import</span><span style="color: #000000"> javax.persistence.JoinColumn;</br> </span><span style="color: #0000ff">import</span><span style="color: #000000"> javax.persistence.JoinTable;</br> </span><span style="color: #0000ff">import</span><span style="color: #000000"> javax.persistence.ManyToMany;</br>
</span><span style="color: #0000ff">import</span><span style="color: #000000"> com.fasterxml.jackson.annotation.JsonBackReference;</br>
@Entity</br> </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span><span style="color: #000000"> User {</br>
1@Id</br> 2@GeneratedValue</br> 3</span><span style="color: #0000ff">private</span> Integer user_id;<span style="color: #008000">//</span><span style="color: #008000">用户序号</span></br>
<span style="color: #000000"> @Column(unique</span>=<span style="color: #0000ff">true</span><span style="color: #000000">)</br> </span><span style="color: #0000ff">private</span> String name;<span style="color: #008000">//</span><span style="color: #008000">账户</span></br> </br> <span style="color: #0000ff">private</span> String password;<span style="color: #008000">//</span><span style="color: #008000">密码</span></br></br>
1<span style="color: #0000ff">private</span> String salt;<span style="color: #008000">//</span><span style="color: #008000">盐</span></br></br> 2 3<span style="color: #0000ff">private</span> Integer state;<span style="color: #008000">//</span><span style="color: #008000">用户状态</span></br></br> 4 5<span style="color: #0000ff">private</span> String createtime;<span style="color: #008000">//</span><span style="color: #008000">创建时间</span></br></br>
<span style="color: #000000"> @ManyToMany<span style="color: #ff0000">(fetch</span></span><span style="color: #ff0000">=FetchType.EAGER)</span><span style="color: #008000">//</span><span style="color: #008000">立即从数据库中进行加载数据;</span> @JoinTable(name="User_Role",joinColumns={@JoinColumn(name="user_id"<span style="color: #000000">)},</br> inverseJoinColumns</span>={@JoinColumn(name="role_id"<span style="color: #000000">)})</br> </span><span style="color: #0000ff">private</span> List<Role><span style="color: #000000"> roleList;</br>
1@JsonBackReference 2</span><span style="color: #0000ff">public</span> List<Role><span style="color: #000000"> getRoleList(){</br> 3 </span><span style="color: #0000ff">return</span><span style="color: #000000"> roleList;</br> 4}</br> 5</br> 6</span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> setRoleList(List<Role><span style="color: #000000"> roleList){</br> 7 </span><span style="color: #0000ff">this</span>.roleList=<span style="color: #000000">roleList;</br> 8}</br>
</span><span style="color: #000000">
注:其它getter和setter省略</span><span style="color: #000000">
}</span></pre>
<div class="cnblogs\_code\_toolbar"><span class="cnblogs\_code\_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src="https://my.oschina.net//common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></span></div></div> <p> 关于为什么要在getRolelist这个方法上加上@JsonBackReference注解,可以查看这篇文章<a href="http://blog.csdn.net/maxu12345/article/details/45538157" target="\_blank">http://blog.csdn.net/maxu12345/article/details/45538157</a></p> <p> Role实体(角色):</p> <div class="cnblogs\_code"><div class="cnblogs\_code\_toolbar"><span class="cnblogs\_code\_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src="https://my.oschina.net//common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></span></div> <pre><span style="color: #0000ff">package</span><span style="color: #000000"> com.cy.coo.bean;</br></br></span><span style="color: #0000ff">import</span><span style="color: #000000"> java.io.Serializable;</br> </span><span style="color: #0000ff">import</span><span style="color: #000000"> java.util.ArrayList;</br> </span><span style="color: #0000ff">import</span><span style="color: #000000"> java.util.List;</br></br>
</span><span style="color: #0000ff">import</span><span style="color: #000000"> javax.persistence.Entity;</br> </span><span style="color: #0000ff">import</span><span style="color: #000000"> javax.persistence.FetchType;</br> </span><span style="color: #0000ff">import</span><span style="color: #000000"> javax.persistence.GeneratedValue;</br> </span><span style="color: #0000ff">import</span><span style="color: #000000"> javax.persistence.Id;</br> </span><span style="color: #0000ff">import</span><span style="color: #000000"> javax.persistence.JoinColumn;</br> </span><span style="color: #0000ff">import</span><span style="color: #000000"> javax.persistence.JoinTable;</br> </span><span style="color: #0000ff">import</span><span style="color: #000000"> javax.persistence.ManyToMany;</br></br>
</span><span style="color: #0000ff">import</span><span style="color: #000000"> com.fasterxml.jackson.annotation.JsonBackReference;</br></br>
@Entity</br> </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> Role <span style="color: #0000ff">implements</span><span style="color: #000000"> Serializable {</br> </span><span style="color: #0000ff">private</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">final</span> <span style="color: #0000ff">long</span> serialVersionUID = 1L<span style="color: #000000">;</br></br>
1@Id</br> 2@GeneratedValue</br> 3</span><span style="color: #0000ff">private</span> Integer role_id;<span style="color: #008000">//</span><span style="color: #008000">角色序号</span></br></br> 4 5<span style="color: #0000ff">private</span> String role_name;<span style="color: #008000">//</span><span style="color: #008000">角色名称</span></br></br> 6 7<span style="color: #0000ff">private</span> String role_description;<span style="color: #008000">//</span><span style="color: #008000">角色描述</span></br></br>
<span style="color: #000000"> @ManyToMany</br> @JoinTable(name </span>= "User_Role", joinColumns = { @JoinColumn(name = "role_id") }, inverseJoinColumns =<span style="color: #000000"> {</br> @JoinColumn(name </span>= "user_id"<span style="color: #000000">) })</br> </span><span style="color: #0000ff">private</span> List<User> userList=<span style="color: #0000ff">new</span> ArrayList<><span style="color: #000000">();</br></br>
1@ManyToMany<span style="color: #ff0000">(fetch</span></span><span style="color: #ff0000">=</span><span style="color: #000000"><span style="color: #ff0000">FetchType.EAGER)</span></br> 2@JoinTable(name</span>="Role_Function",joinColumns={@JoinColumn(name="role_id")},inverseJoinColumns=<span style="color: #000000">{</br> 3 @JoinColumn(name</span>="function_id"<span style="color: #000000">)})</br> 4</span><span style="color: #0000ff">private</span> List<Function> functionList=<span style="color: #0000ff">new</span> ArrayList<><span style="color: #000000">();</br></br> 5 6@JsonBackReference</br> 7</span><span style="color: #0000ff">public</span> List<Function><span style="color: #000000"> getFunctionList(){</br> 8 </span><span style="color: #0000ff">return</span><span style="color: #000000"> functionList;</br> 9}</br> 10</br> 11</span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> setFunctionList(List<Function><span style="color: #000000"> functionList){</br> 12 </span><span style="color: #0000ff">this</span>.functionList=<span style="color: #000000">functionList;</br> 13}</br> 14 15@JsonBackReference</br> 16</span><span style="color: #0000ff">public</span> List<User><span style="color: #000000"> getUserList() {</br> 17 </span><span style="color: #0000ff">return</span><span style="color: #000000"> userList;</br> 18}</br></br> 19 20</span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> setUserList(List<User><span style="color: #000000"> userList) {</br> 21 </span><span style="color: #0000ff">this</span>.userList =<span style="color: #000000"> userList;</br> 22}</br></br> 23 24</span><span style="color: #0000ff">public</span><span style="color: #000000"> Integer getRole_id() {</br> 25 </span><span style="color: #0000ff">return</span><span style="color: #000000"> role_id;</br> 26}</br></br> 27 28</span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span><span style="color: #000000"> setRole_id(Integer role_id) {</br> 29 </span><span style="color: #0000ff">this</span>.role_id =<span style="color: #000000"> role_id;</br> 30}</br></br></br> 31 32 33</span><span style="color: #0000ff">public</span><span style="color: #000000"> String getRole_name() {</br> 34 </span><span style="color: #0000ff">return</span><span style="color: #000000"> role_name;</br> 35}</br></br> 36 37</span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span><span style="color: #000000"> setRole_name(String role_name) {</br> 38 </span><span style="color: #0000ff">this</span>.role_name =<span style="color: #000000"> role_name;</br> 39}</br> 40 41</span><span style="color: #0000ff">public</span><span style="color: #000000"> String getRole_description() {</br> 42 </span><span style="color: #0000ff">return</span><span style="color: #000000"> role_description;</br> 43}</br> 44 45</span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span><span style="color: #000000"> setRole_description(String role_description) {</br> 46 </span><span style="color: #0000ff">this</span>.role_description =<span style="color: #000000"> role_description;</br> 47}</br>
}</span></pre>
<div class="cnblogs\_code\_toolbar"><span class="cnblogs\_code\_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src="https://my.oschina.net//common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></span></div></div> <p> Function实体(权限):</p> <div class="cnblogs\_code"><div class="cnblogs\_code\_toolbar"><span class="cnblogs\_code\_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src="https://my.oschina.net//common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></span></div> <pre><span style="color: #0000ff">package</span><span style="color: #000000"> com.cy.coo.bean;</br></br></span><span style="color: #0000ff">import</span><span style="color: #000000"> java.util.List;</br></br>
</span><span style="color: #0000ff">import</span><span style="color: #000000"> javax.persistence.Entity;</br> </span><span style="color: #0000ff">import</span><span style="color: #000000"> javax.persistence.GeneratedValue;</br> </span><span style="color: #0000ff">import</span><span style="color: #000000"> javax.persistence.Id;</br> </span><span style="color: #0000ff">import</span><span style="color: #000000"> javax.persistence.JoinColumn;</br> </span><span style="color: #0000ff">import</span><span style="color: #000000"> javax.persistence.JoinTable;</br> </span><span style="color: #0000ff">import</span><span style="color: #000000"> javax.persistence.ManyToMany;</br></br>
@Entity</br> </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span><span style="color: #000000"> Function {</br> </br> @Id</br> @GeneratedValue</br> </span><span style="color: #0000ff">private</span> Integer function_id;<span style="color: #008000">//</span><span style="color: #008000">功能序号</span></br></br>
<span style="color: #0000ff">private</span> String permission;<span style="color: #008000">//</span><span style="color: #008000">权限字符串</span></br>
<span style="color: #000000"> </br></br>
1@ManyToMany</br> 2@JoinTable(name </span>= "Role_Function", joinColumns = { @JoinColumn(name = "function_id") }, inverseJoinColumns =<span style="color: #000000"> {</br> 3 @JoinColumn(name </span>= "role_id"<span style="color: #000000">) })</br> 4</span><span style="color: #0000ff">private</span> List<Role><span style="color: #000000"> roleList;</br></br> 5 6</span><span style="color: #0000ff">public</span> List<Role><span style="color: #000000"> getRoleList() {</br> 7 </span><span style="color: #0000ff">return</span><span style="color: #000000"> roleList;</br> 8}</br> 9 10</span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> setRoleList(List<Role><span style="color: #000000"> roleList) {</br> 11 </span><span style="color: #0000ff">this</span>.roleList =<span style="color: #000000"> roleList;</br> 12}</br> 13 14</span><span style="color: #0000ff">public</span><span style="color: #000000"> Integer getFunction_id() {</br> 15 </span><span style="color: #0000ff">return</span><span style="color: #000000"> function_id;</br> 16}</br> 17 18</span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span><span style="color: #000000"> setFunction_id(Integer function_id) {</br> 19 </span><span style="color: #0000ff">this</span>.function_id =<span style="color: #000000"> function_id;</br> 20}</br></br></br> 21 22 23</span><span style="color: #0000ff">public</span><span style="color: #000000"> String getPermission() {</br> 24 </span><span style="color: #0000ff">return</span><span style="color: #000000"> permission;</br> 25}</br></br> 26 27</span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span><span style="color: #000000"> setPermission(String permission) {</br> 28 </span><span style="color: #0000ff">this</span>.permission =<span style="color: #000000"> permission;</br> 29}</br>
}</span></pre>
<div class="cnblogs\_code\_toolbar"><span class="cnblogs\_code\_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src="https://my.oschina.net//common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></span></div></div> <p> 这几个实体类的具体关系如下图,也完美的解释了为什么会生成5张表:</p> <p><img src="https://images2015.cnblogs.com/blog/945531/201705/945531-20170521201754853-1187454130.png" alt=""></p> <p> 三、写一个与前端交互的controller方法,service层的具体逻辑的方法</p> <div class="cnblogs\_code"> <pre> @PostMapping(value = "/logon"<span style="color: #000000">)</br> </span><span style="color: #0000ff">public</span><span style="color: #000000"> Object logon(@RequestBody Login user) {</br></br></div> <p> 这个方法就是将前端传来的username和password封装到Login类中,Login类也只有这两个属性,然后调用Service层的login方法来处理。下面是service的login方法:</p> <div class="cnblogs\_code"><div class="cnblogs\_code\_toolbar"><span class="cnblogs\_code\_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src="https://my.oschina.net//common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></span></div> <pre><span style="color: #008000">/\*\*</span><span style="color: #008000"></br> \* 用户登录 create by yyc 2017年5月12日下午4:31:26</br> </span><span style="color: #008000">\*/</span><span style="color: #000000"></br> @Override</br> </span><span style="color: #0000ff">public</span><span style="color: #000000"> Object login(Login user) {</br> String username </span>=<span style="color: #000000"> user.getUsername().trim();</br> String password </span>=<span style="color: #000000"> user.getPassword().trim();</br></br>1 </span><span style="color: #0000ff">return</span><span style="color: #000000"> userService.login(user);</br> 2}</span></pre>
<div class="cnblogs\_code\_toolbar"><span class="cnblogs\_code\_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src="https://my.oschina.net//common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></span></div></div> <p> service中主要是将用户名和密码封装到shiro的UsernamePasswordToken中,然后将token对象放到SecurityUtils.getSubject()的login方法中,以便shiro认证登录使用。认证失败就会抛出AuthenticationException这个异常,就对异常进行相应的操作,这里的处理是抛出一个自定义异常ResultException。</p> <p> 四、写我认为的shiro的核心类</p> <div class="cnblogs\_code"><div class="cnblogs\_code\_toolbar"><span class="cnblogs\_code\_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src="https://my.oschina.net//common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></span></div> <pre><span style="color: #0000ff">package</span><span style="color: #000000"> com.cy.coo.shiro;1 </span><span style="color: #008000">//</span><span style="color: #008000"> 检查空值</span></br> 2 <span style="color: #0000ff">if</span> (!<span style="color: #000000">CheckObjectField.CheckField(user)) {</br> 3 </span><span style="color: #0000ff">throw</span> <span style="color: #0000ff">new</span> ResultException(CheckObjectField.FieldName + "为空!"<span style="color: #000000">); 4 }</br></br></br> 5 6 </span><span style="color: #008000">//</span><span style="color: #008000"> 检查用户状态</span></br> 7 Integer userState =<span style="color: #000000"> userRepository.findUserState(username);</br> 8 </span><span style="color: #0000ff">if</span> (<span style="color: #0000ff">new</span> Integer("1"<span style="color: #000000">).equals(userState)) {</br> 9 </span><span style="color: #0000ff">throw</span> <span style="color: #0000ff">new</span> ResultException("该用户已锁定"<span style="color: #000000">);</br> 10 }</br></br> 11 12 </span><span style="color: #008000">//</span><span style="color: #008000"> 1、获取Subject实例对象</span></br> 13 Subject currentUser =<span style="color: #000000"> SecurityUtils.getSubject();</br></br> 14 15 </span><span style="color: #008000">//</span><span style="color: #008000"> 2、判断当前用户是否登录</span></br> 16 <span style="color: #0000ff">if</span> (currentUser.isAuthenticated() == <span style="color: #0000ff">false</span><span style="color: #000000">) {</br> 17 </span><span style="color: #008000">//</span><span style="color: #008000"> 3、将用户名和密码封装到UsernamePasswordToken</span></br> 18 UsernamePasswordToken token = <span style="color: #0000ff">new</span><span style="color: #000000"> UsernamePasswordToken(username, password);</br></br> 19 20 </span><span style="color: #008000">//</span><span style="color: #008000"> 4、认证</span></br> 21 <span style="color: #0000ff">try</span><span style="color: #000000"> {</br> 22 currentUser.login(token);</span><span style="color: #008000">//</span><span style="color: #008000"> 传到MyAuthorizingRealm类中的方法进行认证</span> 23 Session session =<span style="color: #000000"> currentUser.getSession();</br> 24 session.setAttribute(</span>"username"<span style="color: #000000">, username);</br> 25 } </span><span style="color: #0000ff">catch</span><span style="color: #000000"> (AuthenticationException e) {</br> 26 </span><span style="color: #0000ff">throw</span> <span style="color: #0000ff">new</span> ResultException("密码或用户名错误"<span style="color: #000000">);</br> 27 }</br> 28 }</br> 29 </span><span style="color: #008000">//</span><span style="color: #008000"> 根据用户名查询角色信息</span></br> 30 List<String> RoleNames =<span style="color: #000000"> roleService.findRoleName(username);</br></br> 31 32 </span><span style="color: #0000ff">return</span> <span style="color: #0000ff">new</span><span style="color: #000000"> LoginReturn(username, RoleNames);</br> 33 34}</span></pre>
</span><span style="color: #0000ff">import</span><span style="color: #000000"> org.apache.shiro.authc.AuthenticationException;</br> </span><span style="color: #0000ff">import</span><span style="color: #000000"> org.apache.shiro.authc.AuthenticationInfo;</br> </span><span style="color: #0000ff">import</span><span style="color: #000000"> org.apache.shiro.authc.AuthenticationToken;</br> </span><span style="color: #0000ff">import</span><span style="color: #000000"> org.apache.shiro.authc.SimpleAuthenticationInfo;</br> </span><span style="color: #0000ff">import</span><span style="color: #000000"> org.apache.shiro.authc.UsernamePasswordToken;</br> </span><span style="color: #0000ff">import</span><span style="color: #000000"> org.apache.shiro.authz.AuthorizationInfo;</br> </span><span style="color: #0000ff">import</span><span style="color: #000000"> org.apache.shiro.authz.SimpleAuthorizationInfo;</br> </span><span style="color: #0000ff">import</span><span style="color: #000000"> org.apache.shiro.realm.AuthorizingRealm;</br> </span><span style="color: #0000ff">import</span><span style="color: #000000"> org.apache.shiro.subject.PrincipalCollection;</br> </span><span style="color: #0000ff">import</span><span style="color: #000000"> org.apache.shiro.util.ByteSource;</br> </span><span style="color: #0000ff">import</span><span style="color: #000000"> org.slf4j.Logger;</br> </span><span style="color: #0000ff">import</span><span style="color: #000000"> org.slf4j.LoggerFactory;</br> </span><span style="color: #0000ff">import</span><span style="color: #000000"> org.springframework.beans.factory.annotation.Autowired;</br></br>
</span><span style="color: #0000ff">import</span><span style="color: #000000"> com.cy.coo.bean.Function;</br> </span><span style="color: #0000ff">import</span><span style="color: #000000"> com.cy.coo.bean.Role;</br> </span><span style="color: #0000ff">import</span><span style="color: #000000"> com.cy.coo.bean.User;</br> </span><span style="color: #0000ff">import</span><span style="color: #000000"> com.cy.coo.service.UserService;</br></br>
</span><span style="color: #008000">/**</span><span style="color: #008000"> * *
-
</span><span style="color: #808080">@author</span><span style="color: #008000"> E-mail:34782655@qq.com
-
</span><span style="color: #808080">@version</span><span style="color: #008000"> 创建时间:2017年5月8日 上午10:50:50
-
类说明:
-
-- </span><span style="color: #008000">*/</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> MyAuthorizingRealm <span style="color: #0000ff">extends</span><span style="color: #000000"> AuthorizingRealm {
</span><span style="color: #0000ff">private</span> <span style="color: #0000ff">final</span> <span style="color: #0000ff">static</span> Logger logger=LoggerFactory.getLogger(MyAuthorizingRealm.<span style="color: #0000ff">class</span><span style="color: #000000">);
@Autowired </span><span style="color: #0000ff">private</span><span style="color: #000000"> UserService userService;</br> </span><span style="color: #008000">//</span><span style="color: #008000">shiro的权限配置方法</span></br>
<span style="color: #000000"> @Override</br> </span><span style="color: #0000ff">protected</span><span style="color: #000000"> AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {</br></br>
1 logger.info(</span>"权限配置-->doGetAuthorizationInfo"<span style="color: #000000">);</br></br> 2 3 SimpleAuthorizationInfo authorizationInfo </span>= <span style="color: #0000ff">new</span><span style="color: #000000"> SimpleAuthorizationInfo();</br> 4 logger.info(</span>"----------------------------->"+<span style="color: #000000">principals.getPrimaryPrincipal());</br> 5 User user</span>=<span style="color: #000000">(User) principals.getPrimaryPrincipal();</br> 6 </span><span style="color: #0000ff">for</span><span style="color: #000000">(Role role:user.getRoleList()){</br> 7 authorizationInfo.addRole(role.getRole_name());</br> 8 </span><span style="color: #0000ff">for</span><span style="color: #000000">(Function function:role.getFunctionList()){</br> 9 authorizationInfo.addStringPermission(function.getPermission());</br> 10 }</br> 11 }</br> 12 13 logger.info(</span>"用户"+user.getName()+"具有的角色:"+<span style="color: #000000">authorizationInfo.getRoles());</br> 14 logger.info(</span>"用户"+user.getName()+"具有的权限:"+<span style="color: #000000">authorizationInfo.getStringPermissions());</br></br> 15 16 </span><span style="color: #0000ff">return</span><span style="color: #000000"> authorizationInfo;</br> 17} 18 19 </span><span style="color: #008000">//</span><span style="color: #008000">shiro的身份验证方法</span></br>
<span style="color: #000000"> @Override</br> </span><span style="color: #0000ff">protected</span> AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) <span style="color: #0000ff">throws</span><span style="color: #000000"> AuthenticationException {</br></br>
1 logger.info(</span>"正在验证身份..."<span style="color: #000000">);</br> 2 SimpleAuthenticationInfo info</span>=<span style="color: #0000ff">null</span><span style="color: #000000">;</br></br> 3 4 </span><span style="color: #008000">//</span><span style="color: #008000">将token转换成UsernamePasswordToken</span></br> 5 UsernamePasswordToken upToken =<span style="color: #000000"> (UsernamePasswordToken) token;</br> 6 </span><span style="color: #008000">//</span><span style="color: #008000">从转换后的token中获取用户名</span></br> 7 String username=<span style="color: #000000"> upToken.getUsername(); </br> 8 logger.info(</span>"----->"+<span style="color: #000000">username);</br></br> 9 10 </span><span style="color: #008000">//</span><span style="color: #008000">查询数据库,得到用户</span></br> 11 User user=<span style="color: #000000">userService.findByName(username);</br> 12 </span><span style="color: #0000ff">if</span>(user==<span style="color: #0000ff">null</span><span style="color: #000000">){</br> 13 </span><span style="color: #0000ff">return</span> <span style="color: #0000ff">null</span><span style="color: #000000">;</br> 14 }</br> 15 16 </span><span style="color: #008000">//</span><span style="color: #008000">得到加密密码的盐值</span></br> 17 ByteSource salt =<span style="color: #000000"> ByteSource.Util.bytes(user.getSalt());</br>
</span><span style="color: #008000">//</span><span style="color: #008000"> logger.info("加密密码的盐:"+salt);</br> </span><span style="color: #008000">//</span> <span style="color: #008000">//</span><span style="color: #008000">得到盐值加密后的密码:只用于方便数据库测试,后期不会用到。</br> </span><span style="color: #008000">//</span><span style="color: #008000"> Object md = new SimpleHash("MD5",upToken.getPassword(),salt,1024);</br> </span><span style="color: #008000">//</span><span style="color: #008000"> logger.info("盐值加密后的密码:"+md);</span></br> <span style="color: #000000"> info </span>= <span style="color: #0000ff">new</span><span style="color: #000000"> SimpleAuthenticationInfo(</br> user, </span><span style="color: #008000">//</span><span style="color: #008000">用户名</span></br> user.getPassword(), <span style="color: #008000">//</span><span style="color: #008000">密码</span></br> salt, <span style="color: #008000">//</span><span style="color: #008000">加密的盐值</span></br> getName() <span style="color: #008000">//</span><span style="color: #008000">realm name</span></br> <span style="color: #000000"> );</br> </span><span style="color: #0000ff">return</span><span style="color: #000000"> info;</br> }
}</span></pre>
<div class="cnblogs\_code\_toolbar"><span class="cnblogs\_code\_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src="https://my.oschina.net//common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></span></div></div> <p> 这个类继承shiro的AuthorizingRealm ,主要有两个方法,一个是权限配置,一个是身份认证,权限配置:当我们要用到权限时shiro会回调doGetAuthorizationInfo这个方法,对当前的用户分配权限,这个方法中的嵌套for循环是怎么回事呢,其实就是将数据库中的对应角色、权限放进shiro中,让他来管理,这需要实体类User中有getRoleList()、getRole\_name()和getFunctionList()、getPermission这几个方法,这几个个方法就是设计数据库和实体类时的东西了,关于shiro权限相关的实体类在前面已经给出了。身份认证:在用户登录认证的时候回调,认证失败就抛出AuthenticationException。</p> <p> 五、shiro配置类</p> <div> <div class="cnblogs\_code"><div class="cnblogs\_code\_toolbar"><span class="cnblogs\_code\_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src="https://my.oschina.net//common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></span></div> <pre><span style="color: #0000ff">package</span><span style="color: #000000"> com.cy.coo.shiro;</br></span><span style="color: #0000ff">import</span><span style="color: #000000"> java.util.LinkedHashMap;</br> </span><span style="color: #0000ff">import</span><span style="color: #000000"> java.util.Map;</br></br>
</span><span style="color: #0000ff">import</span><span style="color: #000000"> org.apache.shiro.authc.credential.HashedCredentialsMatcher;</br> </span><span style="color: #0000ff">import</span><span style="color: #000000"> org.apache.shiro.cache.ehcache.EhCacheManager;</br> </span><span style="color: #0000ff">import</span><span style="color: #000000"> org.apache.shiro.mgt.SecurityManager;</br> </span><span style="color: #0000ff">import</span><span style="color: #000000"> org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;</br> </span><span style="color: #0000ff">import</span><span style="color: #000000"> org.apache.shiro.spring.web.ShiroFilterFactoryBean;</br> </span><span style="color: #0000ff">import</span><span style="color: #000000"> org.apache.shiro.web.mgt.CookieRememberMeManager;</br> </span><span style="color: #0000ff">import</span><span style="color: #000000"> org.apache.shiro.web.mgt.DefaultWebSecurityManager;</br> </span><span style="color: #0000ff">import</span><span style="color: #000000"> org.apache.shiro.web.servlet.SimpleCookie;</br> </span><span style="color: #0000ff">import</span><span style="color: #000000"> org.slf4j.Logger;</br> </span><span style="color: #0000ff">import</span><span style="color: #000000"> org.slf4j.LoggerFactory; </span><span style="color: #0000ff">import</span><span style="color: #000000"> org.springframework.beans.factory.annotation.Qualifier;</br> </span><span style="color: #0000ff">import</span><span style="color: #000000"> org.springframework.cache.ehcache.EhCacheManagerFactoryBean;</br> </span><span style="color: #0000ff">import</span><span style="color: #000000"> org.springframework.context.annotation.Bean;</br> </span><span style="color: #0000ff">import</span><span style="color: #000000"> org.springframework.context.annotation.Configuration;</br> </span><span style="color: #0000ff">import</span><span style="color: #000000"> org.springframework.core.io.ClassPathResource;</br></br>
@Configuration </span><span style="color: #008000">//</span><span style="color: #008000"> 等价于beans</span></br> <span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span><span style="color: #000000"> ShiroConfig {</br></br>
1</span><span style="color: #0000ff">private</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">final</span> Logger log = LoggerFactory.getLogger(ShiroFilterFactoryBean.<span style="color: #0000ff">class</span><span style="color: #000000">);</br></br> 2 3@Bean(name </span>= "securityManager"<span style="color: #000000">)</br> 4</span><span style="color: #0000ff">public</span> SecurityManager securityManager(@Qualifier("authRealm"<span style="color: #000000">) MyAuthorizingRealm authRealm,</br> 5 @Qualifier(</span>"cookieRememberMeManager"<span style="color: #000000">) CookieRememberMeManager cookieRememberMeManager) {</br> 6 log.info(</span>"securityManager()"<span style="color: #000000">);</br> 7 DefaultWebSecurityManager securityManager </span>= <span style="color: #0000ff">new</span><span style="color: #000000"> DefaultWebSecurityManager();</br> 8 </span><span style="color: #008000">//</span><span style="color: #008000"> 设置realm.</span></br>
<span style="color: #000000"> securityManager.setRealm(authRealm);</br></br>
</span><span style="color: #008000">//</span><span style="color: #008000"> 设置rememberMe管理器</span></br>
<span style="color: #000000"> securityManager.setRememberMeManager(cookieRememberMeManager);</br></br>
1 </span><span style="color: #0000ff">return</span><span style="color: #000000"> securityManager;</br> 2} 3 4</span><span style="color: #008000">/**</span><span style="color: #008000"></br> 5 * realm</br> 6 * 7 * </span><span style="color: #808080">@return</span></br> 8 <span style="color: #008000">*/</span><span style="color: #000000"></br> 9@Bean(name </span>= "authRealm"<span style="color: #000000">)</br> 10</span><span style="color: #0000ff">public</span><span style="color: #000000"> MyAuthorizingRealm myAuthRealm(</br> 11 @Qualifier(</span>"hashedCredentialsMatcher"<span style="color: #000000">) HashedCredentialsMatcher matcher,</br> 12 @Qualifier(</span>"ehCacheManager"<span style="color: #000000">) EhCacheManager ehCacheManager) {</br> 13 log.info(</span>"myShiroRealm()"<span style="color: #000000">);</br> 14 MyAuthorizingRealm myAuthorizingRealm </span>= <span style="color: #0000ff">new</span><span style="color: #000000"> MyAuthorizingRealm();</br> 15 </span><span style="color: #008000">//</span><span style="color: #008000"> 设置密码凭证匹配器</span></br> 16 myAuthorizingRealm.setCredentialsMatcher(matcher); <span style="color: #008000">//</span><span style="color: #008000"> myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());</br> 17 </span><span style="color: #008000">//</span><span style="color: #008000"> 设置缓存管理器</span></br>
<span style="color: #000000"> myAuthorizingRealm.setCacheManager(ehCacheManager);</br>
1 </span><span style="color: #0000ff">return</span><span style="color: #000000"> myAuthorizingRealm;</br> 2}</br>
</span><span style="color: #008000">/**</span><span style="color: #008000"></br> * 缓存管理器</br> * </span><span style="color: #808080">@return</span> <span style="color: #008000">*/</span><span style="color: #000000"></br> @Bean(value</span>="ehCacheManager"<span style="color: #000000">)</br> </span><span style="color: #0000ff">public</span> EhCacheManager ehCacheManager(@Qualifier("ehCacheManagerFactoryBean"<span style="color: #000000">) EhCacheManagerFactoryBean bean) {</br> log.info(</span>"ehCacheManager()"<span style="color: #000000">);</br> EhCacheManager cacheManager </span>= <span style="color: #0000ff">new</span><span style="color: #000000"> EhCacheManager(); </br>
cacheManager.setCacheManagerConfigFile(</span>"classpath:ehcache-shiro.xml"<span style="color: #000000">);</br> </span><span style="color: #0000ff">return</span><span style="color: #000000"> cacheManager;</br> }</br>
1</span><span style="color: #008000">/**</span><span style="color: #008000"></br> 2 * cookie对象;</br> 3 * </br> 4 * </span><span style="color: #808080">@return</span></br> 5 <span style="color: #008000">*/</span><span style="color: #000000"></br> 6@Bean</br> 7</span><span style="color: #0000ff">public</span><span style="color: #000000"> SimpleCookie rememberMeCookie() {</br> 8 log.info(</span>"rememberMeCookie()"<span style="color: #000000">);</br> 9 </span><span style="color: #008000">//</span><span style="color: #008000"> 这个参数是cookie的名称,对应前端的checkbox 的name = rememberMe</span></br> 10 SimpleCookie simpleCookie = <span style="color: #0000ff">new</span> SimpleCookie("rememberMe"<span style="color: #000000">);</br> 11 </span><span style="color: #008000">//</span><span style="color: #008000"> <!-- 记住我cookie生效时间30天(259200) ,单位秒;--></span></br> 12 simpleCookie.setMaxAge(259200<span style="color: #000000">);</br> 13 </span><span style="color: #0000ff">return</span><span style="color: #000000"> simpleCookie;</br> 14}</br> 15 16</span><span style="color: #008000">/**</span><span style="color: #008000"></br> 17 * 记住我管理器 cookie管理对象;</br></br> 18 * 19 * </span><span style="color: #808080">@return</span></br> 20 <span style="color: #008000">*/</span><span style="color: #000000"></br> 21@Bean(name </span>= "cookieRememberMeManager"<span style="color: #000000">)</br> 22</span><span style="color: #0000ff">public</span><span style="color: #000000"> CookieRememberMeManager rememberMeManager() {</br> 23 System.out.println(</span>"rememberMeManager()"<span style="color: #000000">);</br> 24 CookieRememberMeManager cookieRememberMeManager </span>= <span style="color: #0000ff">new</span><span style="color: #000000"> CookieRememberMeManager();</br> 25 cookieRememberMeManager.setCookie(rememberMeCookie());</br> 26 </span><span style="color: #0000ff">return</span><span style="color: #000000"> cookieRememberMeManager;</br> 27}</br> 28 29</span><span style="color: #008000">/**</span><span style="color: #008000"> 30 * 密码匹配凭证管理器 31 * 32 * </span><span style="color: #808080">@return</span></br> 33 <span style="color: #008000">*/</span><span style="color: #000000"></br> 34@Bean(name </span>= "hashedCredentialsMatcher"<span style="color: #000000">)</br> 35</span><span style="color: #0000ff">public</span><span style="color: #000000"> HashedCredentialsMatcher hashedCredentialsMatcher() {</br> 36 log.info(</span>"hashedCredentialsMatcher()"<span style="color: #000000">);</br> 37 HashedCredentialsMatcher hashedCredentialsMatcher </span>= <span style="color: #0000ff">new</span><span style="color: #000000"> HashedCredentialsMatcher();</br></br> 38 39 hashedCredentialsMatcher.setHashAlgorithmName(</span>"MD5");<span style="color: #008000">//</span><span style="color: #008000"> 散列算法:这里使用MD5算法;</span></br> 40 hashedCredentialsMatcher.setHashIterations(1024);<span style="color: #008000">//</span><span style="color: #008000"> 散列的次数,比如散列两次,相当于</br> 41 </span><span style="color: #008000">//</span><span style="color: #008000"> md5(md5(""));</span></br></br> 42 43 <span style="color: #0000ff">return</span><span style="color: #000000"> hashedCredentialsMatcher;</br> 44}</br> 45 46</span><span style="color: #008000">/**</span><span style="color: #008000"></br> 47 * 开启shiro aop注解支持. 使用代理方式;所以需要开启代码支持; Controller才能使用@RequiresPermissions</br></br> 48 * 49 * </span><span style="color: #808080">@param</span><span style="color: #008000"> securityManager</br> 50 * </span><span style="color: #808080">@return</span></br> 51 <span style="color: #008000">*/</span><span style="color: #000000"></br> 52@Bean</br> 53</span><span style="color: #0000ff">public</span><span style="color: #000000"> AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(</br> 54 @Qualifier(</span>"securityManager"<span style="color: #000000">) SecurityManager securityManager) {</br> 55 log.info(</span>"authorizationAttributeSourceAdvisor()"<span style="color: #000000">);</br> 56 AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor </span>= <span style="color: #0000ff">new</span><span style="color: #000000"> AuthorizationAttributeSourceAdvisor();</br> 57 authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);</br> 58 </span><span style="color: #0000ff">return</span><span style="color: #000000"> authorizationAttributeSourceAdvisor;</br> 59}</br> 60 61@Bean</br> 62</span><span style="color: #0000ff">public</span> ShiroFilterFactoryBean shiroFilter(@Qualifier("securityManager"<span style="color: #000000">) SecurityManager securityManager) {</br> 63 log.info(</span>"shirFilter()"<span style="color: #000000">);</br> 64 ShiroFilterFactoryBean shiroFilterFactoryBean </span>= <span style="color: #0000ff">new</span><span style="color: #000000"> ShiroFilterFactoryBean();</br></br> 65 66 </span><span style="color: #008000">//</span><span style="color: #008000"> 必须设置 SecurityManager</span></br>
<span style="color: #000000"> shiroFilterFactoryBean.setSecurityManager(securityManager);</br></br>
1 </span><span style="color: #008000">//</span><span style="color: #008000"> 拦截器.</span></br> 2 Map<String, String> map = <span style="color: #0000ff">new</span> LinkedHashMap<String, String><span style="color: #000000">();</br></br> 3 4 map.put(</span>"/logout", "logout"<span style="color: #000000">);</br> 5 map.put(</span>"/login", "anon"<span style="color: #000000">);</br> 6 map.put(</span>"/logon", "anon"<span style="color: #000000">);</br></br> 7 8 map.put(</span>"/**", "authc"<span style="color: #000000">);</br></br> 9 10 </span><span style="color: #008000">//</span><span style="color: #008000"> 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面</span></br> 11 shiroFilterFactoryBean.setLoginUrl("/login"<span style="color: #000000">);</br> 12 </span><span style="color: #008000">//</span><span style="color: #008000"> 登录成功后要跳转的链接</span></br> 13 shiroFilterFactoryBean.setSuccessUrl("/index"<span style="color: #000000">);</br> 14 </span><span style="color: #008000">//</span><span style="color: #008000"> 未授权界面;</span></br> 15 shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorized"<span style="color: #000000">);</br></br> 16 17 shiroFilterFactoryBean.setFilterChainDefinitionMap(map);</br> 18 </span><span style="color: #0000ff">return</span><span style="color: #000000"> shiroFilterFactoryBean;</br> 19}</br>
}</span></pre>
<div class="cnblogs\_code\_toolbar"><span class="cnblogs\_code\_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src="https://my.oschina.net//common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></span></div></div> </div> <p> 这个没什么好说的,最后一个类是shiro的过滤器配置。可以看到我在每个方法上面加了一个@Bean(name="..."),其实这是spring的注解,将这个类放到spring容器中管理,在方法形参中使用@Qualifier(...)来使用它,以致于我们在方法体中调用某个方法时就方面多了。</p> <p>在这里,关于shiro在springboot中的基础配置就完成了。下面是期间遇到的错误解决方案:</p> <div id="magicdomid24" class="ace-line gutter-author-p-97562 emptyGutter" data-author-initials="ﻬ" data-author-name="ﻬc m d" data-author-link=""><span class="author-p-97562"><span style="color: #ff6600">错误一</span>:关于实体类的错误,springboot 中hibernate懒加载 报错....................................No Session</span></div> <div id="magicdomid25" class="ace-line gutter-author-p-97562 emptyGutter" data-author-initials="ﻬ" data-author-name="ﻬc m d" data-author-link=""><span class="author-p-97562">解决方法:新建类 配置OpenEntityManagerInViewFilter 以及 上面角色类(表)和用户类(表)(Role、User)Role的红色字体也是必须的,及@ManyToMany(fetch=FetchType.EAGER)</span></div> <div class="ace-line gutter-author-p-97562 emptyGutter" data-author-initials="ﻬ" data-author-name="ﻬc m d" data-author-link=""><span class="author-p-97562">由于博主基础的局限还不知道具体的原因是什么,但是解决了就好。</span></div> <div class="ace-line gutter-author-p-97562 emptyGutter" data-author-initials="ﻬ" data-author-name="ﻬc m d" data-author-link=""> <div class="cnblogs\_code"><div class="cnblogs\_code\_toolbar"><span class="cnblogs\_code\_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src="https://my.oschina.net//common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></span></div> <pre><span style="color: #000000">@Configuration </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span><span style="color: #000000"> HibernateConfig {</br> @Bean</br> </span><span style="color: #0000ff">public</span><span style="color: #000000"> FilterRegistrationBean registerOpenEntityManagerInViewFilterBean() {</br> FilterRegistrationBean registrationBean </span>= <span style="color: #0000ff">new</span><span style="color: #000000"> FilterRegistrationBean();</br> OpenEntityManagerInViewFilter filter </span>= <span style="color: #0000ff">new</span><span style="color: #000000"> OpenEntityManagerInViewFilter();</br> registrationBean.setFilter(filter);</br> registrationBean.setOrder(</span>5<span style="color: #000000">);</br> </span><span style="color: #0000ff">return</span><span style="color: #000000"> registrationBean;</br> }</br> }</span></pre> <div class="cnblogs\_code\_toolbar"><span class="cnblogs\_code\_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src="https://my.oschina.net//common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></span></div></div> <p>参考文章:</p> <p><a href="http://stackoverflow.com/questions/33622222/spring-boot-opensessioninviewfilter-with-actuator-and-custom-security" target="\_blank">http://stackoverflow.com/questions/33622222/spring-boot-opensessioninviewfilter-with-actuator-and-custom-security</a> </p> <p><a href="http://www.jianshu.com/p/a827ecdda99f" target="\_blank"><span class="author-p-97562">http://www.jianshu.com/p/a827ecdda99f</span></a></p> <p><span class="author-p-97562">http://www.w\_2bc.com/article/201653 /\*这个链接博客园不让我发啊,把w\_2\_b\_c中的下划线删了即可\*/</span></p> <p><span style="color: #ff6600">错误二</span>:这个在前面也提到过了,返回json数据出现<span style="color: #ff0000">Could not write JSON document: Infinite recursion</span>(无法编写JSON文档:无限递归 );</p> <p>在后面的使用中发现这个错误也是这样解决的,<span style="color: #ff0000">java.lang.IllegalStateException: Cannot call sendError() after the response has been committed</span>,错误页面到最后就是这样,如图:</p> <p><img src="https://images2015.cnblogs.com/blog/945531/201705/945531-20170526210711466-1708566335.png" alt=""></p> <p> </p> <p>解决方法:</p> <div id="magicdomid51" class="ace-line gutter-author-p-1423966 emptyGutter"><span class="author-p-1423966 color:rgb(51, 51, 51) font-family:Arial font-size:18px"> 在controller返回数据到统一json转换的时候,出现了json infinite recursion stackoverflowerror的错误,即json在将对象转换为json格式的数据的时候,出现了无限递归调用的情况。</span></div> <div id="magicdomid52" class="ace-line gutter-author-p-1423966 emptyGutter"><span class="author-p-1423966 color:rgb(51, 51, 51) font-family:Arial font-size:18px">具体的情况如下:</span></div> <div id="magicdomid53" class="ace-line gutter-author-p-1423966 emptyGutter"><span class="author-p-1423966"> <span class="author-p-1423966 color:rgb(51, 51, 51) font-family:Arial font-size:18px">A类中,有个属性:List<B> b, A与B的关系为 OneToMany;在B类中,有属性A a,引用到A中的字段id,并作为外键。hibernate查询结果正常,可以看到返回的A对象中,有b参数值,但在json转换的时候就出现了无限递归的情况。个人分析,应该是json在序列化A中的b属性的时候,找到了B类,然后序列化B类,而B类中有a属性,因此,为了序列化a属性,json又得去序列化A类,如此递归反复,造成该问题。</span></span></div> <div id="magicdomid54" class="ace-line gutter-author-p-1423966 emptyGutter"><span class="author-p-1423966 color:rgb(51, 51, 51) font-family:Arial font-size:18px">解决:</span></div> <div id="magicdomid55" class="ace-line gutter-author-p-1423966 emptyGutter"><span class="author-p-1423966"> <span class="author-p-1423966 color:rgb(51, 51, 51) font-family:Arial font-size:18px">在B类中a的getter setter方法上加注解@JsonBackReference,其实自己试过只在getter方法上加@JsonBackReference也够了。</span></span></div> <div class="ace-line gutter-author-p-1423966 emptyGutter"><span class="author-p-1423966"><span class="author-p-1423966 color:rgb(51, 51, 51) font-family:Arial font-size:18px">参考文章:<span class="author-p-1423966"> <a target="\_blank"><span class="author-p-1423966">http://blog.csdn.net/ludengji/article/details/11584281</span></a></span></span></span></div> <div class="ace-line gutter-author-p-1423966 emptyGutter"> </div> <div id="magicdomid41" class="ace-line gutter-author-p-97562 emptyGutter" data-author-initials="ﻬ" data-author-name="ﻬc m d" data-author-link=""> </div> </div></div><div id="MySignature"></div> <div class="clear"></div> <div id="blog\_post\_info\_block"> <div id="BlogPostCategory">分类: <a href="http://www.cnblogs.com/hyyq/category/1006206.html" target="\_blank">shiro</a>,<a href="http://www.cnblogs.com/hyyq/category/988585.html" target="\_blank">SpringBoot</a>,<a href="http://www.cnblogs.com/hyyq/category/1019781.html" target="\_blank">Hibernate</a></div> <div id="EntryTag"></div> <div id="blog\_post\_info"><div id="green\_channel"> <a href="javascript:void(0);" id="green\_channel\_digg" onclick="DiggIt(6886004,cb\_blogId,1);green\_channel\_success(this,'谢谢推荐!');">好文要顶</a> <a id="green\_channel\_follow" onclick="follow('a4c6fcaf-b80b-e611-9fc1-ac853d9f53cc');" href="javascript:void(0);">关注我</a> <a id="green\_channel\_favorite" onclick="AddToWz(cb\_entryId);return false;" href="javascript:void(0);">收藏该文</a> <a id="green\_channel\_weibo" href="javascript:void(0);" title="分享至新浪微博" onclick="ShareToTsina()"><img src="https://my.oschina.net//common.cnblogs.com/images/icon\_weibo\_24.png" alt=""></a> <a id="green\_channel\_wechat" href="javascript:void(0);" title="分享至微信" onclick="shareOnWechat()"><img src="https://my.oschina.net//common.cnblogs.com/images/wechat.png" alt=""></a> </div> <div id="author\_profile"> <div id="author\_profile\_info" class="author\_profile\_info"> <a href="http://home.cnblogs.com/u/hyyq/" target="\_blank"><img src="https://my.oschina.net//pic.cnblogs.com/face/945531/20160426221311.png" class="author\_avatar" alt=""></a> <div id="author\_profile\_detail" class="author\_profile\_info"> <a href="http://home.cnblogs.com/u/hyyq/">敲代码的小松鼠</a><br> <a href="http://home.cnblogs.com/u/hyyq/followees">关注 - 11</a><br> <a href="http://home.cnblogs.com/u/hyyq/followers">粉丝 - 11</a> </div> </div> <div class="clear"></div> <div id="author\_profile\_honor"></div> <div id="author\_profile\_follow"> <a href="javascript:void(0);" onclick="follow('a4c6fcaf-b80b-e611-9fc1-ac853d9f53cc');return false;">+加关注</a> </div> </div> <div id="div\_digg"> <div class="diggit" onclick="votePost(6886004,'Digg')"> <span class="diggnum" id="digg\_count">3</span> </div> <div class="buryit" onclick="votePost(6886004,'Bury')"> <span class="burynum" id="bury\_count">0</span> </div> <div class="clear"></div> <div class="diggword" id="digg\_tips"> </div> </div> <script type="text/javascript"> currentDiggType = 0; </script></div> <div class="clear"></div> </div> 原文地址:https://www.cnblogs.com/hyyq/p/6886004.html </div>