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