第三阶段第四,五周笔记及代码
2020/7/20–第一天—动吧用户添加修改设计-day17–tmooc17
数据类型的定义放到了common包中
用户编辑页面呈现以后,发起异步任务从服务端获取角色信息然后呈现在页面上通过findObject方法
上午完成管理模块的内容添加insdertObnject
在用户编辑页面加载完成以后,异步加载角色信息,并在页面上进行呈现
保存用户自身信息和用户角色关系数据saveObject
- 参数校验
- 保存用户信息
- 密码加密(本次算法采用md5加密)
- 保存用户信息
- 保存用户角色关系数据
说了些关于加密算法的函数,回头待补
消息摘要加密算法,特点
- 不可逆,但可以暴力破解
- 相同内容加密结果相同
import lombok.extern.slf4j.Slf4j;
下午讲aop设计思想
Aop主要在控制器和业务层中间,其他部分也有,但是少.主要为了实现扩展功能,但是是非核心业务
通过继承和组合来实现
▪ 切面(aspect): 横切面对象,一般为一个具体类对象(可以借助@Aspect声明)。
/**
* @Aspect 注解描述的类型为Spring AOP中的切面对象类型。此对象中可以封装:
* 1)切入点(定义在哪些目标对象的哪些方法上进行功能扩展)
* 2)通知(封装功能扩展的业务逻辑)
*/
▪ 通知(Advice):在切面的某个特定连接点上执行的动作(扩展功能),例如
around,before,after等。
▪ 连接点(joinpoint):程序执行过程中某个特定的点,一般指被拦截到的的方法。
▪ 切入点(pointcut):对多个连接点(Joinpoint)一种定义,一般可以理解为多个连接
点的集合。
Spring AOP底层基于代理机制实现功能扩展:
- 假如目标对象(被代理对象)实现接口,则底层可以采用JDK动态代理机制为
目标对象创建代理对象(目标类和代理类会实现共同接口)。 - 假如目标对象(被代理对象)没有实现接口,则底层可以采用CGLIB代理机制
为目标对象创建代理对象(默认创建的代理类会继承目标对象类型)。
结合代码补全
@Aspect
//注解用于标识或者描述AOP中的切面类型,基于切面类型构建的对象用于为目标对象进
//行功能扩展或控制目标对象的执行。
@Slf4j
@Component
public class SysLogAspect {
@Pointcut("bean(sysUserServiceImpl)")
/*注解用于描述切面中的方法,并定义切面中的切入点(基于特定表达 式的方式进行描述),
* 在本案例中切入点表达式用的是bean表达式,这个表达式
以bean开头,bean括号中的内容为一个spring管理的某个bean对象的名字。*/
public void doLogPointCut() {
//此方法中不需要写任何代码,只是为注解提供环境
}
@Around("logPointCut()")
/*注解用于描述切面中方法,这样的方法会被认为是一个环绕通知
* (核 心业务方法执行之前和之后要执行的一个动作),@Aournd注
* 解内部value属性的 值为一个切入点表达式或者是切入点表达式的
* 一个引用(这个引用为一个@PointCut注解描述的方法的方法名)。*/
public Object around(ProceedingJoinPoint jp)
throws Throwable{
try {
log.info("start:"+System.currentTimeMillis());
Object result=jp.proceed();//调用下一个切面方法或目标方法
log.info("after:"+System.currentTimeMillis());
return result;
}catch(Throwable e) {
log.error(e.getMessage());
throw e;
}
}
}
2020/7/21–第二天—Spring AOP编程增强-day18–tmooc18
接口MailService功能发邮件void send()
接口实现MailServiceImpl重载send创建MailServiceTests,创建MailServiceImpl的对象mailService利用对象.send方法
运行send(“老婆”)
想在send方法中添加其他内容,但是不能修改send方法,//直接修改方法内部代码实现功能实现功能拓展违背了OCP(开闭)原则
另写一个类LogMailServiceImpl继(extebnds)承MainServiceImpl重写方法并添加新语句//通过继承方式实现功能拓展,不违背ocp原则//但是MailServiceImpl这个类使用final修饰的时候就不行了,不能被继承
test中的方法创建对象的时候改用new LogMailServiceImpl来创建对象就可以扩展功能
可以将扩展功能提取到专门的对象当中(LogAspect)
切面通知应用增强 --18am
五种通知类型:
前置通知@Before
返回通知@AfterReturning
异常通知@AfterThrowing
后置通知@After
环绕通知@Around(格式)
@Around(value="doLogPointCut()")
public Object around(ProceedingJoinPoint jp)throws Throwable{
}
执行顺序Around>>Before>>TargetMethod>>Around>>After>>AfterReturning/AfterThrowing
编写了一个方式以及一个异常的
自定义注解:
简单cache的实现:SimpleCache
产品级cache要考虑(补代码上有)
切入点 表达式增强 --18pm
bean用于匹配指定bean对象的所有方法
bean("userServiceImpl")//指定一个userServiceImpl类中所有方法。
bean("*ServiceImpl")//指定所有后缀为ServiceImpl的类中所有方法。
within用于匹配指定包下所有类内的所有方法
execution用于按指定语法规则匹配到具体方法
@annotion用于匹配指定注解修饰的方法
切面 优先级设置实现
切面的优先级需要借助@Order注解进行描述,数字越小优先级越高
弄了两个吧一个日志的一个Cache的缓存切面
用户行为日志记录实现(实践)============代码
//假如使用lombok的注解@Slf4j描述类,默认会在类的内部生成如下语句
private static final Logger log =
LoggerFactory.getLogger(SysLogAspect.class);
将正常的行为写入到数据库中saveUserLog,和Aop相关的操作在上面的部分
采用@Around通知
SysLogDao—insertObject
xml—insertObject
SysLogSercice—void saveObject
SysLogServiceImpl>>
SysLogAspect>>@Autowired SysLogService sysLogService
ip值获取工具类放在com.cy.pj.common.util包中IPUtils.java
D:\STS_h阶段笔记文件\CGBIII-课前资料\CODES
@Retention//运行时有效
用户名做动态等登陆操作的时候在做,其他的动态实现已经完成了
2020/7/22–第三天—Spring AOP事务处理–day19----tmooc19
10:25开始说的事务,之前在回顾切面
Spring 中事务管理实现
@Transactional可以描述类和方法>>>>事务回滚,直接添加注解即可使用
read-only:指定事务是否为只读事务,默认值为 false;为了忽略那些不需要事
务的方法,比如读取数据,可以设置 read-only 为 true,
rollback-for:用于指定能够触发事务回滚的异常类型,如果有多个异常类型需
要指定,各类型之间可以通过逗号分隔。
timeout:事务的超时时间,默认值为-1,表示没有超时显示。如果配置了具体时
间,则超过该时间限制但事务还没有完成,则自动回滚事务。
故意设置延迟时间然后导致超时错误报异常
说了些底层的东西有点深>>容器启动的时候,工厂会创建一个对象>>>>>>>>>>>>>需要回看视频下午两点到三点的时间
Spring 中事务传播特性
借助debugg来进行了解
线程问题
分析:REQUIRED,逻辑关系有点乱,但是代码少
2020/7/24–第四天—Shiro安全框架简介 --day20----tmooc20
Spring 自定义异步池的实现
看回放拓展了挺多的,可以做笔记回顾一下!!!
ArrayBlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(2);//任务对列
ThreadFactory threadFactory=new ThreadFactory() {
AtomicLong al=new AtomicLong(1);
@Override
public Thread newThread(Runnable r) {
//设置线程名
String name="cgb2004-thread-"+al.getAndIncrement();
return new Thread(r,name);
}
};
ThreadPoolExecutor tExecutor=new ThreadPoolExecutor(
2,//corePoolSize, //核心线程数
3,//maximumPoolSize, //最大线程数
60,//keepAliveTime, //线程空闲多长时间被释放
TimeUnit.SECONDS,//unit, //时间 段位
workQueue//任务对列----------在上面
threadFactory,//threadFactory线程工厂-----------在上面
new CallerRunsPolicy()//拒绝执行任务的一种策略,CallerRunsPolicy表示由调用者线程去执行
);
//执行任务用submit或者execute
核心线程加上对列线程,再来的话核心线程就变成最大线程,超了就报错
Spring AOP中Cache操作实现
在次操作的时候不用去数据库而是在缓存中进行处理,
sysMenuServiceImpl中的findObjects
但是修改之后因为缓存中的数据还在使用需要下面的清除指定缓存数据
sysMenuServiceImpl中的updateObject
重难点分析
▪ AOP 是什么,解决了什么问题,实现原理,应用场景。
▪ AOP 编程基本步骤及实现过程(以基于AspectJ框架实现为例)。
▪ AOP 编程中的核心对象及应用关系。
▪ AOP 思想在Spring中的实现原理分析。组合继承
▪ AOP 编程中基于注解方式的配置实现。(@Aspect,@PointCut,@Around,…)
▪ AOP 编程中基于注解方式的事务控制。(@Transactional)
▪ AOP 编程中异步操作的实现?(@EnableAsync,@Async)
▪ AOP 编程中的缓存应用?(@EnableCaching,@Cacheable,@CacheEvict)
FAQ分析
▪ 什么是OCP原则(开闭原则)?
▪ 什么是DIP原则 (依赖倒置)?
▪ 什么是单一职责原则(SRP)?一个类的职责不要太多mvc,功能扩展,
▪ Spring 中AOP的有哪些配置方式?(XML,注解)
▪ Spring 中AOP 的通知有哪些基本类型?(5种)
▪ Spring 中AOP是如何为Bean对象创建代理对象的?(JDK,CGLIB)
▪ Spring 中AOP切面的执行顺序如何指定?(@Order)
▪ Spring 单体架构项目中事务的控制要通过Connection对象实现,?
▪ Spring 如何保证一个线程一个Connection对象?借助ThreadLocal实现.?
▪ 多个事务并发执行时可能会出现什么问题?(脏读,不可重复读,幻影读)
▪ 如何理解数据库中的的悲观锁和乐观锁? 我更新你只能等待,乐观锁就是可以一起
▪ 你了解事务的隔离级别吗?知道具体的应用场景吗?
A
Shiro框架认证拦截实现
Shiro官网Shiro 架构包含三个主要的理念:
- Subject :主体对象,负责提交用户认证和授权信息。
- SecurityManager:安全管理器,负责认证,授权等业务实现。
- Realm:领域对象,负责从数据层获取业务数据。
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
实现步骤
- 添加shiro依赖>>shiro-spring>>1.5.3
- 核心对象配置>>创建SpringShiroConfig.java>>@Configuration 注解描述的类为一个配置对象,对象会交给speing管理
- Shiro配置类中添加SecurityManager(org.apache.shiro.mgt.SecurityManager)安全管理器的配置需要==@bean==
//@Bean 通常会配置@Configuration注解进行使用,此注解描述方法会交给spring管理
//类的类型是public SecurityManager securityManager(){}
//里面用DefaultWebSecurityManager创建一个sManager对象
//返回类型是sManager
- Shiro配置类中添加ShiroFilterFactoryBean对象的配置
/* Spring容器在管理ShiroFilterFactoryBean对象,
* 会基于ShiroFilterFactoryBean对象, 创建过滤器工厂对象(SpringShiroFilter),
* 然后通过过滤器工厂创建过滤器(filter)对象,最后通过Filter对请求数据进行过滤,
* 例如调用securityManager的方法判定此请求是否已经过认证,假如没有经过认证
* 则跳转到登陆页面进行认证即可。*/
@Bean
public ShiroFilterFactoryBean shiroFilterFactory (){}
//参数是安全管理器(@Autowrite SecurityManager securityManager)
//利用ShiroFilterFactoryBean创建过滤器工程对象sfBean
//将参数传入到对象中sfBean.setSecurityManager(securityManager);
//然后在结合map最后对请求的数据进行过滤sfBean.setFilterChainDefinitionMap(map);
//定义类型为LinkedHashMap的map来指定请求过滤规则(哪些资源允许匿名访问,哪些必须认证访问)
允许匿名访问的用anon,除了匿名允许的其他的不行设置为map.put("/**",“authc”);
Shiro登陆页面呈现
- 服务器拦截请求后看请求是否被认证,如果没有认证就先跳转到登录页面(也就是前面设置的匿名允许)
- 先在控制层写一个到登录页面的方法@requestMApper(“doLoginUI”)…login
- 去Shiro核心对象配置中添加拦截之后的跳转sfBean.setLoginUrl("/doLoginUI");在controller中转到login认证
Shiro框架认证业务实现
其中认证流程分析如下:
- 系统调用subject的login方法将用户信息提交给SecurityManager
- SecurityManager将认证操作委托给认证器对象Authenticator
- Authenticator将用户输入的身份信息传递给Realm。
- Realm访问数据库获取用户信息然后对信息进行封装并返回。
- Authenticator 对realm返回的信息进行身份认证。
认证服务端实现
从这里开始就是说写一些传统数据的一些处理方式
- SysUserDao持久层定义类型进行数据库查询@Select(“select * from sys_users where username=#{username}”)
- 业务是在Realm类型的对象中进行实现,我们编写realm时,要继承AuthorizingRealm并重写相关方法,完成认证及授权业务数据的获取及封装.创建ShiroUserRealm.java
@Service
public class ShiroUserRealm extends AuthorizingRealm{}
//里面会重写两个方法
//protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals)/**负责完成授权信息的获取和封装*/
//protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)/**负责完成认证信息的获取和封装*/
//这里要调用@Autowired private SysUserDao sysUserDao;中的findUserByUserName方法对用户名进行查询
//对用户名进行判断然后可以的话就封装信息,return的类型就是封住类型
//凭证匹配器这里要设置加密的过程,就可以得到数据
- 对 此 realm(ShiroUserRealm )需 要 在 SpringShiroConfig 配 置 类 中 , 注 入 给SecurityManager对象,修改securityManager方法\
@Bean
public SecurityManager securityManager(Realm realm) {
DefaultWebSecurityManager sManager=
new DefaultWebSecurityManager();
sManager.setRealm(realm);
return sManager; }
- 在SysUserController中添加处理登陆的方法@RequestMapping("/user/")@RequestMapping(“doLogin”)
//将用户提交的信息提交给securitymanager进行认证。
Subject subject=SecurityUtils.getSubject();//获取subject
UsernamePasswordToken token=new UsernamePasswordToken(username,password);//凭证信息
subject.login(token);/对用户信息进行身份认证
return new JsonResult("login ok");//结束的时候提示一下
- 修改shiroFilterFactory的配置,对/user/doLogin这个路径进行匿名访问的配置 map.put("/user/doLogin",“anon”);
- 异常信息提醒写在了(com.cy.pj.common.web.GlobalExceptionHandler)中,这样交互友好
问题&异常
2020/7/25–第五天—Shiro安全框架授权 --day21----tmooc21
- 上午11点说的授权原理需要会看视频并记录一下
shiro中有这样的的一个注解(切入点方法),@RequiresPermission描述一个方法的时候,表示一个方法只有授权之后才能访问,不包含的时候则抛出异常。
/* @RequiresPermissions 这个注解描述的方法为一个切入点方法。此方法在执行之前
* 需要进行权限检测(负责这个过程的方法是一个通知方法),假如用户权限中包含
* @RequiresPermissions 注解value属性指定的值,则授权访问,不包含则抛出异常。
* 思考:假如你去设计这个切入点对应的通知方法,你会做什么?
*1)目标方法执行之前获取方法上的@RequiresPermissions注解,进而取到注解中内容。
*2)将注解中内容提交(subject.checkPermission(perstr))给SecurityManager对象(此对象负责授权操作)
*3)SecurityManager会基于realm去查找用户拥有的权限(这部分我们自己实现)。
*4)SecurityManager会判断用户拥有权限中是否包含RequiresPermissions注解中的内容
*5)SecurityManager基于用户权限进行授权或抛出异常。
/* 配置Advisor对象,此对象内容会关联切入点和相关通知
* @param securityManager
* @return */
@Bean //<bean id="" class="">
public AuthorizationAttributeSourceAdvisor
authorizationAttributeSourceAdvisor (
SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor advisor=//顾问对象
new AuthorizationAttributeSourceAdvisor();
advisor.setSecurityManager(securityManager);
return advisor;
}
配置advisor对象,shiro框架底层会通过此对象的matchs方法返回值(类似
切入点)决定是否创建代理对象,进行权限控制。
实现部分:
基于登陆用户ID,认证信息获取登陆用户的权限信息,并进行封装。(Dao,mapper)
- SysUserRoleDao中通过用户id查询到角色id
- SysRoleMenuDao中定义基于角色id寻找菜单id
- SysMenuDao中基于菜单id查询权限标识的方法
定义完方法后再mapper中 实现sql语句或是在方法上面书写也行
Service实现:
在ShiroUserReam类中,重写对象realm的doGetAuthorizationInfo方法,并完成
用户权限信息的获取以及封装,最后将信息传递给授权管理器完成授权操作。
- 下午的时候说的修改密码需要看视频
2020/7/27–第三阶段第五周第一天—动吧shiro
上午复制V3.01另存为V3.02
- 上午巴拉巴拉说了一堆我在整理外加做修改密码没听,需要补一下
下午动态体现不同角色的菜单
老师书写在v3.02里面,我还在V3.01
控制层访问拦截实现
通过对时间进行拦截,采用的Spring MVCC中的拦截器
在Ajax中进行了补充了