You are on page 1of 16

1.

    .A 表中有 a,b,c 三个字段,B 表中有 a,b,c 三个字段,把 A 表数据复制到 B 表


.insert into B (id,a,b,c)
select id,a,b,c from A

2.线程和进程的区别:进程就是一个可执行程序,一个线程可以有多个线程

3.接口和抽象类的区别
抽象类:可有又构造方法,可以有普通成员方法,方法可以是抽象的或者非抽象的,方法的访问类型可以是
public 和 protected,可以包含静态方法,成员变量可以使用任意变量,一个类只能继承一个抽象类,可以实
现代码重用
接口:不能有构造方法,没有普通成员方法,方法必须是抽象的,不能包含静态方法,成员变量必须 final 修饰,
一个类可以实现多个接口。

4      库存什么时候减的:用户将商品加入购物车并付款以后。
5. 分布式用的什么,dubbo 用什么实现的,对 dubbo 了解吗:
a)Dubbo,Redis
b)服务容器负责启动,加载,运行服务提供者
服务提供者在启动时,想注册中心注册自己提供的服务
服务消费者在启动时,向注册中心订阅自己所需的服务
注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费
者。
服务消费者,从消费者地址列表中,基于负载均衡算法,西安一台提供者进行调用,如果调用失败,再
选一台调用
服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
6.     服务器用了几台:13 台
7.  后台页面能自己写吗,easyUi 常用控件,常用方法:
a)Form 表单控件,layout 布局控件,gird 控件
b)Datagrid 动态列,访问 url 获取数据,弹出模态框,数据表格
    前台页面都是 jsp 吗
首页用的 html
8. Jsp 的核心及核心标签
a)Servlet
b)Core       XML Database       Funcations
9.Servlet 生命周期
a)初始化阶段  调用 init()方法
b)响应客户请求阶段  调用 service()方法
c)终止阶段  调用 destroy()方法
8.      Redis 什么情况下使用,redis 持久化方案
a)处理大数据量的时候
b)Redis 的所有数据都是保存在内存中,
Rdb:快照形式,定期把内存中当前时刻的数据保存到磁盘,redis 默认支持的持久化方案
aof 形式:append only file。把所有对 redis 数据库操作的命令,增删改操作命令,保存到文件中,
数据库恢复是把所有命令执行一遍即可。
10.SpringMVC 和 Struts2 有区别
a)Struts2 是类级别拦截器,一个类对应一个 request 上下文;
SpringMVC 是方法级别的拦截,一个方法对应一个 request 上下文。
b)Struts2 需要对每个 request 进行封装,比较消耗内存
c)拦截器实现机制上,Struts2 有自己的 interceptor 机制,springMVC 用的是独立的 aop 方式
d)SpringMVC 的入口是 servlet,而 Struts2 的入口是 filter
e)SpringMVC 集成了 Ajax 使用非常方便,只需要注解@ResponseBody 就可以实现
f)SpringMVC 和 Spring 是无缝的,从项目管理和安全性上比 Struts2 高
g)Spring 开发效率和性能高于 Struts
11. Hibernate 和 Mybatis 的区别和优劣
a)Sql 优化方面:hibernate 的查询会将表中所有的字段查询出来,这一点会有性能的消耗
Mybatis 的 sql 是手动编写的,所以可以按需求指定查询的字段,sql 会更灵活,可控性更好
b)Hibernate 是在 JDBC 上进行了一次封装
Mybatis 是基于原生的 JDBC,运行速度有优势
c)Mybatis mapper xml 支持动态 sql;Hibernate 不支持
d)Hibernate 与具体数据库的关联只需在 xml 文件中配置即可,所有 hql 语句与具体的数据库无关,移植性好
Mybatis 项目所有的 sql 语句都是依赖所用的数据库的,所以不同数据库类型的支持不好
12.Hibernate 映射关系      
a)单向一对一关联映射
b)单向一对多关联映射
c)单向多对一关联映射
d)单向多对多关联映射
13.Spring 的理解,如何依赖注入
a)Spring 是一个轻量级的控制反转和面向切面的容器框架
b)Spring 使得对象管理集中化和简单化
c)依赖注入类型:setter 注入和构造方法注入
setter injection 对象被创建后将被依赖对象通过 set 方法设置进去
constructor injection 对象创建时被依赖对象以构造方法参数的方式注入
d)Spring 核心功能:
BeanFactory:产生一个新的实例,可以实现单例模式,是核心容器的主要组件,是工厂模式的
实现。
BeanWraper:提供统一的 get 及 set 方法
ApplicationContext:提供框架的实现,包括 BeanFactory 的所有功能
14.面试思想

