4670101279
2 years ago
18 changed files with 448 additions and 179 deletions
@ -0,0 +1,66 @@
@@ -0,0 +1,66 @@
|
||||
/** |
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved. |
||||
* |
||||
* https://www.renren.io
|
||||
* |
||||
* 版权所有,侵权必究! |
||||
*/ |
||||
|
||||
package com.ruoyi.common.core.page; |
||||
|
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* 返回数据 |
||||
* |
||||
* @author Mark sunlightcs@gmail.com |
||||
*/ |
||||
public class R extends HashMap<String, Object> { |
||||
private static final long serialVersionUID = 1L; |
||||
|
||||
public R() { |
||||
put("code", 0); |
||||
put("msg", "操作成功"); |
||||
} |
||||
|
||||
public R(Object o) {} |
||||
|
||||
public static R error() { |
||||
return error(500, "发生错误,请联系管理员"); |
||||
} |
||||
|
||||
public static R error(String msg) { |
||||
return error(500, msg); |
||||
} |
||||
|
||||
public static R error(int code, String msg) { |
||||
R r = new R(); |
||||
r.put("code", code); |
||||
r.put("msg", msg); |
||||
return r; |
||||
} |
||||
|
||||
public static R ok(String msg) { |
||||
R r = new R(); |
||||
r.put("msg", msg); |
||||
return r; |
||||
} |
||||
|
||||
public static R ok(Map<String, Object> map) { |
||||
R r = new R(); |
||||
r.putAll(map); |
||||
return r; |
||||
} |
||||
|
||||
public static R ok() { |
||||
return new R(); |
||||
} |
||||
|
||||
@Override |
||||
public R put(String key, Object value) { |
||||
super.put(key, value); |
||||
return this; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,61 @@
@@ -0,0 +1,61 @@
|
||||
/** |
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved. |
||||
* |
||||
* https://www.renren.io
|
||||
* |
||||
* 版权所有,侵权必究! |
||||
*/ |
||||
|
||||
package com.ruoyi.common.exception; |
||||
|
||||
/** |
||||
* 自定义异常 |
||||
* |
||||
* @author Mark sunlightcs@gmail.com |
||||
*/ |
||||
public class RYException extends RuntimeException { |
||||
private static final long serialVersionUID = 1L; |
||||
|
||||
private String msg; |
||||
private int code = 500; |
||||
|
||||
public RYException(String msg) { |
||||
super(msg); |
||||
this.msg = msg; |
||||
} |
||||
|
||||
public RYException(String msg, Throwable e) { |
||||
super(msg, e); |
||||
this.msg = msg; |
||||
} |
||||
|
||||
public RYException(String msg, int code) { |
||||
super(msg); |
||||
this.msg = msg; |
||||
this.code = code; |
||||
} |
||||
|
||||
public RYException(String msg, int code, Throwable e) { |
||||
super(msg, e); |
||||
this.msg = msg; |
||||
this.code = code; |
||||
} |
||||
|
||||
public String getMsg() { |
||||
return msg; |
||||
} |
||||
|
||||
public void setMsg(String msg) { |
||||
this.msg = msg; |
||||
} |
||||
|
||||
public int getCode() { |
||||
return code; |
||||
} |
||||
|
||||
public void setCode(int code) { |
||||
this.code = code; |
||||
} |
||||
|
||||
|
||||
} |
@ -0,0 +1,36 @@
@@ -0,0 +1,36 @@
|
||||
package com.ruoyi.common.utils; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
import org.apache.commons.io.output.CloseShieldOutputStream; |
||||
import org.springframework.beans.BeansException; |
||||
import org.springframework.beans.factory.DisposableBean; |
||||
import org.springframework.context.ApplicationContext; |
||||
import org.springframework.context.ApplicationContextAware; |
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
public class BeanUtil implements ApplicationContextAware, DisposableBean { |
||||
private static ApplicationContext applicationContext = null; |
||||
|
||||
/** |
||||
* 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型. |
||||
*/ |
||||
public static <T> T getBean(Class<T> requiredType) { |
||||
if(applicationContext==null){ |
||||
throw new IllegalStateException("applicaitonContext属性未注入, 请在SpringBoot启动类中注册BeanUtil."); |
||||
} |
||||
return applicationContext.getBean(requiredType); |
||||
} |
||||
|
||||
@Override |
||||
public void destroy() { |
||||
applicationContext = null; |
||||
} |
||||
|
||||
@Override |
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { |
||||
if (BeanUtil.applicationContext != null) { |
||||
System.out.println("BeanUtil中的ApplicationContext被覆盖, 原有ApplicationContext为:" + BeanUtil.applicationContext); |
||||
} |
||||
BeanUtil.applicationContext = applicationContext; |
||||
} |
||||
} |
@ -0,0 +1,75 @@
@@ -0,0 +1,75 @@
|
||||
/** |
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved. |
||||
* |
||||
* https://www.renren.io
|
||||
* |
||||
* 版权所有,侵权必究! |
||||
*/ |
||||
|
||||
package com.ruoyi.common.utils; |
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.OrderItem; |
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
||||
import com.ruoyi.common.constant.Constants; |
||||
import com.ruoyi.common.xss.SQLFilter; |
||||
|
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* 查询参数 |
||||
* |
||||
* @author Mark sunlightcs@gmail.com |
||||
*/ |
||||
public class Query<T> { |
||||
|
||||
public Page<T> getPage(Map<String, Object> params) { |
||||
return this.getPage(params, null, false); |
||||
} |
||||
|
||||
public Page<T> getPage(Map<String, Object> params, String defaultOrderField, boolean isAsc) { |
||||
//分页参数
|
||||
long curPage = 1; |
||||
long limit = 10; |
||||
|
||||
if(params.get(Constants.PAGE) != null){ |
||||
curPage = Long.parseLong((String)params.get(Constants.PAGE)); |
||||
} |
||||
if(params.get(Constants.LIMIT) != null){ |
||||
limit = Long.parseLong((String)params.get(Constants.LIMIT)); |
||||
} |
||||
|
||||
//分页对象
|
||||
Page<T> page = new Page<>(curPage, limit); |
||||
|
||||
//分页参数
|
||||
params.put(Constants.PAGE, page); |
||||
|
||||
//排序字段
|
||||
//防止SQL注入(因为sidx、order是通过拼接SQL实现排序的,会有SQL注入风险)
|
||||
String orderField = SQLFilter.sqlInject((String)params.get(Constants.ORDER_FIELD)); |
||||
String order = (String)params.get(Constants.ORDER); |
||||
|
||||
//前端字段排序
|
||||
if(StringUtils.isNotEmpty(orderField) && StringUtils.isNotEmpty(order)){ |
||||
if(Constants.ASC.equalsIgnoreCase(order)) { |
||||
return page.addOrder(OrderItem.asc(orderField)); |
||||
}else { |
||||
return page.addOrder(OrderItem.desc(orderField)); |
||||
} |
||||
} |
||||
|
||||
//没有排序字段,则不排序
|
||||
if(StringUtils.isBlank(defaultOrderField)){ |
||||
return page; |
||||
} |
||||
|
||||
//默认排序
|
||||
if(isAsc) { |
||||
page.addOrder(OrderItem.asc(defaultOrderField)); |
||||
}else { |
||||
page.addOrder(OrderItem.desc(defaultOrderField)); |
||||
} |
||||
|
||||
return page; |
||||
} |
||||
} |
@ -0,0 +1,51 @@
@@ -0,0 +1,51 @@
|
||||
/** |
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved. |
||||
* |
||||
* https://www.renren.io
|
||||
* |
||||
* 版权所有,侵权必究! |
||||
*/ |
||||
|
||||
package com.ruoyi.common.xss; |
||||
|
||||
|
||||
import com.ruoyi.common.exception.RYException; |
||||
import org.apache.commons.lang3.StringUtils; |
||||
|
||||
/** |
||||
* SQL过滤 |
||||
* |
||||
* @author Mark sunlightcs@gmail.com |
||||
*/ |
||||
public class SQLFilter { |
||||
|
||||
/** |
||||
* SQL注入过滤 |
||||
* @param str 待验证的字符串 |
||||
*/ |
||||
public static String sqlInject(String str){ |
||||
if(StringUtils.isBlank(str)){ |
||||
return null; |
||||
} |
||||
//去掉'|"|;|\字符
|
||||
str = StringUtils.replace(str, "'", ""); |
||||
str = StringUtils.replace(str, "\"", ""); |
||||
str = StringUtils.replace(str, ";", ""); |
||||
str = StringUtils.replace(str, "\\", ""); |
||||
|
||||
//转换成小写
|
||||
str = str.toLowerCase(); |
||||
|
||||
//非法字符
|
||||
String[] keywords = {"master", "truncate", "insert", "select", "delete", "update", "declare", "alter", "drop"}; |
||||
|
||||
//判断是否包含非法字符
|
||||
for(String keyword : keywords){ |
||||
if(str.indexOf(keyword) != -1){ |
||||
throw new RYException("包含非法字符"); |
||||
} |
||||
} |
||||
|
||||
return str; |
||||
} |
||||
} |
@ -1,132 +0,0 @@
@@ -1,132 +0,0 @@
|
||||
package com.ruoyi.framework.config; |
||||
|
||||
import java.io.IOException; |
||||
import java.util.ArrayList; |
||||
import java.util.Arrays; |
||||
import java.util.HashSet; |
||||
import java.util.List; |
||||
import javax.sql.DataSource; |
||||
import org.apache.ibatis.io.VFS; |
||||
import org.apache.ibatis.session.SqlSessionFactory; |
||||
import org.mybatis.spring.SqlSessionFactoryBean; |
||||
import org.mybatis.spring.boot.autoconfigure.SpringBootVFS; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.core.env.Environment; |
||||
import org.springframework.core.io.DefaultResourceLoader; |
||||
import org.springframework.core.io.Resource; |
||||
import org.springframework.core.io.support.PathMatchingResourcePatternResolver; |
||||
import org.springframework.core.io.support.ResourcePatternResolver; |
||||
import org.springframework.core.type.classreading.CachingMetadataReaderFactory; |
||||
import org.springframework.core.type.classreading.MetadataReader; |
||||
import org.springframework.core.type.classreading.MetadataReaderFactory; |
||||
import org.springframework.util.ClassUtils; |
||||
import com.ruoyi.common.utils.StringUtils; |
||||
|
||||
/** |
||||
* Mybatis支持*匹配扫描包 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
@Configuration |
||||
public class MyBatisConfig |
||||
{ |
||||
@Autowired |
||||
private Environment env; |
||||
|
||||
static final String DEFAULT_RESOURCE_PATTERN = "**/*.class"; |
||||
|
||||
public static String setTypeAliasesPackage(String typeAliasesPackage) |
||||
{ |
||||
ResourcePatternResolver resolver = (ResourcePatternResolver) new PathMatchingResourcePatternResolver(); |
||||
MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(resolver); |
||||
List<String> allResult = new ArrayList<String>(); |
||||
try |
||||
{ |
||||
for (String aliasesPackage : typeAliasesPackage.split(",")) |
||||
{ |
||||
List<String> result = new ArrayList<String>(); |
||||
aliasesPackage = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX |
||||
+ ClassUtils.convertClassNameToResourcePath(aliasesPackage.trim()) + "/" + DEFAULT_RESOURCE_PATTERN; |
||||
Resource[] resources = resolver.getResources(aliasesPackage); |
||||
if (resources != null && resources.length > 0) |
||||
{ |
||||
MetadataReader metadataReader = null; |
||||
for (Resource resource : resources) |
||||
{ |
||||
if (resource.isReadable()) |
||||
{ |
||||
metadataReader = metadataReaderFactory.getMetadataReader(resource); |
||||
try |
||||
{ |
||||
result.add(Class.forName(metadataReader.getClassMetadata().getClassName()).getPackage().getName()); |
||||
} |
||||
catch (ClassNotFoundException e) |
||||
{ |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
if (result.size() > 0) |
||||
{ |
||||
HashSet<String> hashResult = new HashSet<String>(result); |
||||
allResult.addAll(hashResult); |
||||
} |
||||
} |
||||
if (allResult.size() > 0) |
||||
{ |
||||
typeAliasesPackage = String.join(",", (String[]) allResult.toArray(new String[0])); |
||||
} |
||||
else |
||||
{ |
||||
throw new RuntimeException("mybatis typeAliasesPackage 路径扫描错误,参数typeAliasesPackage:" + typeAliasesPackage + "未找到任何包"); |
||||
} |
||||
} |
||||
catch (IOException e) |
||||
{ |
||||
e.printStackTrace(); |
||||
} |
||||
return typeAliasesPackage; |
||||
} |
||||
|
||||
public Resource[] resolveMapperLocations(String[] mapperLocations) |
||||
{ |
||||
ResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver(); |
||||
List<Resource> resources = new ArrayList<Resource>(); |
||||
if (mapperLocations != null) |
||||
{ |
||||
for (String mapperLocation : mapperLocations) |
||||
{ |
||||
try |
||||
{ |
||||
Resource[] mappers = resourceResolver.getResources(mapperLocation); |
||||
resources.addAll(Arrays.asList(mappers)); |
||||
} |
||||
catch (IOException e) |
||||
{ |
||||
// ignore
|
||||
} |
||||
} |
||||
} |
||||
return resources.toArray(new Resource[resources.size()]); |
||||
} |
||||
|
||||
@Bean |
||||
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception |
||||
{ |
||||
String typeAliasesPackage = env.getProperty("mybatis.typeAliasesPackage"); |
||||
String mapperLocations = env.getProperty("mybatis.mapperLocations"); |
||||
String configLocation = env.getProperty("mybatis.configLocation"); |
||||
typeAliasesPackage = setTypeAliasesPackage(typeAliasesPackage); |
||||
VFS.addImplClass(SpringBootVFS.class); |
||||
|
||||
final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); |
||||
sessionFactory.setDataSource(dataSource); |
||||
sessionFactory.setTypeAliasesPackage(typeAliasesPackage); |
||||
sessionFactory.setMapperLocations(resolveMapperLocations(StringUtils.split(mapperLocations, ","))); |
||||
sessionFactory.setConfigLocation(new DefaultResourceLoader().getResource(configLocation)); |
||||
return sessionFactory.getObject(); |
||||
} |
||||
} |
@ -0,0 +1,62 @@
@@ -0,0 +1,62 @@
|
||||
package com.ruoyi.framework.config; |
||||
|
||||
import com.baomidou.mybatisplus.annotation.DbType; |
||||
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; |
||||
import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor; |
||||
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor; |
||||
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.transaction.annotation.EnableTransactionManagement; |
||||
|
||||
/** |
||||
* Mybatis Plus 配置 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
@EnableTransactionManagement(proxyTargetClass = true) |
||||
@Configuration |
||||
public class MybatisPlusConfig |
||||
{ |
||||
@Bean |
||||
public MybatisPlusInterceptor mybatisPlusInterceptor() |
||||
{ |
||||
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); |
||||
// 分页插件
|
||||
interceptor.addInnerInterceptor(paginationInnerInterceptor()); |
||||
// 乐观锁插件
|
||||
interceptor.addInnerInterceptor(optimisticLockerInnerInterceptor()); |
||||
// 阻断插件
|
||||
interceptor.addInnerInterceptor(blockAttackInnerInterceptor()); |
||||
return interceptor; |
||||
} |
||||
|
||||
/** |
||||
* 分页插件,自动识别数据库类型 https://baomidou.com/guide/interceptor-pagination.html
|
||||
*/ |
||||
public PaginationInnerInterceptor paginationInnerInterceptor() |
||||
{ |
||||
PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(); |
||||
// 设置数据库类型为mysql
|
||||
paginationInnerInterceptor.setDbType(DbType.MYSQL); |
||||
// 设置最大单页限制数量,默认 500 条,-1 不受限制
|
||||
paginationInnerInterceptor.setMaxLimit(-1L); |
||||
return paginationInnerInterceptor; |
||||
} |
||||
|
||||
/** |
||||
* 乐观锁插件 https://baomidou.com/guide/interceptor-optimistic-locker.html
|
||||
*/ |
||||
public OptimisticLockerInnerInterceptor optimisticLockerInnerInterceptor() |
||||
{ |
||||
return new OptimisticLockerInnerInterceptor(); |
||||
} |
||||
|
||||
/** |
||||
* 如果是对全表的删除或更新操作,就会终止该操作 https://baomidou.com/guide/interceptor-block-attack.html
|
||||
*/ |
||||
public BlockAttackInnerInterceptor blockAttackInnerInterceptor() |
||||
{ |
||||
return new BlockAttackInnerInterceptor(); |
||||
} |
||||
} |
Loading…
Reference in new issue