軟件工程期末大項目

🐇Gradle
Gradle Wrapper實際上就是一個腳本,使用它可以下載和使用指定版本的gradle,根據需要進行在使用之前進行下載,有效避免本地機器的設定等環境一致性問題。
雖然gradle的安裝已經非常簡單,但是使用gradle wrapper是的開發這能夠以一種更爲標準化的方式創建gradle項目。
每一個用gradle編譯的工程,都會有一個gradle/wrapper目錄,目錄下的兩個文件:
gradle-wrapper.jar:用於下載Gradle的相關代碼實現
gradle-wrapper.properties:wrapper所使用的配置信息,比如gradle的版本等信息

distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.8.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

distributionBasedistributionPath組合在一起,是解壓gradle-4.8.1-bin.zip之後的文件的存放位置。distributionPathdistributionBase指定的目錄下的子目錄。
下載位置可以和解壓位置不一樣。
zipStoreBasedistributionBase有兩種取值:GRADLE_USER_HOMEPROJECT
其中,GRADLE_USER_HOME表示用戶目錄。
在Windows下是%USERPROFILE%/.gradle,例如C:\Users\<user_name>\.gradle\
在Linux下是$HOME/.gradle,例如~/.gradle
PROJECT表示工程的當前目錄,即gradlew所在的目錄。
各種屬性的具體含義如下:

  • https\://services.gradle.org/distributions/gradle-4.8.1-bin.zip 下載gradle的4.8.1版本
  • 下載的gradle-4.8.1-bin.zip存放到C:\Users\<user_name>\.gradle\wrapper\dists目錄中
    (注:具體還有2級目錄,即全路徑爲C:\Users\<user_name>\.gradle\wrapper\dists\gradle-3.1-bin\<url-hash>\,gradle-3.1-bin目錄是根據下載的gradle的文件名來定的,目錄名是根據distribution url路徑字符串計算md5值得來的,具體參考PathAssembler.java中的rootDirName()和getHash(),PathAssembler.java的位置見本文最後的參考路徑)
  • 解壓gradle-4.8.1-bin.zip,將解壓後的文件存放到C:\Users\<user_name>\.gradle\wrapper\dists中(注:具體還有2級目錄,同上)

🐇build.gradle

buildscript {
	//ext用於定義屬性
	ext {
		springBootVersion = '1.5.10.RELEASE'
	}
	//使用了Maven的中央倉庫(也可指定其他倉庫)
	repositories {
		maven {url 'http://maven.aliyun.com/nexus/content/groups/public/'}
	}
	//依賴關係
	dependencies {
//classpath	聲明在執行其它腳本時ClassLoader可以使用這些依賴庫
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
	}
}
//使用插件
apply plugin: 'java'
apply plugin: 'eclipse-wtp'
apply plugin: 'org.springframework.boot'
apply plugin: 'war'

group = 'com.zmh'
version = '0.0.1'
//指定編譯.java文件的JDK版本
sourceCompatibility = 1.8

//默認使用Maven的中央倉庫,此處改用自定義的鏡像庫
repositories {
	maven {url 'http://maven.aliyun.com/nexus/content/groups/public/'}
}
//configurations是依賴集合,可爲工程聲明額外依賴
configurations {
	providedRuntime
}

dependencies {
    compile('org.springframework.boot:spring-boot-starter-web')
	//數據庫相關
    compile('mysql:mysql-connector-java')
	compile('org.mybatis.spring.boot:mybatis-spring-boot-starter:1.3.1')
    //友好的HTML規範 搭配spring.thymeleaf.mode=LEGACYHTML5
	compile('org.springframework.boot:spring-boot-starter-thymeleaf')
    compile('net.sourceforge.nekohtml:nekohtml:1.9.22')
    //熱部署 搭配spring.thymeleaf.cache=false
    compile('org.springframework.boot:spring-boot-devtools')
    //SpringBoot內置的Redis
    compile('org.springframework.boot:spring-boot-starter-data-redis')
    //內置tomcat 僅開發測試用
	//runtime('org.springframework.boot:spring-boot-starter-tomcat')
    //spring-boot-admin 圖形化管理頁面
    compile('de.codecentric:spring-boot-admin-server:1.5.7')
    compile('de.codecentric:spring-boot-admin-server-ui:1.5.7')
    compile('de.codecentric:spring-boot-admin-starter-client:1.5.7')
	//pagehelper
	compile group: 'com.github.pagehelper', name: 'pagehelper-spring-boot-starter', version: '1.2.3'
    //使用的是shiro-spring 而非shiro
    compile('org.apache.shiro:shiro-spring:1.4.0')
	compile('com.github.theborakompanioni:thymeleaf-extras-shiro:1.2.1')
	//測試
    testCompile('org.springframework.boot:spring-boot-starter-test')
}