OOA 是面向对象的分析 Analysis
OOD 是面向对象的设计 Design
OOP 是面向对象的编程 Programming
都是相辅相成的: 分析是为了设计,设计是为了编程。
都属于软件工程的不同课题

15
 
16.Dubbo 协议:采用 NIO 复用单一长连接,并使用线程池并发处理请求,减少握手和加大并发效率,在大文件传
输时,单一连接会成为瓶颈
 
为表设置索引要付出代价的:一是增加了数据库的存储空间,二是在插入和修改数据时要花费较多的时间(因为索
引也要随之变动)
 
Dubbo 缺省协议采用单一长连接和 NIO 异步通讯,适合于小数据量大并发的服务调用,以及服务消费者机器数远大
于服务提供者机器数的情况。
索引是对数据库表中一个或多个列(例如,employee 表的姓名 (name) 列)的值进行排序的结构。如果想按特定
职员的姓来查找他或她,则与在表中搜索所有的行相比,索引有助于更快地获取信息。

例如这样一个查询:select * from table1 where id=10000。如果没有索引,必须遍历整个表,直到 ID 等于 10000
的这一行被找到为止;有了索引之后(必须是在 ID 这一列上建立的索引),即可在索引中查找。由于索引是经过某
种算法优化过的,因而查找次数要少的多。可见,索引是用来定位的。

相当于对指定的列生成目录啊,可以加快查找速度,对读多写少的列,可以添加索引
RPC(Remote Procedure Call)是一种远程调用协议,简单地说就是能使应用像调用本地方法一样的调用远程的过
程或服务,可以应用在分布式服务、分布式计算、远程服务调用等许多场景。说起 RPC 大家并不陌生,业界有很
多开源的优秀 RPC 框架,例如 Dubbo、Thrift、gRPC、Hprose 等等。
 
17 
 
上面是直坨数字阵型
18.
19.
20.SQL 语句优化策略
阅读( )暂无评论时间:2014-03-10 18:06:32
总体来说,SQL 语句优化策略有以下几个方面:

● 创建表的时候。应尽量建立主键,根据主键查询数据;
● 大数据表删除,用 truncate table 代替 delete。
● 合理使用索引,在 OLTP 应用中一张表的索引不要太多。组合索引的列顺序尽量与查询条件列顺序保持一致;对
于数据操作频繁的表,索引需要定期重建,以减少失效的索引和碎片。
● 查询尽量用确定的列名,少用*号。

尽量少嵌套子查询,这种查询会消耗大量的 CPU 资源;对于有比较多


or 运算的查询,建议分成多个查询,用 union all 联结起来;多表查询
的查询语句中,选择最有效率的表名顺序(基于规则的优化器中有效)。Oracle 解析器对表解析从右到左,所以记
录少的表放在右边。

● 尽量多用 commit 语句提交事务,可以及时释放资源、解


