springboot深入學習(一)-----springboot核心、配置文件加載、日志配置


在創建spring項目的時候,最煩的就是各種xml配置,通常有一個小坑可能會耽誤好久時間,現在springboot已經改變了這種現象,讓你告別xml配置,並且只要啟動一個java類,搭配上嵌入式的web容器,簡直爽歪歪。

springboot的思想就是“約定大於配置”,也就是說對於同一件事件或是操作,大部分開發者的做法都相同,那springboot就默認提供這種方式,這樣大部分人就不需要手動配置,當然你有特殊項目要求,也可以自己手動配置。

創建一個springboot的項目

直接選擇default的就好,點擊next;

創建工程名:MyProject

這地方有很多的模塊可以選擇,包括spring cloud中的模塊,本人先選擇了其中的兩個模塊;

建好項目之后,本人准備new一個Java文件,但是發現右鍵的時候沒有新建java class的按鈕,如下:

遇到這種問題呢,也不要慌張,解決方法如下:

點擊file-->project structure

點擊modules

將整個項目中的包對應source、resource等一一對應好;

然后點擊apply、ok

搞定了。

下面新建幾個包,完善一下項目結構:

 

建議將所有的包與主類放在同一層級,這樣后面可以減少很多的手工導入以及配置。

@SpringBootApplication

@SpringBootApplication是spring boot的核心注解,源碼如下:

相當於:@Configuration+@EnableAutoConfiguration+@ComponentScan

@Configuration:此類是一個配置

@EnableAutoConfiguration:讓springboot根據類路徑中的jar包依賴為當前項目進行自動配置

@ComponentScan:springboot自動掃描入口類所在包以及其子包里的bean

另外springboot也可以關閉特定的自動配置:@SpringBootApplication(exlude = {DataSourceAutoConfiguration.class})

 

SpringBoot配置文件

1、application.properties或application.yml

SpringBoot的全局配置文件為applicaiton.properties或者application.yml,通常放在src/main/resources/下,如下:

同樣也可以使用yml編寫,示例如下(將tomcat默認端口修改為8001、將默認訪問路徑修改為/index):

A、application.properties

server.port=8001

server.context-path=/index

 

B、application.yml

server:

  port:8001

  context-path: /index

 

2、加載xml

springboot提倡零配置,但是項目中難免需要使用xml配置,引入方式如下:

@ImportResource({"classpath:some-context.xml", "classpath:another-context.xml"})

 

 

外部配置

1、常規屬性配置

在spring的項目中,通過@PropertySource指明properties文件的位置,然后可以通過@Value注入值。在SpringBoot里,只需要在appllication.properties文件中定義屬性,直接使用@Value即可

示例:

application.properties文件增加屬性:

運行結果:

注意點:

A、@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})  ----------------------->項目啟動的時候會報錯,提示沒有數據源,因此在初始化bean的時候,排除這個bean

B、項目運行地址是不需要項目名的,直接使用http://localhost:8080/index,而不是http://localhost:8080/項目名稱/index

 

 2、類型安全的配置

通過@Value的方式配置屬性也可以,但是當屬性過多時,會寫許多個@Value,同時也不美觀,因此springboot還提供了@ConfigurationProperties將屬性與一個bean關聯,示例如下:

運行結果:

 

注意點:

A、使用lombok的@Data可以省去寫get、set方法

B、有時候會提示一個錯誤:Spring Boot Annotion processor not found in classpath

這時需要添加一個依賴,如下:

C、在加載application.properties中的屬性時,不需要指定location,如果是在其他自定義的properties文件中去加載屬性,則需要加上location(1.5.1以上版本取消)

@ConfigurationProperties(prefix = "xxx", locations = {"classpath:/xxx.properties"})

如果springboot版本高於1.5.1,則可以使用這種方式(將類注冊為@component,並且使用@ConfigurationProperties+@PropertySource):

 

 

日志配置

springboot支持log4j、logback等等作為日志框架,但是默認日志框架使用的是logback,示例如下:

配置日志文件:

logging.file=D:/mylog/log.log

配置日志級別:

logging.level.org.springframework.web=DEBUG

 

1、log4j

a、引入依賴

在創建Spring Boot工程時,我們引入了 spring-boot-starter ,其中包含了 spring-boot-starterlogging,該依賴內容就是Spring Boot默認的日志框架Logback,所以我們在引入log4j之前,需要先排除該包的依賴,再引用log4j的依賴。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-logging</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-log4j</artifactId>
</dependency>

b、配置log4j.properties

