diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a2a3040 --- /dev/null +++ b/.gitignore @@ -0,0 +1,31 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/** +!**/src/test/** + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ + +### VS Code ### +.vscode/ diff --git a/.mvn/wrapper/MavenWrapperDownloader.java b/.mvn/wrapper/MavenWrapperDownloader.java new file mode 100644 index 0000000..2281075 --- /dev/null +++ b/.mvn/wrapper/MavenWrapperDownloader.java @@ -0,0 +1,117 @@ +/* + * Copyright 2012-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import java.net.*; +import java.io.*; +import java.nio.channels.*; +import java.util.Properties; + +public class MavenWrapperDownloader { + + private static final String WRAPPER_VERSION = "0.5.5"; + /** + * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. + */ + private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" + + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; + + /** + * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to + * use instead of the default one. + */ + private static final String MAVEN_WRAPPER_PROPERTIES_PATH = + ".mvn/wrapper/maven-wrapper.properties"; + + /** + * Path where the maven-wrapper.jar will be saved to. + */ + private static final String MAVEN_WRAPPER_JAR_PATH = + ".mvn/wrapper/maven-wrapper.jar"; + + /** + * Name of the property which should be used to override the default download url for the wrapper. + */ + private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; + + public static void main(String args[]) { + System.out.println("- Downloader started"); + File baseDirectory = new File(args[0]); + System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); + + // If the maven-wrapper.properties exists, read it and check if it contains a custom + // wrapperUrl parameter. + File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); + String url = DEFAULT_DOWNLOAD_URL; + if(mavenWrapperPropertyFile.exists()) { + FileInputStream mavenWrapperPropertyFileInputStream = null; + try { + mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); + Properties mavenWrapperProperties = new Properties(); + mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); + url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); + } catch (IOException e) { + System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); + } finally { + try { + if(mavenWrapperPropertyFileInputStream != null) { + mavenWrapperPropertyFileInputStream.close(); + } + } catch (IOException e) { + // Ignore ... + } + } + } + System.out.println("- Downloading from: " + url); + + File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); + if(!outputFile.getParentFile().exists()) { + if(!outputFile.getParentFile().mkdirs()) { + System.out.println( + "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); + } + } + System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); + try { + downloadFileFromURL(url, outputFile); + System.out.println("Done"); + System.exit(0); + } catch (Throwable e) { + System.out.println("- Error downloading"); + e.printStackTrace(); + System.exit(1); + } + } + + private static void downloadFileFromURL(String urlString, File destination) throws Exception { + if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { + String username = System.getenv("MVNW_USERNAME"); + char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); + Authenticator.setDefault(new Authenticator() { + @Override + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(username, password); + } + }); + } + URL website = new URL(urlString); + ReadableByteChannel rbc; + rbc = Channels.newChannel(website.openStream()); + FileOutputStream fos = new FileOutputStream(destination); + fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); + fos.close(); + rbc.close(); + } + +} diff --git a/.mvn/wrapper/maven-wrapper.jar b/.mvn/wrapper/maven-wrapper.jar new file mode 100644 index 0000000..0d5e649 Binary files /dev/null and b/.mvn/wrapper/maven-wrapper.jar differ diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..7d59a01 --- /dev/null +++ b/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,2 @@ +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.2/apache-maven-3.6.2-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..48e341a --- /dev/null +++ b/package-lock.json @@ -0,0 +1,3 @@ +{ + "lockfileVersion": 1 +} diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..e6c7724 --- /dev/null +++ b/pom.xml @@ -0,0 +1,137 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.2.2.RELEASE + + + com.jlwl + + house + 0.0.1-SNAPSHOT + springboot-schema + + + 1.8 + 1.2.8 + 3.1.1 + + + + + org.springframework.boot + spring-boot-starter-web + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + 2.1.1 + + + org.springframework.boot + spring-boot-starter-jdbc + + + + mysql + mysql-connector-java + + + org.apache.shiro + shiro-spring + 1.3.2 + + + + com.baomidou + mybatis-plus + 2.3 + + + com.baomidou + mybatisplus-spring-boot-starter + 1.0.5 + + + com.google.protobuf + protobuf-java + 3.10.0 + + + + org.apache.commons + commons-lang3 + 3.0 + + + + javax.validation + validation-api + 2.0.1.Final + + + + commons-io + commons-io + 2.5 + + + + + cn.hutool + hutool-all + 4.0.12 + + + + + com.alibaba + fastjson + ${fastjson.version} + + + com.microsoft.sqlserver + sqljdbc4 + 4.0 + 4.0 + + + + com.microsoft.sqlserver + mssql-jdbc + 6.2.0.jre8 + runtime + + + + com.baidu.aip + java-sdk + 4.4.1 + + + + org.springframework.boot + spring-boot-starter-test + test + + + org.junit.vintage + junit-vintage-engine + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/src/main/java/com/SpringbootSchemaApplication.java b/src/main/java/com/SpringbootSchemaApplication.java new file mode 100644 index 0000000..bc07f40 --- /dev/null +++ b/src/main/java/com/SpringbootSchemaApplication.java @@ -0,0 +1,21 @@ +package com; + +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; + +@SpringBootApplication +@MapperScan(basePackages = {"com.dao"}) +public class SpringbootSchemaApplication extends SpringBootServletInitializer{ + + public static void main(String[] args) { + SpringApplication.run(SpringbootSchemaApplication.class, args); + } + + @Override + protected SpringApplicationBuilder configure(SpringApplicationBuilder applicationBuilder) { + return applicationBuilder.sources(SpringbootSchemaApplication.class); + } +} diff --git a/src/main/java/com/annotation/APPLoginUser.java b/src/main/java/com/annotation/APPLoginUser.java new file mode 100644 index 0000000..21d41b9 --- /dev/null +++ b/src/main/java/com/annotation/APPLoginUser.java @@ -0,0 +1,15 @@ +package com.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 登录用户信息 + */ +@Target(ElementType.PARAMETER) +@Retention(RetentionPolicy.RUNTIME) +public @interface APPLoginUser { + +} diff --git a/src/main/java/com/annotation/IgnoreAuth.java b/src/main/java/com/annotation/IgnoreAuth.java new file mode 100644 index 0000000..7c3cc55 --- /dev/null +++ b/src/main/java/com/annotation/IgnoreAuth.java @@ -0,0 +1,13 @@ +package com.annotation; + +import java.lang.annotation.*; + +/** + * 忽略Token验证 + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface IgnoreAuth { + +} diff --git a/src/main/java/com/annotation/LoginUser.java b/src/main/java/com/annotation/LoginUser.java new file mode 100644 index 0000000..3d808d3 --- /dev/null +++ b/src/main/java/com/annotation/LoginUser.java @@ -0,0 +1,15 @@ +package com.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 登录用户信息 + */ +@Target(ElementType.PARAMETER) +@Retention(RetentionPolicy.RUNTIME) +public @interface LoginUser { + +} diff --git a/src/main/java/com/config/InterceptorConfig.java b/src/main/java/com/config/InterceptorConfig.java new file mode 100644 index 0000000..8cc94d2 --- /dev/null +++ b/src/main/java/com/config/InterceptorConfig.java @@ -0,0 +1,38 @@ +package com.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; + +import com.interceptor.AuthorizationInterceptor; + +@Configuration +public class InterceptorConfig extends WebMvcConfigurationSupport{ + + @Bean + public AuthorizationInterceptor getAuthorizationInterceptor() { + return new AuthorizationInterceptor(); + } + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(getAuthorizationInterceptor()).addPathPatterns("/**").excludePathPatterns("/static/**"); + super.addInterceptors(registry); + } + + /** + * springboot 2.0配置WebMvcConfigurationSupport之后,会导致默认配置被覆盖,要访问静态资源需要重写addResourceHandlers方法 + */ + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + registry.addResourceHandler("/**") + .addResourceLocations("classpath:/resources/") + .addResourceLocations("classpath:/static/") + .addResourceLocations("classpath:/admin/") + .addResourceLocations("classpath:/front/") + .addResourceLocations("classpath:/public/"); + super.addResourceHandlers(registry); + } +} diff --git a/src/main/java/com/config/MybatisPlusConfig.java b/src/main/java/com/config/MybatisPlusConfig.java new file mode 100644 index 0000000..ec2e84b --- /dev/null +++ b/src/main/java/com/config/MybatisPlusConfig.java @@ -0,0 +1,24 @@ + +package com.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import com.baomidou.mybatisplus.mapper.MetaObjectHandler; +import com.baomidou.mybatisplus.plugins.PaginationInterceptor; + +/** + * mybatis-plus配置 + */ +@Configuration +public class MybatisPlusConfig { + + /** + * 分页插件 + */ + @Bean + public PaginationInterceptor paginationInterceptor() { + return new PaginationInterceptor(); + } + +} diff --git a/src/main/java/com/interceptor/AuthorizationInterceptor.java b/src/main/java/com/interceptor/AuthorizationInterceptor.java new file mode 100644 index 0000000..74b5ebd --- /dev/null +++ b/src/main/java/com/interceptor/AuthorizationInterceptor.java @@ -0,0 +1,95 @@ +package com.interceptor; + +import java.io.IOException; +import java.io.PrintWriter; +import java.util.HashMap; +import java.util.Map; +import com.alibaba.fastjson.JSONObject; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.HandlerInterceptor; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.http.HttpStatus; + +import com.annotation.IgnoreAuth; +import com.entity.EIException; +import com.entity.TokenEntity; +import com.service.TokenService; +import com.utils.R; + +/** + * 权限(Token)验证 + */ +@Component +public class AuthorizationInterceptor implements HandlerInterceptor { + + public static final String LOGIN_TOKEN_KEY = "Token"; + + @Autowired + private TokenService tokenService; + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + + //支持跨域请求 + response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE"); + response.setHeader("Access-Control-Max-Age", "3600"); + response.setHeader("Access-Control-Allow-Credentials", "true"); + response.setHeader("Access-Control-Allow-Headers", "x-requested-with,request-source,Token, Origin,imgType, Content-Type, cache-control,postman-token,Cookie, Accept,authorization"); + response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin")); + // 跨域时会首先发送一个OPTIONS请求,这里我们给OPTIONS请求直接返回正常状态 + if (request.getMethod().equals(RequestMethod.OPTIONS.name())) { + response.setStatus(HttpStatus.OK.value()); + return false; + } + + IgnoreAuth annotation; + if (handler instanceof HandlerMethod) { + annotation = ((HandlerMethod) handler).getMethodAnnotation(IgnoreAuth.class); + } else { + return true; + } + + //从header中获取token + String token = request.getHeader(LOGIN_TOKEN_KEY); + + /** + * 不需要验证权限的方法直接放过 + */ + if(annotation!=null) { + return true; + } + + TokenEntity tokenEntity = null; + if(StringUtils.isNotBlank(token)) { + tokenEntity = tokenService.getTokenEntity(token); + } + + if(tokenEntity != null) { + request.getSession().setAttribute("userId", tokenEntity.getUserid()); + request.getSession().setAttribute("role", tokenEntity.getRole()); + request.getSession().setAttribute("tableName", tokenEntity.getTablename()); + request.getSession().setAttribute("username", tokenEntity.getUsername()); + return true; + } + + PrintWriter writer = null; + response.setCharacterEncoding("UTF-8"); + response.setContentType("application/json; charset=utf-8"); + try { + writer = response.getWriter(); + writer.print(JSONObject.toJSONString(R.error(401, "请先登录"))); + } finally { + if(writer != null){ + writer.close(); + } + } +// throw new EIException("请先登录", 401); + return false; + } +} diff --git a/src/main/java/com/utils/BaiduUtil.java b/src/main/java/com/utils/BaiduUtil.java new file mode 100644 index 0000000..3c4e0ae --- /dev/null +++ b/src/main/java/com/utils/BaiduUtil.java @@ -0,0 +1,96 @@ +package com.utils; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.json.JSONObject; + + +/** +* 类说明 : +*/ + +public class BaiduUtil { + + /** + * 根据经纬度获得省市区信息 + * @param lon 纬度 + * @param lat 经度 + * @param coordtype 经纬度坐标系 + * @return + */ + public static Map getCityByLonLat(String key, String lng, String lat) { + String location = lat + "," + lng; + try { + //拼装url + String url = "http://api.map.baidu.com/reverse_geocoding/v3/?ak="+key+"&output=json&coordtype=wgs84ll&location="+location; + String result = HttpClientUtils.doGet(url); + JSONObject o = new JSONObject(result); + Map area = new HashMap<>(); + area.put("province", o.getJSONObject("result").getJSONObject("addressComponent").getString("province")); + area.put("city", o.getJSONObject("result").getJSONObject("addressComponent").getString("city")); + area.put("district", o.getJSONObject("result").getJSONObject("addressComponent").getString("district")); + area.put("street", o.getJSONObject("result").getJSONObject("addressComponent").getString("street")); + return area; + }catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + /** + * 获取API访问token + * 该token有一定的有效期,需要自行管理,当失效时需重新获取. + * @param ak - 百度云官网获取的 API Key + * @param sk - 百度云官网获取的 Securet Key + * @return assess_token + */ + public static String getAuth(String ak, String sk) { + // 获取token地址 + String authHost = "https://aip.baidubce.com/oauth/2.0/token?"; + String getAccessTokenUrl = authHost + // 1. grant_type为固定参数 + + "grant_type=client_credentials" + // 2. 官网获取的 API Key + + "&client_id=" + ak + // 3. 官网获取的 Secret Key + + "&client_secret=" + sk; + try { + URL realUrl = new URL(getAccessTokenUrl); + // 打开和URL之间的连接 + HttpURLConnection connection = (HttpURLConnection) realUrl.openConnection(); + connection.setRequestMethod("GET"); + connection.connect(); + // 获取所有响应头字段 + Map> map = connection.getHeaderFields(); + // 遍历所有的响应头字段 + for (String key : map.keySet()) { + System.err.println(key + "--->" + map.get(key)); + } + // 定义 BufferedReader输入流来读取URL的响应 + BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream())); + String result = ""; + String line; + while ((line = in.readLine()) != null) { + result += line; + } + /** + * 返回结果示例 + */ + System.err.println("result:" + result); + org.json.JSONObject jsonObject = new org.json.JSONObject(result); + String access_token = jsonObject.getString("access_token"); + return access_token; + } catch (Exception e) { + System.err.printf("获取token失败!"); + e.printStackTrace(System.err); + } + return null; + } + +} diff --git a/src/main/java/com/utils/CommonUtil.java b/src/main/java/com/utils/CommonUtil.java new file mode 100644 index 0000000..18f7509 --- /dev/null +++ b/src/main/java/com/utils/CommonUtil.java @@ -0,0 +1,22 @@ +package com.utils; + +import java.util.Random; + +public class CommonUtil { + /** + * 获取随机字符串 + * + * @param num + * @return + */ + public static String getRandomString(Integer num) { + String base = "abcdefghijklmnopqrstuvwxyz0123456789"; + Random random = new Random(); + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < num; i++) { + int number = random.nextInt(base.length()); + sb.append(base.charAt(number)); + } + return sb.toString(); + } +} diff --git a/src/main/java/com/utils/FileUtil.java b/src/main/java/com/utils/FileUtil.java new file mode 100644 index 0000000..d581324 --- /dev/null +++ b/src/main/java/com/utils/FileUtil.java @@ -0,0 +1,27 @@ +package com.utils; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; + +/** +* 类说明 : +*/ + +public class FileUtil { + public static byte[] FileToByte(File file) throws IOException { + // 将数据转为流 + @SuppressWarnings("resource") + InputStream content = new FileInputStream(file); + ByteArrayOutputStream swapStream = new ByteArrayOutputStream(); + byte[] buff = new byte[100]; + int rc = 0; + while ((rc = content.read(buff, 0, 100)) > 0) { + swapStream.write(buff, 0, rc); + } + // 获得二进制数组 + return swapStream.toByteArray(); + } +} diff --git a/src/main/java/com/utils/HttpClientUtils.java b/src/main/java/com/utils/HttpClientUtils.java new file mode 100644 index 0000000..fd6aae5 --- /dev/null +++ b/src/main/java/com/utils/HttpClientUtils.java @@ -0,0 +1,42 @@ +package com.utils; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; + + +/** + * HttpClient工具类 + */ +public class HttpClientUtils { + + /** + * @param uri + * @return String + * @description get请求方式 + * @author: long.he01 + */ + public static String doGet(String uri) { + + StringBuilder result = new StringBuilder(); + try { + String res = ""; + URL url = new URL(uri); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8")); + String line; + while ((line = in.readLine()) != null) { + res += line+"\n"; + } + in.close(); + return res; + }catch (Exception e) { + e.printStackTrace(); + return null; + } + + } + +} + diff --git a/src/main/java/com/utils/JQPageInfo.java b/src/main/java/com/utils/JQPageInfo.java new file mode 100644 index 0000000..af075a4 --- /dev/null +++ b/src/main/java/com/utils/JQPageInfo.java @@ -0,0 +1,54 @@ +package com.utils; + +public class JQPageInfo{ + private Integer page; + + private Integer limit; + + private String sidx; + + private String order; + + private Integer offset; + + public Integer getPage() { + return page; + } + + public void setPage(Integer page) { + this.page = page; + } + + public Integer getLimit() { + return limit; + } + + public void setLimit(Integer limit) { + this.limit = limit; + } + + public String getSidx() { + return sidx; + } + + public void setSidx(String sidx) { + this.sidx = sidx; + } + + public String getOrder() { + return order; + } + + public void setOrder(String order) { + this.order = order; + } + + public Integer getOffset() { + return offset; + } + + public void setOffset(Integer offset) { + this.offset = offset; + } + +} diff --git a/src/main/java/com/utils/MD5Util.java b/src/main/java/com/utils/MD5Util.java new file mode 100644 index 0000000..358a4b1 --- /dev/null +++ b/src/main/java/com/utils/MD5Util.java @@ -0,0 +1,19 @@ +package com.utils; + +import cn.hutool.crypto.digest.DigestUtil; + +public class MD5Util { + + /** + * @param text明文 + * @param key密钥 + * @return 密文 + */ + // 带秘钥加密 + public static String md5(String text) { + // 加密后的字符串 + String md5str = DigestUtil.md5Hex(text); + return md5str; + } + +} diff --git a/src/main/java/com/utils/MPUtil.java b/src/main/java/com/utils/MPUtil.java new file mode 100644 index 0000000..e5d3916 --- /dev/null +++ b/src/main/java/com/utils/MPUtil.java @@ -0,0 +1,184 @@ +package com.utils; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import org.apache.commons.lang3.StringUtils; + +import cn.hutool.core.bean.BeanUtil; + +import com.baomidou.mybatisplus.mapper.Wrapper; + +/** + * Mybatis-Plus工具类 + */ +public class MPUtil { + public static final char UNDERLINE = '_'; + + + //mybatis plus allEQ 表达式转换 + public static Map allEQMapPre(Object bean,String pre) { + Map map =BeanUtil.beanToMap(bean); + return camelToUnderlineMap(map,pre); + } + + //mybatis plus allEQ 表达式转换 + public static Map allEQMap(Object bean) { + Map map =BeanUtil.beanToMap(bean); + return camelToUnderlineMap(map,""); + } + + public static Wrapper allLikePre(Wrapper wrapper,Object bean,String pre) { + Map map =BeanUtil.beanToMap(bean); + Map result = camelToUnderlineMap(map,pre); + + return genLike(wrapper,result); + } + + public static Wrapper allLike(Wrapper wrapper,Object bean) { + Map result = BeanUtil.beanToMap(bean, true, true); + return genLike(wrapper,result); + } + + + public static Wrapper genLike( Wrapper wrapper,Map param) { + Iterator> it = param.entrySet().iterator(); + int i=0; + while (it.hasNext()) { + if(i>0) wrapper.and(); + Map.Entry entry = it.next(); + String key = entry.getKey(); + String value = (String) entry.getValue(); + wrapper.like(key, value); + i++; + } + return wrapper; + } + + public static Wrapper likeOrEq(Wrapper wrapper,Object bean) { + Map result = BeanUtil.beanToMap(bean, true, true); + return genLikeOrEq(wrapper,result); + } + + public static Wrapper genLikeOrEq( Wrapper wrapper,Map param) { + Iterator> it = param.entrySet().iterator(); + int i=0; + while (it.hasNext()) { + if(i>0) wrapper.and(); + Map.Entry entry = it.next(); + String key = entry.getKey(); + if(entry.getValue().toString().contains("%")) { + wrapper.like(key, entry.getValue().toString().replace("%", "")); + } else { + wrapper.eq(key, entry.getValue()); + } + i++; + } + return wrapper; + } + + public static Wrapper allEq(Wrapper wrapper,Object bean) { + Map result = BeanUtil.beanToMap(bean, true, true); + return genEq(wrapper,result); + } + + + public static Wrapper genEq( Wrapper wrapper,Map param) { + Iterator> it = param.entrySet().iterator(); + int i=0; + while (it.hasNext()) { + if(i>0) wrapper.and(); + Map.Entry entry = it.next(); + String key = entry.getKey(); + wrapper.eq(key, entry.getValue()); + i++; + } + return wrapper; + } + + + public static Wrapper between(Wrapper wrapper,Map params) { + for(String key : params.keySet()) { + String columnName = ""; + if(key.endsWith("_start")) { + columnName = key.substring(0, key.indexOf("_start")); + if(StringUtils.isNotBlank(params.get(key).toString())) { + wrapper.ge(columnName, params.get(key)); + } + } + if(key.endsWith("_end")) { + columnName = key.substring(0, key.indexOf("_end")); + if(StringUtils.isNotBlank(params.get(key).toString())) { + wrapper.le(columnName, params.get(key)); + } + } + } + return wrapper; + } + + public static Wrapper sort(Wrapper wrapper,Map params) { + String order = ""; + if(params.get("order") != null && StringUtils.isNotBlank(params.get("order").toString())) { + order = params.get("order").toString(); + } + if(params.get("sort") != null && StringUtils.isNotBlank(params.get("sort").toString())) { + if(order.equalsIgnoreCase("desc")) { + wrapper.orderDesc(Arrays.asList(params.get("sort"))); + } else { + wrapper.orderAsc(Arrays.asList(params.get("sort"))); + } + } + return wrapper; + } + + + /** + * 驼峰格式字符串转换为下划线格式字符串 + * + * @param param + * @return + */ + public static String camelToUnderline(String param) { + if (param == null || "".equals(param.trim())) { + return ""; + } + int len = param.length(); + StringBuilder sb = new StringBuilder(len); + for (int i = 0; i < len; i++) { + char c = param.charAt(i); + if (Character.isUpperCase(c)) { + sb.append(UNDERLINE); + sb.append(Character.toLowerCase(c)); + } else { + sb.append(c); + } + } + return sb.toString(); + } + + public static void main(String[] ages) { + System.out.println(camelToUnderline("ABCddfANM")); + } + + public static Map camelToUnderlineMap(Map param, String pre) { + + Map newMap = new HashMap(); + Iterator> it = param.entrySet().iterator(); + while (it.hasNext()) { + Map.Entry entry = it.next(); + String key = entry.getKey(); + String newKey = camelToUnderline(key); + if (pre.endsWith(".")) { + newMap.put(pre + newKey, entry.getValue()); + } else if (StringUtils.isEmpty(pre)) { + newMap.put(newKey, entry.getValue()); + } else { + + newMap.put(pre + "." + newKey, entry.getValue()); + } + } + return newMap; + } +} diff --git a/src/main/java/com/utils/PageUtils.java b/src/main/java/com/utils/PageUtils.java new file mode 100644 index 0000000..f7356bf --- /dev/null +++ b/src/main/java/com/utils/PageUtils.java @@ -0,0 +1,101 @@ + +package com.utils; + +import java.io.Serializable; +import java.util.List; +import java.util.Map; + +import com.baomidou.mybatisplus.plugins.Page; + +/** + * 分页工具类 + */ +public class PageUtils implements Serializable { + private static final long serialVersionUID = 1L; + //总记录数 + private long total; + //每页记录数 + private int pageSize; + //总页数 + private long totalPage; + //当前页数 + private int currPage; + //列表数据 + private List list; + + /** + * 分页 + * @param list 列表数据 + * @param totalCount 总记录数 + * @param pageSize 每页记录数 + * @param currPage 当前页数 + */ + public PageUtils(List list, int totalCount, int pageSize, int currPage) { + this.list = list; + this.total = totalCount; + this.pageSize = pageSize; + this.currPage = currPage; + this.totalPage = (int)Math.ceil((double)totalCount/pageSize); + } + + /** + * 分页 + */ + public PageUtils(Page page) { + this.list = page.getRecords(); + this.total = page.getTotal(); + this.pageSize = page.getSize(); + this.currPage = page.getCurrent(); + this.totalPage = page.getPages(); + } + + /* + * 空数据的分页 + */ + public PageUtils(Map params) { + Page page =new Query(params).getPage(); + new PageUtils(page); + } + + + public int getPageSize() { + return pageSize; + } + + public void setPageSize(int pageSize) { + this.pageSize = pageSize; + } + + public int getCurrPage() { + return currPage; + } + + public void setCurrPage(int currPage) { + this.currPage = currPage; + } + + public List getList() { + return list; + } + + public void setList(List list) { + this.list = list; + } + + public long getTotalPage() { + return totalPage; + } + + public void setTotalPage(long totalPage) { + this.totalPage = totalPage; + } + + public long getTotal() { + return total; + } + + public void setTotal(long total) { + this.total = total; + } + +} diff --git a/src/main/java/com/utils/Query.java b/src/main/java/com/utils/Query.java new file mode 100644 index 0000000..eb624a7 --- /dev/null +++ b/src/main/java/com/utils/Query.java @@ -0,0 +1,98 @@ + +package com.utils; + +import java.util.LinkedHashMap; +import java.util.Map; + +import org.apache.commons.lang3.StringUtils; + +import com.baomidou.mybatisplus.plugins.Page; + +/** + * 查询参数 + */ +public class Query extends LinkedHashMap { + private static final long serialVersionUID = 1L; + /** + * mybatis-plus分页参数 + */ + private Page page; + /** + * 当前页码 + */ + private int currPage = 1; + /** + * 每页条数 + */ + private int limit = 10; + + public Query(JQPageInfo pageInfo) { + //分页参数 + if(pageInfo.getPage()!= null){ + currPage = pageInfo.getPage(); + } + if(pageInfo.getLimit()!= null){ + limit = pageInfo.getLimit(); + } + + + //防止SQL注入(因为sidx、order是通过拼接SQL实现排序的,会有SQL注入风险) + String sidx = SQLFilter.sqlInject(pageInfo.getSidx()); + String order = SQLFilter.sqlInject(pageInfo.getOrder()); + + + //mybatis-plus分页 + this.page = new Page<>(currPage, limit); + + //排序 + if(StringUtils.isNotBlank(sidx) && StringUtils.isNotBlank(order)){ + this.page.setOrderByField(sidx); + this.page.setAsc("ASC".equalsIgnoreCase(order)); + } + } + + + public Query(Map params){ + this.putAll(params); + + //分页参数 + if(params.get("page") != null){ + currPage = Integer.parseInt((String)params.get("page")); + } + if(params.get("limit") != null){ + limit = Integer.parseInt((String)params.get("limit")); + } + + this.put("offset", (currPage - 1) * limit); + this.put("page", currPage); + this.put("limit", limit); + + //防止SQL注入(因为sidx、order是通过拼接SQL实现排序的,会有SQL注入风险) + String sidx = SQLFilter.sqlInject((String)params.get("sidx")); + String order = SQLFilter.sqlInject((String)params.get("order")); + this.put("sidx", sidx); + this.put("order", order); + + //mybatis-plus分页 + this.page = new Page<>(currPage, limit); + + //排序 + if(StringUtils.isNotBlank(sidx) && StringUtils.isNotBlank(order)){ + this.page.setOrderByField(sidx); + this.page.setAsc("ASC".equalsIgnoreCase(order)); + } + + } + + public Page getPage() { + return page; + } + + public int getCurrPage() { + return currPage; + } + + public int getLimit() { + return limit; + } +} diff --git a/src/main/java/com/utils/R.java b/src/main/java/com/utils/R.java new file mode 100644 index 0000000..680b3f8 --- /dev/null +++ b/src/main/java/com/utils/R.java @@ -0,0 +1,51 @@ +package com.utils; + +import java.util.HashMap; +import java.util.Map; + +/** + * 返回数据 + */ +public class R extends HashMap { + private static final long serialVersionUID = 1L; + + public R() { + put("code", 0); + } + + 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 map) { + R r = new R(); + r.putAll(map); + return r; + } + + public static R ok() { + return new R(); + } + + public R put(String key, Object value) { + super.put(key, value); + return this; + } +} diff --git a/src/main/java/com/utils/SQLFilter.java b/src/main/java/com/utils/SQLFilter.java new file mode 100644 index 0000000..f6ce05d --- /dev/null +++ b/src/main/java/com/utils/SQLFilter.java @@ -0,0 +1,42 @@ + +package com.utils; + +import org.apache.commons.lang3.StringUtils; + +import com.entity.EIException; + +/** + * SQL过滤 + */ +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 EIException("包含非法字符"); + } + } + + return str; + } +} diff --git a/src/main/java/com/utils/SpringContextUtils.java b/src/main/java/com/utils/SpringContextUtils.java new file mode 100644 index 0000000..fd3705b --- /dev/null +++ b/src/main/java/com/utils/SpringContextUtils.java @@ -0,0 +1,43 @@ + +package com.utils; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + + +/** + * Spring Context 工具类 + */ +@Component +public class SpringContextUtils implements ApplicationContextAware { + public static ApplicationContext applicationContext; + + @Override + public void setApplicationContext(ApplicationContext applicationContext) + throws BeansException { + SpringContextUtils.applicationContext = applicationContext; + } + + public static Object getBean(String name) { + return applicationContext.getBean(name); + } + + public static T getBean(String name, Class requiredType) { + return applicationContext.getBean(name, requiredType); + } + + public static boolean containsBean(String name) { + return applicationContext.containsBean(name); + } + + public static boolean isSingleton(String name) { + return applicationContext.isSingleton(name); + } + + public static Class getType(String name) { + return applicationContext.getType(name); + } + +} \ No newline at end of file diff --git a/src/main/java/com/utils/ValidatorUtils.java b/src/main/java/com/utils/ValidatorUtils.java new file mode 100644 index 0000000..06ed26c --- /dev/null +++ b/src/main/java/com/utils/ValidatorUtils.java @@ -0,0 +1,39 @@ + +package com.utils; + + +import java.util.Set; + +import javax.validation.ConstraintViolation; +import javax.validation.Validation; +import javax.validation.Validator; + +import com.entity.EIException; + +/** + * hibernate-validator校验工具类 + */ +public class ValidatorUtils { + private static Validator validator; + + static { + validator = Validation.buildDefaultValidatorFactory().getValidator(); + } + + /** + * 校验对象 + * @param object 待校验对象 + * @param groups 待校验的组 + * @throws EIException 校验不通过,则报EIException异常 + */ + public static void validateEntity(Object object, Class... groups) + throws EIException { + Set> constraintViolations = validator.validate(object, groups); + if (!constraintViolations.isEmpty()) { + ConstraintViolation constraint = (ConstraintViolation)constraintViolations.iterator().next(); + throw new EIException(constraint.getMessage()); + } + } + + +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000..b01dc47 --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,49 @@ +# Tomcat +server: + tomcat: + uri-encoding: UTF-8 + port: 8080 + servlet: + context-path: /house + +spring: + datasource: + driverClassName: com.mysql.jdbc.Driver + url: jdbc:mysql://127.0.0.1:3306/house?useUnicode=true&characterEncoding=utf-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8 + username: root + password: 123456 + + + + servlet: + multipart: + max-file-size: 10MB + max-request-size: 10MB + resources: + static-locations: classpath:static/,file:static/ + +#mybatis +mybatis-plus: + mapper-locations: classpath*:mapper/*.xml + #实体扫描,多个package用逗号或者分号分隔 + typeAliasesPackage: com.entity + global-config: + #主键类型 0:"数据库ID自增", 1:"用户输入ID",2:"全局唯一ID (数字类型唯一ID)", 3:"全局唯一ID UUID"; + id-type: 1 + #字段策略 0:"忽略判断",1:"非 NULL 判断"),2:"非空判断" + field-strategy: 2 + #驼峰下划线转换 + db-column-underline: true + #刷新mapper 调试神器 + refresh-mapper: true + #逻辑删除配置 + logic-delete-value: -1 + logic-not-delete-value: 0 + #自定义SQL注入器 + sql-injector: com.baomidou.mybatisplus.mapper.LogicSqlInjector + configuration: + map-underscore-to-camel-case: true + cache-enabled: false + call-setters-on-nulls: true + #springboot 项目mybatis plus 设置 jdbcTypeForNull (oracle数据库需配置JdbcType.NULL, 默认是Other) + jdbc-type-for-null: 'null' diff --git a/src/test/java/com/SpringbootSchemaApplicationTests.java b/src/test/java/com/SpringbootSchemaApplicationTests.java new file mode 100644 index 0000000..b3880f4 --- /dev/null +++ b/src/test/java/com/SpringbootSchemaApplicationTests.java @@ -0,0 +1,13 @@ +package com; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class SpringbootSchemaApplicationTests { + + @Test + void contextLoads() { + } + +}