🐇gradlew.bat
針對Windows的shell腳本與批處理命令,當項目被push到遠程後,其他用戶使用Git克隆下來,只需在本地執行./gradlew即可進行項目的構建與任務的執行,同時用戶本機並不需要提前安裝好Gradle分發包.


🚢代碼分析
controller–>service–>mapper

  • AdminController
    在頁面標籤欄裏顯示日誌文件
package com.dwz.xietongoa.controller;

import com.dwz.xietongoa.dto.ReturnDto;
import com.dwz.xietongoa.util.ReadFileUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * @author DWZ
 * @date 2020/4/18 16:24
 * 在頁面標籤欄裏顯示日誌文件
 */
@Controller
@RequestMapping(value = "/admin")
public class AdminController {
    //這兩個參數從application.properties獲取
    @Value("${logback.filepath}")
    private String filePath;
    @Value("${logback.charset}")
    private String charSet;

    /**
     * 獲取所有日誌文件的文件名
     * @return
     */
    @RequestMapping(value = "/getFileNames")
    @ResponseBody
    public ReturnDto getFileNames(){
        return ReadFileUtil.getFileName(filePath);
    }

    /**
     * 獲取所有日誌文件的文件名
     * @return
     */
    @RequestMapping(value = "/readFiles")
    @ResponseBody
    public ReturnDto readFiles(@RequestParam("fileName")String fileName){
        return ReadFileUtil.readFileByLines(filePath,fileName,charSet);
    }


    /**
     * 日誌
     */
    @RequestMapping(value = "/logs")
    public String logs(){
        return "logs";
    }
    /**
     * 系統監控
     */
    @RequestMapping(value = "/springbootadmin")
    public String springbootadmin(){
        return "springbootadmin";
    }
}

  • CalendarController-CalendarMapper
    日程表
package com.dwz.xietongoa.controller;

import com.dwz.xietongoa.dto.ReturnDto;
import com.dwz.xietongoa.service.RedisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;

@Controller
public class CalendarController {
    @Autowired
    private RedisService redisService;

    /**
     * 日程表
     */
    @RequestMapping(value = "/calendar")
    public String calendar() {
        return "calendar";
    }

    /**
     * 緩存日程表備註
     * key是 calendar加userID
     * value是 JSON格式備註
     */
    @RequestMapping(value = "/calendarSetValue")
    @ResponseBody
    public ReturnDto calendarSetValue(@RequestParam("value") String value, HttpServletRequest request) {
        String key = "calendar_" + request.getSession().getAttribute("userID");
        redisService.setValue(key, value);
        return ReturnDto.buildSuccessReturnDto();
    }

    /**
     * 獲取日程表備註
     * key是 calendar加userID
     * return是 JSON格式備註
     */
    @RequestMapping(value = "/calendarGetValue")
    @ResponseBody
    public ReturnDto calendarGetValue(HttpServletRequest request) {
        String key = "calendar_" + request.getSession().getAttribute("userID");
        String value = redisService.getValue(key);
        if (value != null) {
            return ReturnDto.buildSuccessReturnDto(value);
        } else {
            return ReturnDto.buildFailedReturnDto("value is null");
        }
    }

}

package com.dwz.xietongoa.mapper;

import com.dwz.xietongoa.model.Calendar;
import com.dwz.xietongoa.model.CalendarExample;

import java.util.List;

import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

@Mapper
public interface CalendarMapper {

    long countByExample(CalendarExample example);

    int deleteByExample(CalendarExample example);

    int deleteByPrimaryKey(Integer id);

    int insert(Calendar record);

    int insertSelective(Calendar record);

    List<Calendar> selectByExample(CalendarExample example);

    Calendar selectByPrimaryKey(Integer id);

    int updateByExampleSelective(@Param("record") Calendar record, @Param("example") CalendarExample example);

    int updateByExample(@Param("record") Calendar record, @Param("example") CalendarExample example);

    int updateByPrimaryKeySelective(Calendar record);

    int updateByPrimaryKey(Calendar record);
}
  • DepartmentController-DepartmentsMapper-DepartmentService
package com.dwz.xietongoa.controller;

import com.dwz.xietongoa.dto.ReturnDto;
import com.dwz.xietongoa.model.Departments;
import com.dwz.xietongoa.service.DepartmentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.List;

/**
 * Created by DWZ
 * 2020/4/14
 * @author dwz
 */
@Controller
//用來標識http請求地址與Controller類的方法之間的映射
@RequestMapping("/department")
public class DepartmentController {

