一、spring中的异常处理
1、在异常发生的controller中来处理
(1)步骤:
1)在controller中定义一个处理异常的方法,注意方法的返回值为ModelAndView;
2)方法接收一个Exception类型的参数:该对象最终为异常对象;
3)在该方法中完成异常发生时的业务逻辑;
4)在该方法中添加注解:@ExceptionHandler,在注解的value值中声明要处理的异常类型(类的类对象)。
(2)缺点
1)系统中可能产生的异常多种多样,如果都需要捕获,则需在controller层设置多个异常处理器;
2)针对每个controller下的请求发生异常都需要通过@ExceptinHandler处理,会有冗余代码产生;
(3)解决办法
2、全局异常处理器
步骤:
(1)定义一个全局异常处理器的类,该类处理各种异常;
(2)在定义的这个类上添加@ControllerAdvice注解;
(3)在这个类中定义不同的方法,提供不同的异常处理业务逻辑;
1)处理异常的方法的返回值为ModelAndView;
2)在方法上添加注解:@ExceptionHandler({异常的类的类对象});
(4)在springmvc的配置文件中配置全局一场处理器的包扫描
扫描ControllerAdvice类。
二、权限管理
1、权限管理理论概念
(1)权限管理的概念
控制一个用户对于所访问的资源是否有对应的权限;根据安全策略来约束用户只能访问被授权的资源。
(2)权限的粒度划分
粗颗粒度:类型资源,通常对应表的操作,通常从系统架构层面进行处理;
细颗粒度:实力资源,通常御用记录的操作,通常在业务逻辑中进行处理;
(3)权限管理的组成
(1)认证:判断用户身份是否合法;
(2)授权:判断用于对于请求的资源是否有相应的权限。
(4)两种授权方式
1)基于角色授权
根据角色的不同,分配不同的访问权限;
比如:董事长和总经理是不同的角色,给予分配不同的权限;
2)基于资源授权
基于每个账户分配资源;
比如:有增加、删除、修改、查询4个资源,对于每个人分配不同的资源;
3、授权的实现
4、授权的思路
授权一定是在认证通过的基础之上;
在拦截器的preHandler方法中执行。
思路:在用户登陆成功之后,应该将当前用户信息存进session作用域;其次,还应该在数据库中查询该用户对应的资源权限,存进session作用域,在preHandler方法中取到当前请求的url路径,与session作用域中的资源权限进行比对,确认是否具有权限。
5、权限管理相关表格
(1)user表
(2)用户_角色中间表
(3)角色表
id、name(角色的名字)、type(角色的类型);
存在意义:角色是为了针对某一类用户进行批量的授权,真正在业务中还是基于资源进行授权;
(4)角色_资源中间表
(5)资源表
记录了项目中所有的资源路径;
id;
name:描述该资源所做的事情;
module id:描述该资源所属的模块,外键;
url:对应的资源的业务方法上的requestMapping注解中的value值;
type:表名是菜单资源还是按钮资源,方便动态加载菜单。
三、拦截器权限管理
1、自定义拦截器
(1)判断用户是否登陆
从session中取当前登陆的用户activeUser;
activeUser=null:没有登陆à请求转发到登陆页面,return false;
activeUser
!=null:已登陆à放行,return true;
(2)用户已登录,判断当前请求是否具有权限
1)获取当前请求的资源
String
servletPath = request.getServletPath():获取到根目录后,参数前的url,
例如:/course/deleteCourse;
2)从session中获取已查询到的当前用户资源权限集合List
3)比对当前用户是否有本次请求的权限
permissions.contains(servletPath);
有权限:放行,return true;
没有权限:请求转发到没有权限的地址,return false;
2、将拦截器配置到springmvc的配置文件
3、联通测试
四、自定义注解权限管理
1、自定义添加权限管理的注解RequirePermission
(1)作用位置target:方法上;
(2)作用有效期retention:运行期间RunTime;
(3)属性:String value();
2、在handler方法上添加自定义的注解
注解的value值为权限码,比如:course:deleteCourse;
3、自定义拦截器
在拦截器的preHandler()方法中拦截请求,进行判断是否有权限;
(1)判断用户是否登陆
从session中取当前登陆的用户activeUser;
activeUser=null:没有登陆à请求转发到登陆页面,return false;
activeUser
!=null:已登陆à放行,return true;
(2)用户已登录,判断当前请求是否具有权限
1)判断当前请求的handler是否为HandlerMethod
handler instanceof
HandlerMethod
不是:表示是静态资源,放行,return true;
2)当前请求的handler为HandlerMethod
①将handler向下转型为HandlerMethod handlerMethod;
②获取当前请求的方法
Method
currentMethod = handlerMethod.getMethod();
③查看当前方法上是否有自定义的注解
currentMethod.isAnnotationPresent(自定义注解类的类对象);
没有:表示不需要权限即可访问,直接放行,return true;
有:表示需要权限才能访问;
④有注解时,判断当前用户是否有权限
a.获取该方法上添加的自定义注解requirePermission:
currentMethod.getAnnotation(自定义注解的类的类对象);
b.获取注解的value值,即是需要的权限码permissionCode:
requirePermission.value();
c.从session中获取从数据库查询到的当前用户的权限码集合;
3)比对当前用户是否有本次请求的权限
permissions.contains(servletPath);
有权限:放行,return true;
没有权限:请求转发到没有权限的地址,return false;
4、联通测试
五、mybatis-generator逆向生成
mybatis-generator逆向生成可以将数据库的表,逆向生成对应的Java bean,mapper接口和sqlMapper.xml映射文件。这些自动生成的文件中定义了最基础的应用。
1、导入jar包
2、配置generator的配置文件
generator配置文件配置了数据库表格到Java中的一些配置:
(1)数据库表映射的Java bean
存放的位置及字段对应的属性名;
(2)数据库表格对应的mapper接口;
(3)数据库表格对应的sqlmapper.xml映射文件;
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<!-- classpathentry 导入jar 因为已经手动导入jar包了, 这里就不要了 -->
<context id="DB2Tables" targetRuntime="MyBatis3">
<!-- 指定如何连接数据库 : 配置数据源信息 -->
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/shiro?allowMultiQueries=true"
userId="root"
password="root">
</jdbcConnection>
<!-- java类型解析器 使用默认的就可以 -->
<javaTypeResolver >
<property name="forceBigDecimals" value="false" />
</javaTypeResolver>
<!-- 指定 生成的java bean 所在的工程 及包路径 -->
<javaModelGenerator targetPackage="com.chen.model" targetProject=".\src">
<property name="enableSubPackages" value="true" />
<property name="trimStrings" value="true" />
</javaModelGenerator>
<!-- 指定sql映射文件生成在哪里 -->
<sqlMapGenerator targetPackage="mapper" targetProject=".\config">
<property name="enableSubPackages" value="true" />
</sqlMapGenerator>
<!-- 指定mapper接口生成在哪里 -->
<javaClientGenerator type="XMLMAPPER" targetPackage="com.chen.mapper" targetProject=".\src">
<property name="enableSubPackages" value="true" />
</javaClientGenerator>
<!-- 指定要为哪些表生成数据 同时指定 类名 -->
<table tableName="sys_module" domainObjectName="SysModule" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>
<table tableName="sys_acl" domainObjectName="SysAcl" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>
<table tableName="sys_role" domainObjectName="SysRole" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>
<table tableName="sys_user" domainObjectName="SysUser" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>
</context>
</generatorConfiguration>
注意:文件中只自动生成了一些基础的配置,自己业务相关的代码需自己定义。
3、新建测试类,加载配置文件,逆向生成
public static void main(String[] args) throws Exception {
List<String> warnings = new ArrayList<String>();
boolean overwrite = true;
File configFile = new File("generator.xml");
ConfigurationParser cp = new ConfigurationParser(warnings);
Configuration config = cp.parseConfiguration(configFile);
DefaultShellCallback callback = new DefaultShellCallback(overwrite);
MyBatisGenerator myBatisGenerator =new MyBatisGenerator(config, callback, warnings);
myBatisGenerator.generate(null);
}