没有足够的数据
(゚∀゚ )
暂时没有任何数据
(゚∀゚ )
暂时没有任何数据
BolunWu 发布了文章 · 2020-12-15
1.表单创建1.1登录表单:[链接]:7001/Liems/ToolsLogin.jsp1.2选择菜单创建表单(画一步保存一步)1.3 发布表单登录系统查看样式.2.系统操作2.1在生产运行菜单中找到发布的表单的位置2.2到系统管理菜单中添加工作流2.3选择应用类型维护添加行,将创建的表单程序号和表单...
赞 0 收藏 0 评论 0
BolunWu 发布了文章 · 2020-11-13
/**
* 测试Redis分片机制
* 思考: shards 如何确定应该存储到哪台redis中呢???
*/
@Test
public void testShards(){
List<JedisShardInfo> shards = new ArrayList<>();
shards.add(new JedisShardInfo("192.168.126.129",6379));
shards.add(new JedisShardInfo("192.168.126.129",6380));
shards.add(new JedisShardInfo("192.168.126.129",6381));
//准备分片对象
ShardedJedis shardedJedis = new ShardedJedis(shards);
shardedJedis.set("shards","redis分片测试");
System.out.println(shardedJedis.get("shards"));
}
# 配置redis单台服务器
redis.host=192.168.126.129
redis.port=6379
# 配置redis分片机制
redis.nodes=192.168.126.129:6379,192.168.126.129:6380,192.168.126.129:6381
@Configuration
@PropertySource("classpath:/properties/redis.properties")
public class JedisConfig {
@Value("${redis.nodes}")
private String nodes; //node,node,node.....
//配置redis分片机制
@Bean
public ShardedJedis shardedJedis(){
nodes = nodes.trim(); //去除两边多余的空格
List<JedisShardInfo> shards = new ArrayList<>();
String[] nodeArray = nodes.split(",");
for (String strNode : nodeArray){ //strNode = host:port
String host = strNode.split(":")[0];
int port = Integer.parseInt(strNode.split(":")[1]);
JedisShardInfo info = new JedisShardInfo(host, port);
shards.add(info);
}
return new ShardedJedis(shards);
}
}
~~~~
1.Redis分片机制1.1为什么需要分片机制如果需要存储海量的内存数据,如果只使用一台redis,无法保证redis工作效率.大量的时间都浪费在了寻址当中.所以需要一种机制,来满足这种需求.采用分片机制实现:1.2Redis分片搭建1.2.1搭建注意事项Redis服务启动需要依赖redis.conf...
赞 0 收藏 0 评论 0
BolunWu 发布了文章 · 2020-11-13
[root@localhost src]# tar -zxvf redis-5.0.4.tar.gz
<!--spring整合redis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
</dependency>
package com.jt.test;
import org.junit.jupiter.api.Test;
import redis.clients.jedis.Jedis;
public class TestRedis {
/**
* 1.测试redis程序链接是否正常
* 步骤:
* 1.实例化jedis工具API对象(host:port)
* 2.根据实例 操作redis 方法就是命令
*
* 关于链接不通的说明:
* 1.检查Linux防火墙
* 2.检查Redis配置文件修改项
* 2.1 IP绑定
* 2.2 保护模式
* 2.3 后台启动
* 3.检查redis启动方式 redis-server redis.conf
* 4.检查IP 端口 及redis是否启动...
*
* */
@Test
public void test01(){
String host = "192.168.126.129";
int port = 6379;
Jedis jedis = new Jedis(host,port);
jedis.set("cgb2006","好好学习 天天向上");
System.out.println(jedis.get("cgb2006"));
//2.练习是否存在key
if(jedis.exists("cgb2006")){
jedis.del("cgb2006");
}else{
jedis.set("cgb2006", "xxxx");
jedis.expire("cgb2006", 100);
}
}
}
/**
* 2.需求:
* 1.向redis中插入数据 k-v
* 2.为key设定超时时间 60秒后失效.
* 3.线程sleep 3秒
* 4.获取key的剩余的存活时间.
*
* 问题描述: 数据一定会被删除吗??????
* 问题说明: 如果使用redis 并且需要添加超时时间时 一般需要满足原子性要求.
* 原子性: 操作时要么成功 要么失败.但是必须同时完成.
*/
@Test
public void test02() throws InterruptedException {
Jedis jedis = new Jedis("192.168.126.129",6379);
jedis.setex("宝可梦", 60, "小火龙 妙蛙种子");
System.out.println(jedis.get("宝可梦"));
/* Jedis jedis = new Jedis("192.168.126.129",6379);
jedis.set("宝可梦", "小火龙 妙蛙种子");
int a = 1/0; //可能会出异常
jedis.expire("宝可梦", 60);
Thread.sleep(3000);
System.out.println(jedis.ttl("宝可梦"));*/
}
/**
* 3.需求如果发现key已经存在时 不修改数据.如果key不存在时才会修改数据.
*
*/
@Test
public void test03() throws InterruptedException {
Jedis jedis = new Jedis("192.168.126.129", 6379);
jedis.setnx("aaaa", "测试nx的方法");
/*if(jedis.exists("aaa")){
System.out.println("key已经存在 不做修改");
}else {
jedis.set("aaa", "测试数据");
}*/
System.out.println(jedis.get("aaaa"));
}
/**
* 需求:
* 1.要求用户赋值时,如果数据存在则不赋值. setnx
* 2.要求在赋值操作时,必须设定超时的时间 并且要求满足原子性 setex
*/
@Test
public void test04() throws InterruptedException {
Jedis jedis = new Jedis("192.168.126.129", 6379);
SetParams setParams = new SetParams();
setParams.nx().ex(20);
jedis.set("bbbb", "实现业务操作AAAA", setParams);
System.out.println(jedis.get("bbbb"));
}
@Test
public void testList() throws InterruptedException {
Jedis jedis = new Jedis("192.168.126.129", 6379);
jedis.lpush("list", "1","2","3");
System.out.println(jedis.rpop("list"));
}
@Test
public void testTx() throws InterruptedException {
Jedis jedis = new Jedis("192.168.126.129", 6379);
//1.开启事务
Transaction transaction = jedis.multi();
try {
transaction.set("aa", "aa");
//提交事务
transaction.exec();
}catch (Exception e){
e.printStackTrace();
//回滚事务
transaction.discard();
}
}
@Configuration
@PropertySource("classpath:/properties/redis.properties")
public class JedisConfig {
@Value("${redis.host}")
private String host;
@Value("${redis.port}")
private Integer port;
@Bean
public Jedis jedis(){
return new Jedis(host,port);
}
}
/**
* 测试简单对象的转化
*/
@Test
public void test01() throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
ItemDesc itemDesc = new ItemDesc();
itemDesc.setItemId(100L).setItemDesc("商品详情信息")
.setCreated(new Date()).setUpdated(new Date());
//对象转化为json
String json = objectMapper.writeValueAsString(itemDesc);
System.out.println(json);
//json转化为对象
ItemDesc itemDesc2 = objectMapper.readValue(json, ItemDesc.class);
System.out.println(itemDesc2.getItemDesc());
}
/**
* 测试集合对象的转化
*/
@Test
public void test02() throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
ItemDesc itemDesc = new ItemDesc();
itemDesc.setItemId(100L).setItemDesc("商品详情信息1")
.setCreated(new Date()).setUpdated(new Date());
ItemDesc itemDesc2 = new ItemDesc();
itemDesc2.setItemId(100L).setItemDesc("商品详情信息2")
.setCreated(new Date()).setUpdated(new Date());
List<ItemDesc> lists = new ArrayList<>();
lists.add(itemDesc);
lists.add(itemDesc2);
//[{key:value},{}]
String json = objectMapper.writeValueAsString(lists);
System.out.println(json);
//将json串转化为对象
List<ItemDesc> list2 = objectMapper.readValue(json, lists.getClass());
System.out.println(list2);
}
package com.jt.util;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jt.pojo.ItemDesc;
import org.springframework.util.StringUtils;
public class ObjectMapperUtil {
/**
* 1.将用户传递的数据转化为json串
* 2.将用户传递的json串转化为对象
*/
private static final ObjectMapper MAPPER = new ObjectMapper();
//1.将用户传递的数据转化为json串
public static String toJSON(Object object){
if(object == null) {
throw new RuntimeException("传递的数据为null.请检查");
}
try {
String json = MAPPER.writeValueAsString(object);
return json;
} catch (JsonProcessingException e) {
//将检查异常,转化为运行时异常
e.printStackTrace();
throw new RuntimeException(e);
}
}
//需求: 要求用户传递什么样的类型,我返回什么样的对象 泛型的知识
public static <T> T toObj(String json,Class<T> target){
if(StringUtils.isEmpty(json) || target ==null){
throw new RuntimeException("参数不能为null");
}
try {
return MAPPER.readValue(json, target);
} catch (JsonProcessingException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
@Override
public List<EasyUITree> findItemCatListCache(Long parentId) {
//0.定义公共的返回值对象
List<EasyUITree> treeList = new ArrayList<>();
//1.定义key
String key = "ITEM_CAT_PARENTID::"+parentId;
//2.检索redis服务器,是否含有该key
//记录时间
Long startTime = System.currentTimeMillis();
if(jedis.exists(key)){
//数据存在
String json = jedis.get(key);
Long endTime = System.currentTimeMillis();
//需要将json串转化为对象
treeList = ObjectMapperUtil.toObj(json,treeList.getClass());
System.out.println("从redis中获取数据 耗时:"+(endTime-startTime)+"毫秒");
}else{
//3.数据不存在 查询数据库
treeList = findItemCatList(parentId);
Long endTime = System.currentTimeMillis();
//3.将数据保存到缓存中
String json = ObjectMapperUtil.toJSON(treeList);
jedis.set(key, json);
System.out.println("查询数据库 耗时:"+(endTime-startTime)+"毫秒");
}
return treeList;
}
@Target(ElementType.METHOD) //注解对方法有效
@Retention(RetentionPolicy.RUNTIME) //运行期有效
public @interface CacheFind {
public String preKey(); //用户标识key的前缀.
public int seconds() default 0; //如果用户不写表示不需要超时. 如果写了以用户为准.
}
package com.jt.aop;
import com.jt.anno.CacheFind;
import com.jt.config.JedisConfig;
import com.jt.util.ObjectMapperUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import redis.clients.jedis.Jedis;
import java.lang.reflect.Method;
import java.util.Arrays;
@Aspect //我是一个AOP切面类
@Component //将类交给spring容器管理
public class CacheAOP {
@Autowired
private Jedis jedis;
/**
* 切面 = 切入点 + 通知方法
* 注解相关 + 环绕通知 控制目标方法是否执行
*
* 难点:
* 1.如何获取注解对象
* 2.动态生成key prekey + 用户参数数组
* 3.如何获取方法的返回值类型
*/
@Around("@annotation(cacheFind)")
public Object around(ProceedingJoinPoint joinPoint,CacheFind cacheFind){
Object result = null;
try {
//1.拼接redis存储数据的key
Object[] args = joinPoint.getArgs();
String key = cacheFind.preKey() +"::" + Arrays.toString(args);
//2. 查询redis 之后判断是否有数据
if(jedis.exists(key)){
//redis中有记录,无需执行目标方法
String json = jedis.get(key);
//动态获取方法的返回值类型 向上造型 向下造型
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
Class returnType = methodSignature.getReturnType();
result = ObjectMapperUtil.toObj(json,returnType);
System.out.println("AOP查询redis缓存");
}else{
//表示数据不存在,需要查询数据库
result = joinPoint.proceed(); //执行目标方法及通知
//将查询的结果保存到redis中去
String json = ObjectMapperUtil.toJSON(result);
//判断数据是否需要超时时间
if(cacheFind.seconds()>0){
jedis.setex(key,cacheFind.seconds(),json);
}else {
jedis.set(key, json);
}
System.out.println("aop执行目标方法查询数据库");
}
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return result;
}
}
1.Redis介绍redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操...
赞 0 收藏 0 评论 0
BolunWu 发布了文章 · 2020-11-13
package com.jt.dubbo.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import com.alibaba.dubbo.config.annotation.Service;
import com.jt.dubbo.mapper.UserMapper;
import com.jt.dubbo.pojo.User;
@Service(timeout=3000) //3秒超时 内部实现了rpc
//@org.springframework.stereotype.Service//将对象交给spring容器管理
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public List<User> findAll() {
System.out.println("我是第一个服务的提供者");
return userMapper.selectList(null);
}
@Override
public void saveUser(User user) {
userMapper.insert(user);
}
}
server:
port: 9000 #定义端口
spring:
datasource:
#引入druid数据源
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/jtdb?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true
username: root
password: root
#关于Dubbo配置
dubbo:
scan:
basePackages: com.jt #指定dubbo的包路径 扫描dubbo注解
application: #应用名称
name: provider-user #一个接口对应一个服务名称 一个接口可以有多个实现
registry: #注册中心 用户获取数据从机中获取 主机只负责监控整个集群 实现数据同步
address: zookeeper://192.168.126.129:2181?backup=192.168.126.129:2182,192.168.126.129:2183
protocol: #指定协议
name: dubbo #使用dubbo协议(tcp-ip) web-controller直接调用sso-Service
port: 20880 #每一个服务都有自己特定的端口 不能重复.
mybatis-plus:
type-aliases-package: com.jt.dubbo.pojo #配置别名包路径
mapper-locations: classpath:/mybatis/mappers/*.xml #添加mapper映射文件
configuration:
map-underscore-to-camel-case: true #开启驼峰映射规则
package com.jt.dubbo.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.alibaba.dubbo.config.annotation.Reference;
import com.jt.dubbo.pojo.User;
import com.jt.dubbo.service.UserService;
@RestController
public class UserController {
//利用dubbo的方式为接口创建代理对象 利用rpc调用
@Reference
private UserService userService;
/**
* Dubbo框架调用特点:远程RPC调用就像调用自己本地服务一样简单
* @return
*/
@RequestMapping("/findAll")
public List<User> findAll(){
//远程调用时传递的对象数据必须序列化.
return userService.findAll();
}
@RequestMapping("/saveUser/{name}/{age}/{sex}")
public String saveUser(User user) {
userService.saveUser(user);
return "用户入库成功!!!";
}
}
server:
port: 9001
dubbo:
scan:
basePackages: com.jt
application:
name: consumer-user #定义消费者名称
registry: #注册中心地址
address: zookeeper://192.168.126.129:2181?backup=192.168.126.129:2182,192.168.126.129:2183
@RestController
public class UserController {
//利用dubbo的方式为接口创建代理对象 利用rpc调用
//@Reference(loadbalance = "random") //默认策略 负载均衡随机策略
//@Reference(loadbalance = "roundrobin") //轮询方式
//@Reference(loadbalance = "consistenthash") //一致性hash 消费者绑定服务器提供者
@Reference(loadbalance = "leastactive") //挑选当前负载小的服务器进行访问
private UserService userService;
}
<!--引入dubbo配置 -->
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>0.2.0</version>
</dependency>
server:
port: 8093
servlet:
context-path: /
spring:
datasource:
#引入druid数据源
#type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/jtdb?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true
username: root
password: root
mvc:
view:
prefix: /WEB-INF/views/
suffix: .jsp
#mybatis-plush配置
mybatis-plus:
type-aliases-package: com.jt.pojo
mapper-locations: classpath:/mybatis/mappers/*.xml
configuration:
map-underscore-to-camel-case: true
logging:
level:
com.jt.mapper: debug
#关于Dubbo配置
dubbo:
scan:
basePackages: com.jt #指定dubbo的包路径 扫描dubbo注解
application: #应用名称
name: provider-user #一个接口对应一个服务名称 一个接口可以有多个实现
registry: #注册中心 用户获取数据从机中获取 主机只负责监控整个集群 实现数据同步
address: zookeeper://192.168.126.129:2181?backup=192.168.126.129:2182,192.168.126.129:2183
protocol: #指定协议
name: dubbo #使用dubbo协议(tcp-ip) web-controller直接调用sso-Service
port: 20880 #每一个服务都有自己特定的端口 不能重复.
server:
port: 8092
spring: #定义springmvc视图解析器
mvc:
view:
prefix: /WEB-INF/views/
suffix: .jsp
dubbo:
scan:
basePackages: com.jt
application:
name: consumer-web #定义消费者名称
registry: #注册中心地址
address: zookeeper://192.168.126.129:2181?backup=192.168.126.129:2182,192.168.126.129:2183
~~~~
1.Dubbo1.1 Dubbo介绍Apache Dubbo是一款高性能,轻量级的开源Java RPC框架,他提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现.1.2 Dubbo特点2.Dubbo入门案例2.1定义公共接口项目说明:接口项目一般定义公共的部分,并且被第三方...
赞 0 收藏 0 评论 0
BolunWu 发布了文章 · 2020-11-11
spring.aop.proxy-target-class=false
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
package com.cy.pj.common.aspect;
@Aspect
@Slf4j
@Component
public class SysLogAspect {
@Pointcut("bean(sysUserServiceImpl)")
public void logPointCut() {}
@Around("logPointCut()")
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("after:{}",e.getMessage());
throw e;
}
}
@SpringBootTest
public class AopTests {
@Autowired
private SysUserService userService;
@Test
public void testSysUserService() {
PageObject<SysUserDeptVo> po=
userService.findPageObjects("admin",1);
System.out.println("rowCount:"+po.getRowCount());
}
}
@Component
@Aspect
public class SysTimeAspect {
@Pointcut("bean(sysUserServiceImpl)")
public void doTime(){}
@Before("doTime()")
public void doBefore(JoinPoint jp){
System.out.println("time doBefore()");
}
@After("doTime()")
public void doAfter(){
System.out.println("time doAfter()");
}
/**核心业务正常结束时执行* 说明:假如有after,先执行after,再执行returning*/
@AfterReturning("doTime()")
public void doAfterReturning(){
System.out.println("time doAfterReturning");
}
/**核心业务出现异常时执行说明:假如有after,先执行after,再执行Throwing*/
@AfterThrowing("doTime()")
public void doAfterThrowing(){
System.out.println("time doAfterThrowing");
}
@Around("doTime()")
public Object doAround(ProceedingJoinPoint jp)
throws Throwable{
System.out.println("doAround.before");
try{
Object obj=jp.proceed();
System.out.println("doAround.after");
return obj;
}catch(Throwable e){
System.out.println(e.getMessage());
throw e;
}
}
}
package com.cy.pj.common.annotation;
/**
* 自定义注解,一个特殊的类,所有注解都默认继承Annotation接口
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface RequiredCache {
//...
}
package com.cy.pj.common.aspect;
@Aspect
@Component
public class SysCacheAspect {
@Pointcut("@annotation(com.cy.pj.common.annotation.RequiredCache)")
public void doCache() {}
@Around("doCache()")
public Object around(ProceedingJoinPoint jp)
throws Throwable{
System.out.println("Get data from cache");
Object obj=jp.proceed();
System.out.println("Put data to cache");
return obj;
}
}
@RequiredCache
@Override
public List<Map<String, Object>> findObjects() {
….
return list;
}
@Order(1)
@Aspect
@Component
public class SysLogAspect {
…
}
@Order(2)
@Aspect
@Component
public class SysCacheAspect {
…
}
@Transactional(timeout = 30,
readOnly = false,
isolation = Isolation.READ_COMMITTED,
rollbackFor = Throwable.class,
propagation = Propagation.REQUIRED)
@Service
public class implements SysUserService {
@Transactional(readOnly = true)
@Override
public PageObject<SysUserDeptVo> findPageObjects(
String username, Integer pageCurrent) {
…
}
}
@EnableAsync //spring容器启动时会创建线程池
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
@Async
@Transactional(propagation = Propagation.REQUIRES_NEW)
@Override
public void saveObject(SysLog entity) {
System.out.println("SysLogServiceImpl.save:"+
Thread.currentThread().getName());
sysLogDao.insertObject(entity);
//try{Thread.sleep(5000);}catch(Exception e) {}
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
@Async
@Override
public Future<Integer> saveObject(SysLog entity) {
System.out.println("SysLogServiceImpl.save:"+
Thread.currentThread().getName());
int rows=sysLogDao.insertObject(entity);
//try{Thread.sleep(5000);}catch(Exception e) {}
return new AsyncResult<Integer>(rows);
}
spring:
task:
execution:
pool:
queue-capacity: 128
core-size: 5
max-size: 128
keep-alive: 60000
thread-name-prefix: db-service-task-
查看原文1.1 AOP概述1.1.1 AOP是什么?AOP是一种设计思想,是软件设计领域的面向切面编程,他是面向对象编程OOP的一种补充和完善.它以通过预编译的方式和运行期动态代理方式,实现在不修改源代码的情况下给程序动态统一添加额外功能的一种技术.1.1.2 AOP应用场景分析?实际项目中...
赞 1 收藏 1 评论 0
BolunWu 发布了文章 · 2020-11-11
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.5.3</version>
</dependency>
package com.cy.pj.common.config;
/**@Configuration 注解描述的类为一个配置对象,
* 此对象也会交给spring管理
*/
@Configuration
public class SpringShiroConfig {
}
@Bean
public SecurityManager securityManager() {
DefaultWebSecurityManager sManager=
new DefaultWebSecurityManager();
return sManager;
}
@Bean
public ShiroFilterFactoryBean shiroFilterFactory (
SecurityManager securityManager) {
ShiroFilterFactoryBean sfBean=
new ShiroFilterFactoryBean();
sfBean.setSecurityManager(securityManager);
//定义map指定请求过滤规则(哪些资源允许匿名访问,哪些必须认证访问)
LinkedHashMap<String,String> map= new LinkedHashMap<>();
//静态资源允许匿名访问:"anon"
map.put("/bower_components/**","anon");
map.put("/build/**","anon");
map.put("/dist/**","anon");
map.put("/plugins/**","anon");
//除了匿名访问的资源,其它都要认证("authc")后访问
map.put("/**","authc");
sfBean.setFilterChainDefinitionMap(map);
return sfBean;
}
@RequestMapping("doLoginUI")
public String doLoginUI(){
return "login";
}
@Bean
public ShiroFilterFactoryBean shiroFilterFactory (
SecurityManager securityManager) {
ShiroFilterFactoryBean sfBean=
new ShiroFilterFactoryBean();
sfBean.setSecurityManager(securityManager);
sfBean.setLoginUrl("/doLoginUI");
//定义map指定请求过滤规则(哪些资源允许匿名访问,
哪些必须认证访问)
LinkedHashMap<String,String> map=
new LinkedHashMap<>();
//静态资源允许匿名访问:"anon"
map.put("/bower_components/**","anon");
map.put("/modules/**","anon");
map.put("/dist/**","anon");
map.put("/plugins/**","anon");
//除了匿名访问的资源,其它都要认证("authc")后访问
map.put("/**","authc");
sfBean.setFilterChainDefinitionMap(map);
return sfBean;
}
SysUser findUserByUserName(String username)。
<select id="findUserByUserName"
resultType="com.cy.pj.sys.entity.SysUser">
select *
from sys_users
where username=#{username}
</select>
package com.cy.pj.sys.service.realm;
@Service
public class ShiroUserRealm extends AuthorizingRealm {
@Autowired
private SysUserDao sysUserDao;
/**
* 设置凭证匹配器(与用户添加操作使用相同的加密算法)
*/
@Override
public void setCredentialsMatcher(
CredentialsMatcher credentialsMatcher) {
//构建凭证匹配对象
HashedCredentialsMatcher cMatcher=
new HashedCredentialsMatcher();
//设置加密算法
cMatcher.setHashAlgorithmName("MD5");
//设置加密次数
cMatcher.setHashIterations(1);
super.setCredentialsMatcher(cMatcher);
}
/**
* 通过此方法完成认证数据的获取及封装,系统
* 底层会将认证数据传递认证管理器,由认证
* 管理器完成认证操作。
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken token)
throws AuthenticationException {
//1.获取用户名(用户页面输入)
UsernamePasswordToken upToken=
(UsernamePasswordToken)token;
String username=upToken.getUsername();
//2.基于用户名查询用户信息
SysUser user=
sysUserDao.findUserByUserName(username);
//3.判定用户是否存在
if(user==null)
throw new UnknownAccountException();
//4.判定用户是否已被禁用。
if(user.getValid()==0)
throw new LockedAccountException();
//5.封装用户信息
ByteSource credentialsSalt=
ByteSource.Util.bytes(user.getSalt());
//记住:构建什么对象要看方法的返回值
SimpleAuthenticationInfo info=
new SimpleAuthenticationInfo(
user,//principal (身份)
user.getPassword(),//hashedCredentials
credentialsSalt, //credentialsSalt
getName());//realName
//6.返回封装结果
return info;//返回值会传递给认证管理器(后续
//认证管理器会通过此信息完成认证操作)
}
....
}
@Bean
public SecurityManager securityManager(Realm realm) {
DefaultWebSecurityManager sManager=
new DefaultWebSecurityManager();
sManager.setRealm(realm);
return sManager;
}
public JsonResult doLogin(String username,String password){
//1.获取Subject对象
Subject subject=SecurityUtils.getSubject();
//2.通过Subject提交用户信息,交给shiro框架进行认证操作
//2.1对用户进行封装
UsernamePasswordToken token=
new UsernamePasswordToken(
username,//身份信息
password);//凭证信息
//2.2对用户信息进行身份认证
subject.login(token);
//分析:
//1)token会传给shiro的SecurityManager
//2)SecurityManager将token传递给认证管理器
//3)认证管理器会将token传递给realm
return new JsonResult("login ok");
}
@Bean
public ShiroFilterFactoryBean shiroFilterFactory (
SecurityManager securityManager) {
ShiroFilterFactoryBean sfBean=
new ShiroFilterFactoryBean();
sfBean.setSecurityManager(securityManager);
//假如没有认证请求先访问此认证的url
sfBean.setLoginUrl("/doLoginUI");
//定义map指定请求过滤规则(哪些资源允许匿名访问,哪些必须认证访问)
LinkedHashMap<String,String> map=
new LinkedHashMap<>();
//静态资源允许匿名访问:"anon"
map.put("/bower_components/**","anon");
map.put("/build/**","anon");
map.put("/dist/**","anon");
map.put("/plugins/**","anon");
map.put("/user/doLogin","anon"); //authc表示,除了匿名访问的资源,其它都要认证("authc")后才能访问访问
map.put("/**","authc");
sfBean.setFilterChainDefinitionMap(map);
return sfBean;
}
@ExceptionHandler(ShiroException.class)
@ResponseBody
public JsonResult doHandleShiroException(
ShiroException e) {
JsonResult r=new JsonResult();
r.setState(0);
if(e instanceof UnknownAccountException) {
r.setMessage("账户不存在");
}else if(e instanceof LockedAccountException) {
r.setMessage("账户已被禁用");
}else if(e instanceof IncorrectCredentialsException) {
r.setMessage("密码不正确");
}else if(e instanceof AuthorizationException) {
r.setMessage("没有此操作权限");
}else {
r.setMessage("系统维护中");
}
e.printStackTrace();
return r;
}
@Bean
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
@DependsOn("lifecycleBeanPostProcessor")
@Bean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
return new DefaultAdvisorAutoProxyCreator();
}
@Bean
public AuthorizationAttributeSourceAdvisor
authorizationAttributeSourceAdvisor (
SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor advisor=
new AuthorizationAttributeSourceAdvisor();
advisor.setSecurityManager(securityManager);
return advisor;
}
//说明:使用框架最重要的尊重规则,框架规则指定了什么方式就使用什么方式。
List<Integer> findRoleIdsByUserId(Integer id);
List<Integer> findMenuIdsByRoleIds(
@Param("roleIds")List<Integer> roleIds);
List<String> findPermissions(
@Param("menuIds")
List<Integer> menuIds);
<select id="findRoleIdsByUserId"
resultType="int">
select role_id
from sys_user_roles
where user_id=#{userId}
</select>
<select id="findMenuIdsByRoleIds"
resultType="int">
select menu_id
from sys_role_menus
where role_id in
<foreach collection="roleIds"
open="("
close=")"
separator=","
item="item">
#{item}
</foreach>
</select>
<select id="findPermissions"
resultType="string">
select permission <!-- sys:user:update -->
from sys_menus
where id in
<foreach collection="menuIds"
open="("
close=")"
separator=","
item="item">
#{item}
</foreach>
</select>
@Service
public class ShiroUserRealm extends AuthorizingRealm {
@Autowired
private SysUserDao sysUserDao;
@Autowired
private SysUserRoleDao sysUserRoleDao;
@Autowired
private SysRoleMenuDao sysRoleMenuDao;
@Autowired
private SysMenuDao sysMenuDao;
/**通过此方法完成授权信息的获取及封装*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(
PrincipalCollection principals) {
//1.获取登录用户信息,例如用户id
SysUser user=(SysUser)principals.getPrimaryPrincipal();
Integer userId=user.getId();
//2.基于用户id获取用户拥有的角色(sys_user_roles)
List<Integer> roleIds=
sysUserRoleDao.findRoleIdsByUserId(userId);
if(roleIds==null||roleIds.size()==0)
throw new AuthorizationException();
//3.基于角色id获取菜单id(sys_role_menus)
List<Integer> menuIds=
sysRoleMenuDao.findMenuIdsByRoleIds(roleIds);
if(menuIds==null||menuIds.size()==0)
throw new AuthorizationException();
//4.基于菜单id获取权限标识(sys_menus)
List<String> permissions=
sysMenuDao.findPermissions(menuIds);
//5.对权限标识信息进行封装并返回
Set<String> set=new HashSet<>();
for(String per:permissions){
if(!StringUtils.isEmpty(per)){
set.add(per);
}
}
SimpleAuthorizationInfo info=
new SimpleAuthorizationInfo();
info.setStringPermissions(set);
return info;//返回给授权管理器
}
}
@RequestMapping("doLogin")
@ResponseBody
public JsonResult doLogin(
boolean isRememberMe,
String username,
String password) {
//1.封装用户信息
UsernamePasswordToken token=
new UsernamePasswordToken(username, password);
if(isRememberMe) {
token.setRememberMe(true);
}
//2.提交用户信息
Subject subject=SecurityUtils.getSubject();
subject.login(token);//token会提交给securityManager
return new JsonResult("login ok");
}
@Bean
public RememberMeManager rememberMeManager() {
CookieRememberMeManager cManager=
new CookieRememberMeManager();
SimpleCookie cookie=new SimpleCookie("rememberMe");
cookie.setMaxAge(7*24*60*60);
cManager.setCookie(cookie);
return cManager;
}
@Bean
public SecurityManager securityManager(
Realm realm,CacheManager cacheManager
RememberMeManager rememberManager) {
DefaultWebSecurityManager sManager=
new DefaultWebSecurityManager();
sManager.setRealm(realm);
sManager.setCacheManager(cacheManager);
sManager.setRememberMeManager(rememberManager);
return sManager;
}
@Bean
public ShiroFilterFactoryBean shiroFilterFactory(
SecurityManager securityManager) {
ShiroFilterFactoryBean sfBean=
new ShiroFilterFactoryBean();
sfBean.setSecurityManager(securityManager);
//假如没有认证请求先访问此认证的url
sfBean.setLoginUrl("/doLoginUI");
//定义map指定请求过滤规则(哪些资源允许匿名访问,哪些必须认证访问)
LinkedHashMap<String,String> map=
new LinkedHashMap<>();
//静态资源允许匿名访问:"anon"
map.put("/bower_components/**","anon");
map.put("/build/**","anon");
map.put("/dist/**","anon");
map.put("/plugins/**","anon");
map.put("/user/doLogin","anon");
map.put("/doLogout", "logout");//自动查LoginUrl
//除了匿名访问的资源,其它都要认证("authc")后访问
map.put("/**","user");//authc
sfBean.setFilterChainDefinitionMap(map);
return sfBean;
}
@Bean
public SessionManager sessionManager() {
DefaultWebSessionManager sManager=
new DefaultWebSessionManager();
sManager.setGlobalSessionTimeout(60*60*1000);
return sManager;
}
@Bean
public SecurityManager securityManager(
Realm realm,CacheManager cacheManager,
RememberMeManager rememberManager,
SessionManager sessionManager) {
DefaultWebSecurityManager sManager=
new DefaultWebSecurityManager();
sManager.setRealm(realm);
sManager.setCacheManager(cacheManager);
sManager.setRememberMeManager(rememberMeManager);
sManager.setSessionManager(sessionManager);
return sManager;
}
查看原文1.Shiro安全框架1.1Shiro框架简介Shiro是apache旗下一个开源安全框架([链接]1.2Shiro的概要架构1)Subject:主体对象,负责提交用户认证和授权信息.2)SecuritvManager:安全管理器,负责认证,授权等业务实现.3)Realm:领域对象,负责从数据层获取业务数据.1.3Shiro框架认证...
赞 0 收藏 0 评论 0
BolunWu 发布了文章 · 2020-11-10
#1.mysql数据库驱动依赖
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
#2.spring对象jdbc支持(此时会默认帮我们下载HikariCP连接池)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
spring.datasource.url=jdbc:mysql:///dbgoods?serverTimezone=GMT%2B8&characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=root
package com.cy.pj.common.datasource;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class DataSourceTests {
@Autowired
private DataSource dataSource;
@Test
public void testConnection() throws Exception{
System.out.println(dataSource.getConnection());
}
}
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.1</version>
</dependency>
mybatis.configuration.default-statement-timeout=30
mybatis.configuration.map-underscore-to-camel-case=true
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>~~~~
</dependency>
spring.thymeleaf.prefix=classpath:/templates/pages/
spring.thymeleaf.suffix=.html
项目中添加健康检查依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
management.endpoints.web.exposure.include=*
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
查看原文1.Spring Boot核心特性1.1Springboot是一个脚手架,构建于Spring框架(framwork)基础之上,基于快速构建理念,提供了自动配置功能,可实现其开箱即用特性(创建完一个基本的项目以后,可零配置或者少量配置即可运行我们的项目),其核心主要有如下几个方面:起步依赖--创建项目...
赞 0 收藏 0 评论 0
BolunWu 发布了文章 · 2020-11-07
http://image.jt.com/2020/09/30/a.jpg
file:///D:/JT-SOFT/image/2020/09/30/d534bed912c748b0ac979ee40222490a.jpg
1.restFul业务需求:实现用户的页面跳转url:[链接]:8091/page/item-add 页面:item-add[链接]:8091/page/item-list 页面:item-list能否利用一个方法来实现通用页面的跳转功能如果能动态获取url中的参数就可以实现页面的跳转.restFul风格...1.1restFul语法:1.参数必须使...
赞 0 收藏 0 评论 0
查看全部 个人动态 →
(゚∀゚ )
暂时没有
(゚∀゚ )
暂时没有
注册于 2020-08-25
个人主页被 914 人浏览
推荐关注