    @Autowired
    DepartmentService departmentService;

    /**
     * 查詢部門
     * @return
     */
    @RequestMapping(value = "/query")
    @ResponseBody
    public ReturnDto queryDepartment(){
        List<Departments> departments = departmentService.queryDepartment();
        return ReturnDto.buildSuccessReturnDto(departments);
    }

}

package com.dwz.xietongoa.mapper;

import com.dwz.xietongoa.model.Departments;
import com.dwz.xietongoa.model.DepartmentsExample;

import java.util.List;

import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

@Mapper
public interface DepartmentsMapper {
    long countByExample(DepartmentsExample example);

    int deleteByExample(DepartmentsExample example);

    int deleteByPrimaryKey(Integer id);

    int insert(Departments record);

    int insertSelective(Departments record);

    List<Departments> selectByExample(DepartmentsExample example);

    Departments selectByPrimaryKey(Integer id);

    int updateByExampleSelective(@Param("record") Departments record, @Param("example") DepartmentsExample example);

    int updateByExample(@Param("record") Departments record, @Param("example") DepartmentsExample example);

    int updateByPrimaryKeySelective(Departments record);

    int updateByPrimaryKey(Departments record);
}
  • IndexController
  • LoginController
  • MessageController-MessagesMapper-MessageService
  • NoticeController-NoticesMapper-NoticeService
  • PositionController-PositionsMapper-PositionService
  • UserinfoController-UserinfoMapper-UserinfoService
  • UsersController-UsersMapper-UsersService

🐇Mapper
Mapper.xml映射文件中定義了操作數據庫的sql,每一個sql都是一個statement,映射文件是MyBatis的核心.MyBatis的真正強大在於映射語句,映射器的xml文件顯得相對簡單。與具有相同功能的JDBC代碼進行對比,節省了將近95%的代碼。MyBatis是針對SQL構建的,而且比普通方法做得好。映射文件是以<mapper>爲根節點,在節點中支持9個元素,分別是cache,cache-ref,resultMap,parameterMap,sql,insert,update,delete,select

  • 🌿insert、update、delet
<?xml version="1.0" encoding="UTF-8" ?>   
<!DOCTYPE mapper   
PUBLIC "-//ibatis.apache.org//DTD Mapper 3.0//EN"  
"http://ibatis.apache.org/dtd/ibatis-3-mapper.dtd"> 
 
<!-- mapper 爲根元素節點, 一個namespace對應一個dao -->
<mapper namespace="com.dy.dao.UserDao">
 
    <insert
      <!-- 1. id (必須配置)
        id是命名空間中的唯一標識符,可被用來代表這條語句。 
        一個命名空間(namespace) 對應一個dao接口, 
        這個id也應該對應dao裏面的某個方法(相當於方法的實現),因此id 應該與方法名一致 -->
      
      id="addUser"
      
      <!-- 2. parameterType (可選配置, 默認爲mybatis自動選擇處理)
        將要傳入語句的參數的完全限定類名或別名, 如果不配置,mybatis會通過ParameterHandler 根據參數類型默認選擇合適的typeHandler進行處理
        parameterType 主要指定參數類型,可以是int, short, long, string等類型,也可以是複雜類型(如對象) -->
      
      parameterType="user"
      
      <!-- 3. flushCache (可選配置,默認配置爲true)
        將其設置爲 true,任何時候只要語句被調用,都會導致本地緩存和二級緩存都會被清空,默認值:true(對應插入、更新和刪除語句) -->
      
      flushCache="true"
      
      <!-- 4. statementType (可選配置,默認配置爲PREPARED)
        STATEMENT,PREPARED 或 CALLABLE 的一個。這會讓 MyBatis 分別使用 Statement,PreparedStatement 或 CallableStatement,默認值:PREPARED。 -->
      
      statementType="PREPARED"
      
      <!-- 5. keyProperty (可選配置, 默認爲unset)
        (僅對 insert 和 update 有用)唯一標記一個屬性,MyBatis 會通過 getGeneratedKeys 的返回值或者通過 insert 語句的 selectKey 子元素設置它的鍵值,默認:unset。如果希望得到多個生成的列,也可以是逗號分隔的屬性名稱列表。 -->
      
      keyProperty=""
      
      <!-- 6. keyColumn     (可選配置)
        (僅對 insert 和 update 有用)通過生成的鍵值設置表中的列名,這個設置僅在某些數據庫(像 PostgreSQL)是必須的,當主鍵列不是表中的第一列的時候需要設置。如果希望得到多個生成的列,也可以是逗號分隔的屬性名稱列表。 -->
      
      keyColumn=""
      
      <!-- 7. useGeneratedKeys (可選配置, 默認爲false)
        (僅對 insert 和 update 有用)這會令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法來取出由數據庫內部生成的主鍵(比如:像 MySQL 和 SQL Server 這樣的關係數據庫管理系統的自動遞增字段),默認值:false-->
      
      useGeneratedKeys="false"
      
      <!-- 8. timeout  (可選配置, 默認爲unset, 依賴驅動)
        這個設置是在拋出異常之前,驅動程序等待數據庫返回請求結果的秒數。默認值爲 unset(依賴驅動)。 -->
      timeout="20">