在src/main/resources目錄下加入log4j.properties配置文件。

控制台輸出:

# 控制台輸出
# LOG4J配置
log4j.rootCategory=INFO, stdout
# 控制台輸出
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L - %m%n

輸出到文件:

# 輸出到文件
log4j.rootCategory=INFO, stdout, file
# root⽇志輸出
log4j.appender.file=org.apache.log4j.DailyRollingFileAppender
log4j.appender.file.file=logs/all.log
log4j.appender.file.DatePattern='.'yyyy-MM-dd
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L - %m%n

 

2、將log4j日志寫入到mongodb

思路:log4j提供的輸出器實現自Appender接口,要自定義appender輸出到mongodb,只需要繼承AppenderSkeleton,並實現幾個方法即可。

a、引入依賴

<dependency>
    <groupId>org.mongodb</groupId>
    <artifactId>mongodb-driver</artifactId>
    <version>3.2.2</version>
</dependency>

b、繼承AppenderSkeleton

public class MongoAppender extends AppenderSkeleton {
    //mongodb的連接客戶端
    private MongoClient mongoClient;
    //記錄日志的數據庫
    private MongoDatabase mongoDatabase;
    //記錄日志的集合
    private MongoCollection<BasicDBObject> logsCollection;
    //連接mongodb的串
    private String connectionUrl;
    //數據庫名
    private String databaseName;
    //集合名
    private String collectionName;
    
    @Override
    protected void append(LoggingEvent loggingEvent) {
        if(mongoDatabase == null) {
            MongoClientURI connectionString = new MongoClientURI(connectionUrl);
            mongoClient = new MongoClient(connectionString);
            mongoDatabase = mongoClient.getDatabase(databaseName);
            logsCollection = mongoDatabase.getCollection(collectionName, BasicDBObject.class);
        }
        logsCollection.insertOne((BasicDBObject) loggingEvent.getMessage());
    }
    
    @Override
    public void close() {
        if(mongoClient != null) {
            mongoClient.close();
        }
    }
    
    @Override
    public boolean requiresLayout() {
        return false;
    }
    // 省略getter和setter
}

c、配置log4j.properties

# 記錄INFO級別⽇志
log4j.logger.mongodb=INFO, mongodb
# mongodb輸出
# appender實現為com.didispace.log.MongoAppende
log4j.appender.mongodb=com.didispace.log.MongoAppender
# mongodb連接地址:mongodb://localhost:27017
log4j.appender.mongodb.connectionUrl=mongodb://localhost:27017
# mongodb數據庫名:logs
log4j.appender.mongodb.databaseName=logs
# mongodb集合名:logs_request
log4j.appender.mongodb.collectionName=logs_request

d、通過切面實現

@Aspect
@Order(1)
@Component
public class WebLogAspect {
    private Logger logger = Logger.getLogger("mongodb");
    
    @Pointcut("execution(public * com.didispace.web..*.*(..))")
    public void webLog(){}
    
    @Before("webLog()")
    public void doBefore(JoinPoint joinPoint) throws Throwable {
        // 獲取HttpServletRequest有兩種方式:
    
//一:在controller層中將HttpServletRequest一層層的傳下去。
     //二:((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest()獲得 ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = attributes.getRequest(); // 獲取要記錄的⽇志內容 BasicDBObject logInfo = getBasicDBObject(request, joinPoint); logger.info(logInfo); } private BasicDBObject getBasicDBObject(HttpServletRequest request, JoinPoint joinPoint) { // 基本信息 BasicDBObject r = new BasicDBObject(); r.append("requestURL", request.getRequestURL().toString()); r.append("requestURI", request.getRequestURI()); r.append("queryString", request.getQueryString()); r.append("remoteAddr", request.getRemoteAddr()); r.append("remoteHost", request.getRemoteHost()); r.append("remotePort", request.getRemotePort()); r.append("localAddr", request.getLocalAddr()); r.append("localName", request.getLocalName()); r.append("method", request.getMethod()); r.append("headers", getHeadersInfo(request)); r.append("parameters", request.getParameterMap()); r.append("classMethod", joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName()); r.append("args", Arrays.toString(joinPoint.getArgs())); return r; } private Map<String, String> getHeadersInfo(HttpServletRequest request) { Map<String, String> map = new HashMap<>(); Enumeration headerNames = request.getHeaderNames(); while (headerNames.hasMoreElements()) { String key = (String) headerNames.nextElement(); String value = request.getHeader(key); map.put(key, value); } return map; } }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM