1. 程式人生 > 其它 >決策樹——非正常企業預測

決策樹——非正常企業預測

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

  1. 檔案校驗

    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("兩檔案不同");
    }
    
  2. 密碼校驗

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>