</mapper>
  • 🌿logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<!--debug當次屬性設置爲true時,將打印出logback內部日誌信息,實時查看logback運行狀態,默認值爲false-->
<!--根節點configuration還包含其他的兩個屬性:scan和scanPeriod.scan設置爲true時配置文件如果發生改變也將會被重新加載,默認爲false.scanPeriod設置檢測配置文件是否有修改的時間間隔(默認爲毫秒),默認時間爲1分鐘-->
<configuration debug="false">
    <!--定義日誌文件的存儲地址 勿在 LogBack 的配置中使用相對路徑-->
    <property resource="application.properties" />
    <!-- 控制檯輸出 -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <!--encoder默認配置爲PatternLayoutEncoder-->
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!--格式化輸出:%d表示日期,%thread表示線程名,%-5level:級別從左顯示5個字符寬度%msg:日誌消息,%n是換行符-->
            <!--encoder負責兩件事:一是把日誌信息轉換成字節數組,二是把字節數組寫入到輸出流,目前PatternLayoutEncoder是唯一有用的且默認的encoder,有一個pattern節點用來設置日誌的輸入格式-->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        </encoder>
    </appender>
    <!-- 按照每天生成日誌文件 -->
    <!--appender是configuration的子節點,是負責寫日誌的組件,有兩個必要屬性name和class,name指appender名稱,class指appender的全限定名-->
    <appender name="FILE"  class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--日誌文件輸出的文件名 ${logback.filepath}是從application.properties裏面取的-->
            <FileNamePattern>${logback.filepath}/projectoa.%d{yyyyMMdd}.log</FileNamePattern>
            <!--日誌文件保留天數-->
            <MaxHistory>30</MaxHistory>
        </rollingPolicy>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!--格式化輸出:%d表示日期,%thread表示線程名,%-5level:級別從左顯示5個字符寬度%msg:日誌消息,%n是換行符-->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        </encoder>
        <!--日誌文件最大的大小-->
        <!--triggeringPolicy告知RollingFileAppender適合激活滾動-->
        <!--SizedBasedTriggeringPolicy查看當前活動文件的大小,如果超過指定大小會告知-->
        <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
        <!--maxFileSize是活動文件的大小,默認值是10MB-->
            <MaxFileSize>10MB</MaxFileSize>
        </triggeringPolicy>
    </appender>
    <!--myibatis log configure-->
    <!--將ibatis,Connection,Statement等所有類的日誌打印出來,並分別設置日誌級別-->
    <logger name="com.apache.ibatis" level="TRACE"/>
    <logger name="java.sql.Connection" level="DEBUG"/>
    <logger name="java.sql.Statement" level="DEBUG"/>
    <logger name="java.sql.PreparedStatement" level="DEBUG"/>

    <!-- 日誌輸出級別 默認WARN -->
    <root level="WARN">
    <!--appender的配置表示打印到控制檯-->
    <!--未設置addtivity默認爲true,因此此logger的打印信息不再向上級傳遞並且制定了名字爲"STDOUT"的appender-->
        <appender-ref ref="STDOUT" />
        <appender-ref ref="FILE" />
    </root>
    <!--日誌異步到數據庫 -->
    <!--<appender name="DB" class="ch.qos.logback.classic.db.DBAppender">-->
    <!--&lt;!&ndash;日誌異步到數據庫 &ndash;&gt;-->
    <!--<connectionSource class="ch.qos.logback.core.db.DriverManagerConnectionSource">-->
    <!--&lt;!&ndash;連接池 &ndash;&gt;-->
    <!--<dataSource class="com.mchange.v2.c3p0.ComboPooledDataSource">-->
    <!--<driverClass>com.mysql.jdbc.Driver</driverClass>-->
    <!--<url>jdbc:mysql://127.0.0.1:3306/databaseName</url>-->
    <!--<user>root</user>-->
    <!--<password>root</password>-->
    <!--</dataSource>-->
    <!--</connectionSource>-->
    <!--</appender>-->
</configuration>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章