決策樹——非正常企業預測
阿新 • • 發佈:2021-10-22
springboot總結
1、配置檔案application.properties載入順序和優先順序
- 優先順序:高 -> 低
- ./config/
- ./
- classpath:/config/
- classpath:
所有的檔案都會被載入,載入配置檔案的順序從低優先順序到高優先順序,高優先順序的內容會覆蓋低優先順序的內容,形成互補配置。
- 常用配置
#Logger配置 logging.level.com.xxx= info logging.file.path=./log #資料庫配置 spring.datasource.url=jdbc:mysql://localhost:3306/db?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai spring.datasource.username=xxx spring.datasource.password=xxxxxx spring.datasource.type=com.alibaba.druid.pool.DruidDataSource #mybatis配置 mybatis.mapper-locations=classpath:mapper/*.xml ##開啟駝峰命名 mybatis.global-config.column-underline=true mybatis.configuration.map-underscore-to-camel-case=true #控制檯列印sql語句 mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl #上傳檔案大小限制 ##單個檔案大小 spring.servlet.multipart.max-file-size=100MB ##總上傳資料大小 spring.servlet.multipart.max-request-size=100MB
2、專案啟動時初始化資源:CommandLineRunner或ApplicationRunner
@Component//標識為Bean @Order(1)//如果有多個runner可以指定一些順序 public class InitRunner implements ApplicationRunner { I @Autowired private ConfigurableApplicationContext applicationContext; @Override public void run(ApplicationArguments args) { //初始化邏輯程式碼 //初始化失敗時停止啟動 applicationContext.close(); } }
3、static變數使用@Value從配置檔案取值
server.seckey=turtledove
server.maps={key1:'value1', key2:'value2', key3:'value3'}
@Component public class Host { public static String SECKEY; public static Map<String, String> xxxMap = new HashMap<>(); @Value("${server.seckey}") public void setSeckey(String seckey) { SECKEY = seckey; } @Value("#{${server.maps}}") public void setUrlMap(Map<String, String> urlMap) { Host.urlMap = urlMap; } }
4、multipartFile.transferTo()路徑問題
分析下面原始碼,multipartFile.transferTo()首先會執行一個write方法,這個write方法會判斷傳入引數的路徑是否是相對路徑,如果是相對路徑,則把它拼接成絕對路徑。
- 原始碼
public class StandardMultipartHttpServletRequest extends AbstractMultipartHttpServletRequest {
public void transferTo(File dest) throws IOException, IllegalStateException {
this.part.write(dest.getPath());
if (dest.isAbsolute() && !dest.exists()) {
FileCopyUtils.copy(this.part.getInputStream(), Files.newOutputStream(dest.toPath()));
}
}
}
public class ApplicationPart implements Part {
public void write(String fileName) throws IOException {
File file = new File(fileName);
if (!file.isAbsolute()) {
file = new File(this.location, fileName);
}
try {
this.fileItem.write(file);
} catch (Exception var4) {
throw new IOException(var4);
}
}
}
- 使用
//相對路徑
multipartFile.transferTo(new File("./xxx/xxx"));
//絕對路徑
//因為windows的絕對路徑以碟符開始如"C:/xxx/xxx",linux的絕對路徑以斜槓開始如"/xxx/xxx",為避免服務從windows環境部署到linux環境時出問題,推薦使用第三種
multipartFile.transferTo(new File("C:/xxx/xxx"));//windows
multipartFile.transferTo(new File("/xxx/xxx"));//linux
multipartFile.transferTo(new File("./xxx/xxx").getAbsoluteFile());//推薦
5、Interceptor 用法
- 自定義攔截器
@Component
public class CheckUserTokenInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return HandlerInterceptor.super.preHandle(request, response, handler);
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
}
- 配置攔截器
@Configuration
public class WebConfigurer implements WebMvcConfigurer {
@Autowired
private CheckUserTokenInterceptor checkUserTokenInterceptor;
@Autowired
private XxxInterceptor xxxInterceptor;
/**
* 註冊攔截器
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(checkUserTokenInterceptor).addPathPatterns("/xxx/**").addPathPatterns("/xxx/**");
registry.addInterceptor(xxxInterceptor).addPathPatterns("/xxx/**").addPathPatterns("/xxx/**");
}
}
- 自定義返回
/**
* 自定義響應資料
*/
public void setResponseBody(HttpServletResponse response, Result result) {
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json");
try (PrintWriter responseWriter = response.getWriter()) {
responseWriter.print(JSON.toJSONString(result));
} catch (IOException e) {
log.error("response.getWriter()異常", e);
}
}
6、服務呼叫指令碼Runtime.getRuntime().exec(cmdString);
- 不成熟demo
public static boolean exec(String command) throws IOException, InterruptedException {
//執行指令碼
Process exec = Runtime.getRuntime().exec(command);
AtomicBoolean error = new AtomicBoolean(false);
//新建執行緒記錄錯誤資訊,避免阻塞記錄
new Thread(() -> {
BufferedReader errorReader = new BufferedReader(new InputStreamReader(exec.getErrorStream()));
errorReader.lines().forEach(line -> {
log.debug("bash error: {}", line);
error.set(true);
});
}).start();
//記錄一般資訊
BufferedReader infoReader = new BufferedReader(new InputStreamReader(exec.getInputStream()));
String line;
while ((line = infoReader.readLine()) != null) {
log.debug("bash info: {}", line);
}
exec.waitFor();
return exec.exitValue() == 0 && !error.get();
}
7、註解+AOP
-
@Aspect
-
@Pointcut:宣告一個切入點
匹配service中所有方法:@Pointcut("execution(* com.example.demo.service.*(..))")
第一個
*
代表任意修飾符及任意返回值型別,第二個*
代表任意方法,..
匹配任意數量任意型別的引數,若目標類與該切面在同一個包中,可以省略包名。例如:
//匹配XxxServiceImpl類中的所有公有方法 @Pointcut("execution public * com.example.demo.service.XxxService.*(..)") //匹配XxxServiceImpl類中返回值型別為double型別的所有公有方法 @Pointcut("execution public double com.example.demo.service.XxxService.*(..)") //匹配XxxServiceImpl類中第一個引數為double型別,後面不管有無引數的所有公有方法,並且該方法的返回值型別為double型別 @Pointcut("execution public double com.example.demo.service.XxxService.*(double, ..)") //匹配XxxServiceImpl類中引數型別為double,double型別的,並且返回值型別也為double型別的所有公有方法 @Pointcut("execution public double com.example.demo.service.XxxService.*(double, double)")s
-
@Around:環繞;@Before:前置
-
用例:
- 定義一個註解
package com.example.demo.common.aspectj; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface Log { String value() default ""; }
- 配置切入點
@Aspect @Service public class LogAspect { @Pointcut("@annotation(com.example.demo.common.aspectj.Log)") public void pointCut() { } @Around("pointCut()") public Object around(ProceedingJoinPoint proceedingJoinPoint) { //前置邏輯 Object obj = proceedingJoinPoint.proceed() //後置邏輯 return obj; } }
- 在需要切入的地方加上註解@Log即可切入
8、MD5
-
檔案校驗
String md5_1 DigestUtils.md5DigestAsHex(new FileInputStream(path1)); String md5_2 DigestUtils.md5DigestAsHex(new FileInputStream(path2)); if (md5_1.equals(md5_2)){ System.out.println("兩檔案相同"); }else { System.out.println("兩檔案不同"); }
-
密碼校驗
9、執行緒鎖Lock lock = new ReentrantLock()
10、 Fastjson
-
demo
//JSON.toJSONString(object) 將 object 轉換換為 JSON 物件 //JSON.parseObject() 將 JSON 字串轉換為 Java 物件 Person person = new Person(20, "turtledove", new Date()); String jsonString = JSON.toJSONString(person); Person newPerson = JSON.parseObject(jsonString, Person.class); //JSONArray JSONObject data = jsonObject.getJSONArray("data").getJSONObject(0);
11、Apache HttpClient
-
demo
public static JSONObject postRequest(Object requestParams, String url) throws IOException { //請求引數json格式化 String paramsJson = JSON.toJSONString(requestParams); //請求配置 CloseableHttpClient httpClient = HttpClientBuilder.create().build(); HttpPost httpPost = new HttpPost(url); httpPost.setEntity(new StringEntity(JSON.toJSONString(requestParams), "utf-8")); httpPost.setConfig(RequestConfig.custom().setConnectTimeout(2000).setSocketTimeout(2000).build()); //執行請求 CloseableHttpResponse httpResponse = httpClient.execute(httpPost); //響應結果json格式化 return JSONObject.parseObject(EntityUtils.toString(httpResponse.getEntity())); }
12、SQL注入
-
攻擊例項
<select id="getUserLoginInfo" resultType="map"> SELECT `username`, `password` FROM `user_table` WHERE `username` = ${username} AND `password` = ${password} </select>
-- 正常情況下 SELECT `username`, `password` FROM `user_table` WHERE `username` = 'username' AND `password` = 'password'; -- sql注入1:當 username = "' or 1 = 1 -- " SELECT `username`, `password` FROM `user_table` WHERE `username` = '' or 1 = 1 -- ' AND `password` = 'password'; -- sql注入2:當 username = "'; DROP DATABASE (DB Name) -- " SELECT `username`, `password` FROM `user_table` WHERE `username` = ''; DROP DATABASE (DB Name) -- ' AND `password` = 'password';
-
分析SQL語句: --條件後面username=”or 1=1 使用者名稱等於 ” 或1=1 那麼這個條件一定會成功; --然後後面加兩個-,這意味著註釋,它將後面的語句註釋,讓他們不起作用,這樣語句永遠都--能正確執行,使用者輕易騙過系統,獲取合法身份。
-
分析SQL
-
條件後面username=”or 1=1 使用者名稱等於 ” 或1=1 那麼這個條件一定會成功;
-
然後後面加兩個-,這意味著註釋,它將後面的語句註釋,讓他們不起作用,這樣語句永遠都--能正確執行,使用者輕易騙過系統,獲取合法身份。
-
-
預防sql注入(mybatis)ti
- 使用預編譯語句:即儘量使用#{value}。
若不得不使用“${xxx}”這樣的引數,要手工地做好過濾工作,來防止SQL注入攻擊。
-
過濾特殊符號:對於無法確定固定格式的變數,一定要進行特殊符號過濾或轉義處理。
-
一次只執行一條sql語句:mybatis jdbc 預設 allowMultiQueries=false,非必要不修改。
-
使用特定的使用者賬號,許可權限制住。不要使用root使用者。
13、Mybatis 動態SQL
-
where、if
<select id="findActiveBlogLike" resultType="Blog"> SELECT * FROM BLOG <where> <if test="author != null and author.name != null"> AND author_name like #{author.name} </if> </where> </select>
-
foreach
<foreach item="item" index="index" collection="list" open="(" separator="," close=")"> #{item} </foreach>
-
choose、when、otherwise
<select id="findActiveBlogLike" resultType="Blog"> SELECT * FROM BLOG WHERE state = ‘ACTIVE’ <choose> <when test="title != null"> AND title like #{title} </when> <when test="author != null and author.name != null"> AND author_name like #{author.name} </when> <otherwise> AND featured = 1 </otherwise> </choose> </select>