全部/webjars/**
,都去classpath:/META-INF/resources/webjars/
找資源;webjars
文件表明以jar包的形式去引入靜態資源,具體見webjars;css
webjars
使用方式很簡單,以 jquery
引入爲例:html
// pom.xml <!-- 引入jQuery -->在訪問的時候只須要寫**/webjars/文件夾下面的資源名稱便可 <dependency> <groupId></groupId> <artifactId>jquery</artifactId> <version>3.3.1</version> </dependency> 複製代碼
訪問http://localhost:8080/webjars/jquery/3.3.1/jquery.js
便可訪問到導入靜態資源文件夾中的jquery.js
文件java
全部訪問/**
訪問當前項目的靜態資源(css,img,js等文件),都會去如下路徑查找是否含有該文件mysql
"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", // 習慣使用這個 **/src/main/resources/static/ "classpath:/public/", // 習慣使用這個 **/src/main/resource/public/ "/" // 當前項目跟路徑 複製代碼
訪問http://localhost:8080/assets/css/signin.css
實際上是訪問/src/main/resource/static/assets/css/signin.css
jquery
訪問/
默認顯示的頁面,也叫歡迎頁面,都會去靜態資源所在的路徑尋找index.html
文件顯示出來web
private Optional<Resource> getWelcomePage() { String[] locations = getResourceLocations(this.resourceProperties.getStaticLocations()); return Arrays.stream(locations).map(this::getIndexHtml).filter(this::isReadable).findFirst(); } private Resource getIndexHtml(String location) { return this.resourceLoader.getResource(location + "index.html"); } 複製代碼
訪問/favicon.ico
會直接映射到classpath:/public|static|resources/favicon.ico
spring
classpath:/resources/
下的application.yml
文件中配置數據庫鏈接信息spring: datasource: username: root password: 123456 url: jdbc:mysql://localhost:3306/jdbc driver-class-name: com.mysql.cj.jdbc.Driver 複製代碼
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> 複製代碼
默認數據源:sql
SpringBoot建立默認DataSource時,規則以下:數據庫
參考資料:apache
引入druid,切換數據源爲druid數據源
type: com.alibaba.druid.pool.DruidDataSource // 指定爲druid數據源 // 其餘屬性 #上半區公共部分對應的是 org.springframework.boot.autoconfigure.jdbc.DataSourceProperties 中的屬性 #下半區屬性對應的是 com.alibaba.druid.pool.DruidDataSource 中的屬性,Spring Boot 默認是不注入不了這些屬性值的,須要本身綁定 #druid 數據源專有配置 initialSize: 5 minIdle: 5 maxActive: 20 maxWait: 60000 timeBetweenEvictionRunsMillis: 60000 minEvictableIdleTimeMillis: 300000 validationQuery: SELECT 1 FROM DUAL testWhileIdle: true testOnBorrow: false testOnReturn: false poolPreparedStatements: true #配置監控統計攔截的filters,stat:監控統計、log4j:日誌記錄、wall:防護sql注入 #若是容許時報錯 java.lang.ClassNotFoundException: org.apache.log4j.Priority #則導入log4j依賴便可,Maven 地址: https://mvnrepository.com/artifact/log4j/log4j filters: stat,wall,log4j maxPoolPreparedStatementPerConnectionSize: 20 useGlobalDataSourceStat: true connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500 複製代碼
配置druid數據源自動裝配
// SpringBoot啓動類SpringBootDataJdbcApplication的同級文件夾中建立config.DruidConfig.java文件 package com.dyh.www.springbootjdbc.config; import com.alibaba.druid.pool.DruidDataSource; import com.alibaba.druid.support.http.StatViewServlet; import com.alibaba.druid.support.http.WebStatFilter; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import javax.sql.DataSource; import java.util.Arrays; import java.util.HashMap; import java.util.Map; @Configuration public class DruidConfig { @ConfigurationProperties(prefix = "spring.datasource") @Bean public DataSource druidDataSource() { return new DruidDataSource(); } // 配置druid的監控 // 配置一個管理後臺的servlet @Bean public ServletRegistrationBean statViewServlet() { ServletRegistrationBean bean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*"); Map<String, String> initParams = new HashMap<>(); initParams.put("loginUsername", "admin"); initParams.put("loginPassword", "123456"); initParams.put("allow", ""); initParams.put("deny", ""); bean.setInitParameters(initParams); return bean; } // 配置一個web監控的攔截filter @Bean public FilterRegistrationBean webStatFilter() { FilterRegistrationBean bean = new FilterRegistrationBean(); bean.setFilter(new WebStatFilter()); Map<String, String> initParams = new HashMap<>(); initParams.put("exclusions", "*.js, *.css, /druid/*"); // 靜態資源js,css文件不攔截過濾 bean.setInitParameters(initParams); bean.setUrlPatterns(Arrays.asList("/*")); return bean; } } 複製代碼
<dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.0.1</version> </dependency> 複製代碼
// 這是操做數據庫的mapper @Mapper // 數據庫與數據模型的映射註解,若是這裏沒有,則須要在SpringBootApplication啓動類上添加掃描全局mapper的註解,並指定相應的掃描路徑 public interface DepartmentMapper { // 數據庫的增刪改查sql接口數據映射 @Select("select * from department") public List<Department> getDepartmentList(); @Select("select * from department where id=#{id}") public Department getDepartmentById(Integer id); @Delete("delete from department where id=#{id}") public int deleteDepartmentById(Integer id); @Options(useGeneratedKeys = true, keyProperty = "id") // 指定主鍵 @Insert("insert into department(departmentName) values(#{departmentName})") public int insertDepartment(Department department); @Update("update department set departmentName=#{departmentName} where id=#{id}") public int updateDepartment(Department department); } // 這裏的 departmentName 對應數據庫的 departmentName 字段 // 若是這裏的 department_name 相對應數據庫的 departmentName 字段 轉換成駝峯命名方式,則能夠增長轉換的自動配置 複製代碼
import com.dyh.springbootmybatis.bean.Department; import com.dyh.springbootmybatis.mapper.DepartmentMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.List; // web API接口 @RestController public class DepartmentController { @Autowired DepartmentMapper departmentMapper; @RequestMapping(value = "/dept/{id}", method=RequestMethod.GET) public Department getDepartmentById(@PathVariable("id") Integer id) { return departmentMapper.getDepartmentById(id); } @RequestMapping(value = "/dept/list", method=RequestMethod.GET) public List<Department> getDepartmentList() { return departmentMapper.getDepartmentList(); } @RequestMapping(value = "/dept", method = RequestMethod.GET) public Department insertDepartment(Department department) { departmentMapper.insertDepartment(department); return department; } } 複製代碼
轉換的自動配置
在config/文件夾下建立自定義mybatis的映射規則, 給Spring容器添加一個ConfigurationCustomizer組件便可
@org.springframework.context.annotation.Configuration // 代表這是一個自動配置類 public class MybatisConfig { @Bean // 代表這是一個Spring容器組件 public ConfigurationCustomizer configurationCustomizer() { return new ConfigurationCustomizer() { @Override public void customize(Configuration configuration) { configuration.setMapUnderscoreToCamelCase(true); } }; } } 複製代碼
@MapperScan(value = "com.dyh.springbootmybatis.mapper") // 這裏批量掃描mapper文件,而且使用value指定路徑 @SpringBootApplication public class SpringBootMybatisApplication { public static void main(String[] args) { SpringApplication.run(SpringBootMybatisApplication.class, args); } } 複製代碼
以Employee對象爲例,首先定義數據實體類,與數據庫表字段一一對應
public class Employee { private Integer id; private String lastName; private String email; private Integer gender; private Integer departmentId; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public Integer getGender() { return gender; } public void setGender(Integer gender) { this.gender = gender; } public Integer getDepartmentId() { return departmentId; } public void setDepartmentId(Integer departmentId) { this.departmentId = departmentId; } } 複製代碼
創建操做數據庫表接口的mapper,並統一在SpringBoot的主配置類中配置掃描mapper的路徑
import com.dyh.springbootmybatis.bean.Employee; import java.util.List; // API接口 public interface EmployeeMapper { public Employee getEmployeeById(Integer id); public List<Employee> getEmployeeList(); public Integer deleteEmployeeById(Integer id); } 複製代碼
配置接口mapper與數據庫表操做對應的sql語句xml文件
配置application.yml文件指定xml文件所在路徑
# 引入mybatis配置版文件 mybatis: config-location: classpath:config/mybatis-config/global.xml mapper-locations: classpath:config/mybatis-config/mapper/*.xml 複製代碼
配置全局mybatis的配置文件xml
<!-- global.xml文件 --> <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <settings> <setting name="mapUnderscoreToCamelCase" value="true"/> </settings> </configuration> 複製代碼
配置mybatis操做數據庫表的sql語句,與接口API的方法行成映射,具體配置見文檔
<!-- Employee.xml --> <!-- 接口API映射配置文件 --> <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.dyh.springbootmybatis.mapper.EmployeeMapper"> <!-- 惟一標識記號id值爲API接口的對應方法 --> <select id="getEmployeeById" resultMap="employeeMap"> select * from employee where id = #{id} </select> <select id="getEmployeeList" resultMap="employeeMap"> select * from employee </select> <delete id="deleteEmployeeById"> delete from employee where id = #{id} </delete> <resultMap id="employeeMap" type="com.dyh.springbootmybatis.bean.Employee"> <!-- 數據庫表列字段與實體類的實例屬性映射規則 --> <id property="id" column="id" /> <result property="lastName" column="lastName"/> <result property="gender" column="gender"/> <result property="email" column="email"/> <result property="departmentId" column="departmentId"/> </resultMap> </mapper> 複製代碼
JPA是做爲Spring Data一部分,用於簡化數據庫的curd和分頁列表獲取等數據操做的持久化框架,經過配置繼承封裝好數據操做的接口,爲咱們提供統一的API。
JPA(ORM): Object Relational Mapping
編寫一個實體類(entity.User),將數據表的字段和實體類的字段進行映射,同時配置好映射規則(主鍵、自增、別名等)
import javax.persistence.*; // 使用JPA註解配置映射關係 @JsonIgnoreProperties(value = { "hibernateLazyInitializer", "handler" }) // 標記不生成json對象的屬性 @Entity @Table(name = "tbl_user") // @Table指定該實體類的數據跟哪一個數據表對應,若是省略,默認數據庫表名爲該類名小寫user public class User { @Id // 這是一個主鍵 @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; @Column(name = "last_name", length = 50) // 表明這是和數據庫表對應的一個列 private String lastName; @Column // 省略則默認列名就是屬性名 private String email; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } } 複製代碼
編寫一個Dao接口來操做實體類對應的數據表,稱爲Repository,包含常見數據的增刪改查,分頁等操做
import com.dyh.springbootjpa.entity.User; import org.springframework.data.jpa.repository.JpaRepository; // 繼承JpaRepository來繼承對數據的操做接口 public interface UserRepository extends JpaRepository<User, Integer> { } 複製代碼
application.yml基本配置
# jpa關於sql相關配置 spring: jpa: hibernate: # 更新或建立數據表 ddl-auto: update # 在每次執行sql語句時打印出執行的sql語句 show-sql: true 複製代碼
接口文件
import com.dyh.springbootjpa.entity.User; import com.dyh.springbootjpa.repostitoy.UserRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import java.util.List; @RestController public class UserController { @Autowired UserRepository userRepository; @RequestMapping(value = "/user/{id}", method = RequestMethod.GET) public User getUserById(@PathVariable("id") Integer id) { User user = userRepository.getOne(id); return user; } @RequestMapping(value = "/user/save", method = RequestMethod.GET) public User insertUser(User user) { User newUser = userRepository.save(user); return newUser; } @RequestMapping(value = "/user/all", method = RequestMethod.GET) public List<User> getUserList() { List<User> userList = userRepository.findAll(); return userList; } @RequestMapping(value = "/user/test", method = RequestMethod.GET) public String userTest() { long count = userRepository.count(); return "success:" + count; } } 複製代碼
SpringBoot底層是Spring框架, Spring框架默認使用JCL做爲日誌抽象層;
SpringBoot選用SLF4做爲日誌抽象層,logback做爲日誌實現層;
Jul - Java util logging
java.util.logging包下面的一款日誌框架,屬於JDK自帶的日誌實現;
Log4j
Apache的一個開源項目,能夠不須要依賴第三方技術,直接記錄日誌;
Log4j2
log4j2和log4j是同一個做者開發,只不過log4j2是從新架構的一款日誌組件,拋棄了log4j的不足,以及吸收了優秀的logback的設計從新推出的一款新組件;
Jcl - Jakarta Commons Logging
jcl是apache公司開發的一個抽象日誌通用框架,自己不實現日誌記錄,可是提供了記錄日誌的抽象接口方法(info,debug,error…)。jcl默認使用jul打印日誌,若是項目依賴了log4j jar包,則使用log4j打印日誌;
Logback
Logback是由log4j創始人設計的一個開源日誌組件。LogBack被分爲3個組件,logback-core, logback-classic 和 logback-access;
Slf4j - Simple Logging Facade for Java
Java的簡單日誌門面(SLF4J)用做各類日誌框架的簡單門面或抽象,像jul、logback和log4j等。SLF4J容許最終用戶在部署時插入所需的日誌框架,若是在項目中使用slf4j必須加一個依賴jar,即slf4j-api-xxx.jar。slf4j自己不記錄日誌,經過綁定器綁定一個具體的日誌框架來完成日誌記錄。
日誌抽象層 | 日誌實現層 |
---|---|
Jcl、Slf4j、Jboss-logging | Log4j、 Jul、Log4j二、Logback |
SLF4j的使用
日誌記錄方法的調用,不該該直接調用日誌的實現類,而是應該調用日誌抽象層裏面的方法。
本身的應用(slf4j+logback), spring(commons-logging), Hibernate(jboss-logging), Mybatis各框架都使用了不一樣的日誌框架,如何統一日誌記錄,使得全部的框架都使用slf4j輸出日誌,這是須要解決的問題。
將系統中其餘日誌框架先排除掉,
用中間包替換掉原有被排除的日誌框架
再導入slf4j實現統一的日誌輸出
底層依賴的日誌框架
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> <version>2.1.6.RELEASE</version> <scope>compile</scope> </dependency> 複製代碼
依賴關係
總結:
SpringBoot使用slf4j+logback方式進行日誌記錄;
SpringBoot也把其餘日誌換成了slf4j;
引入其餘日誌框架,必須把本框架下的默認依賴的日誌框架移除掉(若是有的話);
// 低版本的Spring-core移除commons-logging日誌框架 // 高版本的Spring-core默認不集成commons-logging日誌框架 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <exclusions> <exclusion> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> </exclusion> </exclusions> </dependency> 複製代碼
日誌級別
Logger logger = LoggerFactory.getLogger(SpringbootLoggingApplication.class); // 日誌的級別 // 由低到高 trace < debug < info < warn < error // 在配置文件中能夠調整輸出的日誌級別,日誌就會在該級別及以上的高級別生效輸出日誌 logger.trace("這是trace信息..."); logger.debug("這是debug信息..."); // 本版本的SpringBoot默認輸出info級別及以上的日誌, 配置文件中沒有指定級別的話默認使用info級別,也叫root級別 - logging.level.root logger.info("這是info信息..."); logger.warn("這是warn信息..."); logger.error("這是error信息..."); 複製代碼
日誌輸出配置文件—application.properties
# application.properties
#日誌輸出級別
logging.level.com.dyh = trace
# 日誌輸出路徑
logging.path=/Users/dyh/IdeaProjects/mvn/springboot-logging
# 日誌輸出至文件名, 固然能夠直接指定帶路徑的文件名,這樣日誌輸出路徑可不指定
logging.file=springboot-logging.log
# 控制檯輸出日誌的格式
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{50} - %msg%n
# 文件中輸出日誌的格式
logging.pattern.file=%d{yyyy-MM-dd HH:mm:ss.SSS} === [%thread] %-5level === %logger{50} === %msg%n
複製代碼
日誌輸出格式說明
%clr(%5p) 表示輸出日誌的顏色(根據日誌級別)
%d 表示日期時間
%thread 表示線程名
%-5level 表示日誌級別level向左對齊顯示五個字符寬度
%logger{50} 表示日誌名字logger最長50個字符(日誌所在的包名),不然按句點分割
%msg 日誌輸出消息
%n 換行符
日誌輸出配置文件—logback.xml || logback-spring.xml
雖然application.properties能進行日誌的配置,可是爲了更方便、獨立地配置日誌,咱們通常使用單獨的日誌配置文件來進行日誌配置,以下:
Logging System | Customization |
---|---|
Logback | logback-spring.xml , logback-spring.groovy , logback.xml , or logback.groovy |
Log4j2 | log4j2-spring.xml or log4j2.xml |
JDK (Java Util Logging) | logging.properties |
SpringBoot
應用會默認識別logback.xml
文件做爲日誌的配置文件,可是在logback.xml
中沒法使用SpringBoot
配置的高級功能,如spring.profiles.active=dev
, 即在不一樣環境中使用不一樣的日誌配置文件,所以通常使用logback-spring.xml
做爲指定的日誌配置文件
<!-- logback-spring.xml --> <?xml version="1.0" encoding="UTF-8"?> <configuration debug="false"> <!--自定義屬性,能夠在以後使用;定義日誌文件的存儲地址 勿在LogBack的配置中使用相對路徑--> <property name="LOG_HOME" value="/Users/dyh/IdeaProjects/mvn/springboot-logging" /> <!-- 控制檯輸出 --> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <!--格式化輸出:%d表示日期,%thread表示線程名,%-5level:級別從左顯示5個字符寬度%msg:日誌消息,%n是換行符, %yellow() 定義某個輸出信息的顏色--> <pattern>%yellow(%d{yyyy-MM-dd HH:mm:ss.SSS}) %highlight([%thread] %-5level) %green(%logger{50}) - %cyan(%msg%n)</pattern> </encoder> </appender> <!-- 按照天天生成日誌文件 --> <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!--日誌文件輸出的文件名--> <FileNamePattern>${LOG_HOME}/TestWeb-%d{yyyy-MM-dd}.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 class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> <MaxFileSize>10MB</MaxFileSize> </triggeringPolicy> </appender> <!-- 日誌輸出級別 --> <!--根據不一樣的環境輸出不一樣級別的日誌信息--> <springProfile name="dev"> <!-- 在application.properties文件中指定 spring.profiles.active=dev --> <root level="DEBUG"> <appender-ref ref="STDOUT" /> </root> </springProfile> <springProfile name="prod"> <!-- 在application.properties文件中指定 spring.profiles.active=prod --> <root level="WARN"> <appender-ref ref="STDOUT" /> </root> </springProfile> </configuration> 複製代碼
按照日誌適配圖進行切換便可