锁、释放日志空间、减少管理花费;在频繁的、性能要求比较高的
数据操作中,尽量避免远程访问,如数据库链等,访问频繁的表可
以常驻内存:alter table...cache;
详细分来:
1)、尽量少用 IN 操作符,基本上所有的 IN 操作符都可以用 EXISTS 代替。 
2)、不用 NOT IN 操作符,可以用 NOT EXISTS 或者外连接+(外连接+判断为空)替代。
3)、不用“<>”或者“!=”操作符。对不等于操作符的处理会造成全表扫描,可以用“<” or “>”代替。例如:
a<>0 改为 a>0 or a<0,a<>’ ’ 改为 a>’ ’ 
4)、Where 子句中出现 IS NULL 或者 IS NOT NULL 时,Oracle 会停止使用索引而执行全表扫描。可以考虑在设计表
时,对索引列设置为 NOT NULL。这样就可以用其他操作来取代判断 NULL 的操作。 
5)、当通配符“%”或者“_”作为查询字符串的第一个字符时,索引不会被使用,因此一般不要作为第一个字符
出现。 
6)、对于有连接的列“||”,最后一个连接列索引会无效。尽量避免连接,可以分开连接或者使用不作用在列上
的函数替代。 
7)、如果索引不是基于函数的,那么当在 Where 子句中对索引列使用函数时,索引不再起作用。 
8)、Where 子句中避免在索引列上使用计算,否则将导致索引失效而进行全表扫描。 
9)、对数据类型不同的列进行比较时,会使索引失效。 
10)、用“>=”替代“>”。 
11)、UNION 操作符会对结果进行筛选,消除重复,数据量大的情况下可能会引起磁盘排序。如果不需要删除重复
记录,应该使用 UNION ALL。 
12)、Oracle 从下到上处理 Where 子句中多个查询条件,所以表连接语句应写在其他 Where 条件前,可以过滤掉最
大数量记录的条件必须写在 Where 子句的末尾。 
13)、Oracle 从右到左处理 From 子句中的表名,所以在 From 子句中包含多个表的情况下,将记录最少的表放在最
后。 
14)、Order By 语句中的非索引列会降低性能,可以通过添加索引的方式处理。严格控制在 Order By 语句中使用表
达式。 
15)、不同区域出现的相同的 Sql 语句,要保证查询字符完全相同,以利用 SGA 共享池,防止相同的 Sql 语句被多
次分析。 
16)、多利用内部函数提高 Sql 效率。 
17)、当在 Sql 语句中连接多个表时,使用表的别名,并将之作为每列的前缀。这样可以减少解析时间。 
18)、根据 SQL 不同设定优化模式的方式,选择不同的优化策略,通过 SELECT /*+ALL+_ROWS*/ ……;来设定。可用
的 HINT 包括/*+ALL_ROWS*/、/*+FIRST_ROWS*/、/*+CHOOSE*/、/*+RULE*/ 等一般在 SQL 前加 first_rows 策略,
速度都会提高,特殊情况下改用 choose 策略。(本策略架构包已经支持) 
19)、对于大表查询中的列应尽量避免进行诸如To_char,to_date,to_number等转换 
20)、有索引的尽量用索引,有用到索引的条件写在前面 
21)、如有可能和有必要就建立一些索引 
22)、尽量避免进行全表扫描,限制条件尽可能多,以便更快搜索到要查询的数据 

21.请求转发和重定向的区别?
forword -- 请求转发 : 
1、服务器端跳转,地址栏不改变 
2、执行到跳转语句后马上无条件跳转,之后的代码不再执行(跳转之前一定要释放全部资源)
3、request 设置的属性在跳转后的页面仍可以使用
4、使用<jsp:param name="参数名" value="参数值" />传递参数
 redirct-- 重定向:
1、客户端跳转,地址栏改变 
2、所有代码执行完毕后跳转
3、跳转后的页面不能使用上一个页面的 request 属性
4、使用地址重写传递参数(response.sendRedirect("URL?参数名=参数值"))

22.String,StringBuffer、StringBuilder 的区别?
答: String 是一个特殊的引用数据类型,是一个长度不可变的字符序列,没有缓冲区,一旦创建就不会发生变化
了。即使重新赋值不是在原来对象的基础上改变的,而是创建了一个新的对象,将引用指向这个新的对象,浪费
空间,效率比较低。
StringBuffer、StringBuilder 是容器,是可变的字符串序列,存放于堆内存。
StringBuffer 是 JDK1.0 版本的,线程是安全的,效率比较低。StringBuilder 是 JDK1.5 出现的,线程不安全,效
率高。 

23.   Hashtable 和 HashMap 的区别?

    Hashtable 的底层数据结构是哈希表,不可以存储 null 键和 null 值,线程同步,效率低。JDK1.0.


    HashMap 的底层数据结构是哈希表,可以存储 null 键和 null 值,线程不同步,将 Hashtable 替代,JDK1.2 效率
高。保证键的唯一性的 依据是 hashCode 和 equals 方法。

24.事务就是访问可能更新数据库各种数据项的一个可执行单元
25.Struts2 中访问多个 Action 怎么办?
通过配置 method 属性,通配符,或者动态访问

26.struts 中不存在线程安全问题,因为它是一个实例,数据封装有模型驱动,方法封装,属性驱动,Ognl 表达式

27. zookeeper 端口号为:2181   SVN 端口号:3690    


    Mysql 端口号:3306  oracle 端口号:1521 ActiveMQ:61616  Redis 端号口:6379

28. Webservice 好处:


相当于一个借口,实现跨平台跨源交互,底层是 SOAP 协议.是基于服务器与服务器之间的.有三种维护规范
是阿帕奇下的 cxf 框架实现的
29.什么时候进行序列化?

序列化是一种用来处理对象流的机制
,所谓对象流就是将对象的内容进行流化。可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络
之间。序列化是为了解决在对对象流进行读写操作时所引发的问题。

序列化的实现:将需要被序列化的类实现 Serializable 接口,该接口没有需要实现的方法,implements


Serializable 只是为了标注该对象是可被序列化的,然后使用一个输出流(如:FileOutputStream)来构造一个
ObjectOutputStream(对象流)对象,接着,使用 ObjectOutputStream 对象的 writeObject(Object obj)方法就可
以将参数为 obj 的对象写出(即保存其状态),要恢复的话则用输入流;

什么时候使用序列化:

一:对象序列化可以实现分布式对象。主要应用例如:RMI 要利用对象序列化运行远程主机上的服务,就像在本地
机上运行对象时一样。

二:java 对象序列化不仅保留一个对象的数据,而且递归保存对象引用的每个对象的数据。可以将整个对象层次
写入字节流中,可以保存在文件中或在网络连接上传递。利用对象序列化可以进行对象的"深复制",即复制对象
本身及引用的对象本身。序列化一个对象可能得到整个对象序列。

30.浅谈 Shiro 框架
1.Spring security 与 apache shiro 差别:
shiro 配置更加容易理解,容易上手;security 配置相对比较难懂。
在 spring 的环境下,security 整合性更好。Shiro 对很多其他的框架兼容性更好,号称是无缝集成。
shiro 不仅仅可以使用在 web 中,它可以工作在任何应用环境中。
在集群会话时 Shiro 最重要的一个好处或许就是它的会话是独立于容器的。
Shiro 提供的密码加密使用起来非常方便。
 
2.控制精度:
Shiro 也支持注解方式。
注解方式控制权限只能是在方法上控制,无法控制类级别访问。

过滤器方式控制是根据访问的 URL 进行控制。允许使用*匹配 URL,所以可以进行粗粒度,也可以进行细粒度控制。

URL 权限过滤
shiro 安全框架:
+ehcache 缓存

1)、引入依赖 pom.xml

<!-- Apache Shiro 权限架构 -->


<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-all</artifactId>
<version>1.2.3</version>
</dependency>

2)、核心 filter,一个 filter 相当于 10 个 filter;web.xml

注意:shiro 的 filter 必须在 struts2 的 filter 之前,否则 action 无法创建

    <!-- Shiro Security filter  filter-name 这个名字的值将来还会在 spring 中用到  -->


    <filter>
        <filter-name>shiroFilter</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
        <init-param>
            <param-name>targetFilterLifecycle</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>shiroFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

3)、在 spring applicationContext.xml 中记载 shiro 配置文件,放在事务管理器之前配置


<aop:aspectj-autoproxy proxy-target-class="true" />

同时添加专门配置 shiro 的配置文件


<import resource="spring/applicationContext-shiro.xml"/>
和 ehcache 支持 ehcache-shiro.xml

<ehcache updateCheck="false" name="shiroCache">

    <defaultCache
            maxElementsInMemory="10000"
            eternal="false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            overflowToDisk="false"
            diskPersistent="false"
            diskExpiryThreadIntervalSeconds="120"
            />
</ehcache>

4)、applicationContext-shiro.xml,配置校验的策略,哪些校验,哪些放行

<?xml version="1.0" encoding="UTF-8"?>


<beans xmlns="http://www.springframework.org/schema/beans"  
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"       
xmlns:p="http://www.springframework.org/schema/p"  
xmlns:context="http://www.springframework.org/schema/context"   
xmlns:tx="http://www.springframework.org/schema/tx"  
xmlns:aop="http://www.springframework.org/schema/aop"  
xsi:schemaLocation="http://www.springframework.org/schema/beans    
http://www.springframework.org/schema/beans/spring-beans.xsd    
http://www.springframework.org/schema/aop    
http://www.springframework.org/schema/aop/spring-aop.xsd    
http://www.springframework.org/schema/tx    
http://www.springframework.org/schema/tx/spring-tx.xsd    
http://www.springframework.org/schema/context    
http://www.springframework.org/schema/context/spring-context.xsd">

<description>Shiro 的配置</description>

<!-- SecurityManager 配置 -->


<!-- 配置 Realm 域 -->
<!-- 密码比较器 -->
<!-- 代理如何生成? 用工厂来生成 Shiro 的相关过滤器-->
<!-- 配置缓存:ehcache 缓存 -->
<!-- 安全管理 -->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <!-- Single realm app.  If you have multiple realms, use the 'realms' property instead. -->
        <property name="realm" ref="authRealm"/><!-- 引用自定义的 realm -->
        <!-- 缓存 -->
        <property name="cacheManager" ref="shiroEhcacheManager"/>
    </bean>
    <!-- 自定义权限认证 -->
    <bean id="authRealm" class="cn.itcast.jk.shiro.AuthRealm">
<property name="userService" ref="userService"/>
<!-- 自定义密码加密算法  -->
<property name="credentialsMatcher" ref="passwordMatcher"/>
</bean>

<!-- 设置密码加密策略 md5hash -->


<bean id="passwordMatcher" class="cn.itcast.jk.shiro.CustomCredentialsMatcher"/>

    <!-- filter-name 这个名字的值来自于 web.xml 中 filter 的名字 -->


    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <property name="securityManager" ref="securityManager"/>
        <!--登录页面  -->
        <property name="loginUrl" value="/index.jsp"></property>
        <!-- 登录成功后 -->      
        <property name="successUrl" value="/home.action"></property>
        <property name="filterChainDefinitions">
            <!-- /**代表下面的多级目录也过滤 -->
            <value>
/index.jsp* = anon
/home* = anon
/sysadmin/login/login.jsp* = anon
/sysadmin/login/logout.jsp* = anon
/login* = anon
/logout* = anon
/components/** = anon
/css/** = anon
/images/** = anon
/js/** = anon
/make/** = anon
/skin/** = anon
/stat/** = anon
/ufiles/** = anon
/validator/** = anon
/resource/** = anon
/** = authc
/*.* = authc
            </value>
        </property>
    </bean>

    <!-- 用户授权/认证信息 Cache, 采用 EhCache  缓存 -->


    <bean id="shiroEhcacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
        <property name="cacheManagerConfigFile" value="classpath:ehcache-shiro.xml"/>
    </bean>

    <!-- 保证实现了 Shiro 内部 lifecycle 函数的 bean 执行 -->


    <bean id="lifecycleBeanPostProcessor"
class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>

    <!-- 生成代理,通过代理进行控制 -->


    <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
          depends-on="lifecycleBeanPostProcessor">
        <property name="proxyTargetClass" value="true"/>
    </bean>
    
    <!-- 安全管理器 -->
    <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
        <property name="securityManager" ref="securityManager"/>
    </bean>

</beans>

5)、自定义 realm AuthRealm

在认证、授权内部实现机制中都有提到,最终处理都将交给 Realm 进行处理。


因为在 Shiro 中,最终是通过 Realm 来获取应用程序中的用户、角色及权限信息的。
通常情况下,在 Realm 中会直接从我们的数据源中获取 Shiro 需要的验证信息。可以说,Realm 是专用于安全框架
的 DAO.

public class AuthRealm extends AuthorizingRealm{


private UserService userService;
public void setUserService(UserService userService) {
this.userService = userService;
}

//授权
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
System.out.println("授权");
//获取当前用户
User user = (User)principals.fromRealm(getName()).iterator().next();
//得到权限字符串
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

Set<Role> roles = user.getRoles();


List<String> list = new ArrayList();
for(Role role :roles){
Set<Module> modules = role.getModules();
for(Module m:modules){
if(m.getCtype()==0){
//说明是主菜单
list.add(m.getCpermission());
}
}
}
info.addStringPermissions(list);
return info;
}
//认证  登录
protected AuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken token) throws AuthenticationException {
System.out.println("认证");
UsernamePasswordToken upToken = (UsernamePasswordToken)token;

User user = userService.findUserByName(upToken.getUsername());


if(user==null){
return null;
}else{
AuthenticationInfo info = new SimpleAuthenticationInfo(user, user.getPassword(),
getName());
return info;
}

}
6)、修改传统登录为 shiro 登录

package cn.itcast.jk.action;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.subject.Subject;

import cn.itcast.common.SysConstant;
import cn.itcast.jk.service.UserService;

/**
 * @Description: 登录和退出类
 * @Author: 靳磊
 * @Company: http://java.itcast.cn
 * @CreateDate: 2014 年 10 月 31 日
 */
public class LoginAction extends BaseAction {

private static final long serialVersionUID = 1L;

private String username;


private String password;

private UserService userService;


public void setUserService(UserService userService) {
this.userService = userService;
}

public String login() throws Exception {


/*
 * shiro 登录方式:根据用户名获取密码,密码为 null 非法用户;有密码检查是否用户填写的密码
 * 登录成功后无需往 httpsession 中存放当前用户,这样就跟 web 容器绑定,关联太紧密;它自己创建
 * subject 对象,实现自己的 session。这个跟 web 容器脱离,实现松耦合。
 */

//调用 shiro 判断当前用户是否是系统用户


Subject subject = SecurityUtils.getSubject(); //得到当前用户
//shiro 是将用户录入的登录名和密码(未加密)封装到 token 对象中
UsernamePasswordToken token = new UsernamePasswordToken(userName,password);

try{
subject.login(token); //自动调用 AuthRealm.doGetAuthenticationInfo

//写 seesion,保存当前 user 对象


User curUser = (User)subject.getPrincipal(); //从 shiro 中获取当前用户
System.out.println(curUser.getDept().getDeptName()); //让懒加载变成立即加载
Set<Role> roles = curUser.getRoles();
for(Role role :roles){
Set<Module> moduless =  role.getModules();
for(Module m :moduless)
   System.out.println(m.getName());
}
session.put(SysConstant.CURRENT_USER_INFO, curUser); //Principal 当前用户对象
}catch(Exception ex){
super.put("errorInfo","用户名密码错误,请重新填写!");
ex.printStackTrace();

return "login";
}
return SUCCESS;
}

public String logout(){


session.remove(SysConstant.CURRENT_USER_INFO); //删除 session
return "logout";
}

public String getUsername() {


return username;
}

public void setUsername(String username) {


this.username = username;
}
public String getPassword() {
return password;
}

public void setPassword(String password) {


this.password = password;
}

}
7)、授权(另一种加载数据的思想   可省略因为在登录时已加载)
根据用户查询出角色对应的权限,并返回权限串

-hql,service

public List<String> getPermission(String userName) {


List<String> _list = new ArrayList<String>();

//用户,角色,权限,两级多对多,使用 left join 关联实现


String hql = "select p from User as u left join u.roles as r left join r.modules as p where
u.username='"+userName+"'";
List<Module> moduleList = baseDao.find(hql, Module.class, null);

for(Module m : moduleList){
if(m!=null){ //观察 hibernate 实现的 SQL,会多出一条 Null 记录
_list.add(m.getName());
}
}

return _list;
}

在 realm 中进行授权 userService.getPermission

//授权
protected AuthorizationInfo doGetAuthorizationInfo(
PrincipalCollection principals) {
log.info("执行授权...");

//获取登录用户的权限,配合 jsp 页面中的 shiro 标签进行控制


User curUser = (User) principals.fromRealm(getName()).iterator().next();  
String userName = curUser.getUsername();
List<String> sList = userService.getPermission(userName );
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
for(String permission : sList){
//设置当前用户的权限
authorizationInfo.addStringPermission(permission);
}

return authorizationInfo;
}

8)、页面使用 shiro 标签,/home/title.jsp 主菜单

<%@ taglib uri="http://shiro.apache.org/tags" prefix="shiro"%>

     <shiro:hasPermission name="sysadmin">
     <span id="topmenu" onclick="toModule('sysadmin');">系统管理</span>
     </shiro:hasPermission>

You might also like