Springboot知識點

1Spring boot簡介

主要用來簡化spring開發,快速地建立獨立的spring項目,而且與雲計算自然集成。

2. @Controller 

標記一個類是Controller,也能夠標記方法,標記方法時是指傳統Web的Controller,返回的是字符串。

3. @ResponseBody

註解的做用是將controller的 方法返回的對象經過適當的轉換器轉換爲指定的格式以後,寫入到response對象的body區,一般用來返回JSON數據或者是XML。例如:  
1 @RequestMapping("/login")
2 @ResponseBody
3 public User login(User user){
4   return user;
5 }
User字段:userName pwd
那麼在前臺接收到的數據爲:
1 '{"userName":"xxx","pwd":"xxx"}'
效果等同於以下代碼:
1 @RequestMapping("/login")
2 public void login(User user, HttpServletResponse response){    
3    response.getWriter.write(JSONObject.fromObject(user).toString());
4 }

4. @RequestBody

將前端發來的json格式數據轉換成java對象,好比
1 @PostMapping(value = "/log/runtime/info")
2 public CommonResponse getMesosClusterInfo(@RequestBody QueryLogRequest request) throws BearException {
3     CommonResponse commonResponse = new CommonResponse();
4     commonResponse.setData(request);
5     return commonResponse;
6 }

5. @RestController

@RestController = @Controller + @ResponseBody
在編寫接口時標記方法是一個Rest接口,返回一個可序列化的Json或者XML對象。Controller中的註解具體能夠參考: 必須知道的Spring Boot中的一些Controller註解

6. @RequestMapping簡介

指定控制器能夠處理哪些URL請求,至關於Servlet中在web.xml中配置:
1 <servlet>
2     <servlet-name>servletName</servlet-name>
3     <servlet-class>ServletClass</servlet-class>
4 </servlet>
5 <servlet-mapping>
6     <servlet-name>serveltName</servlet-name>
7     <url-pattern>url</url-pattern>
8 </servlet-mapping>
(1)在@Target中有兩個屬性,分別爲 ElementType.METHOD 和 ElementType.TYPE ,也就是說 @RequestMapping 能夠在方法和類的聲明中使用;
(2)能夠看到註解中的屬性除了 name() 返回的字符串,其它的方法均返回數組,也就是能夠定義多個屬性值,例如 value() 和 path() 均可以同時定義多個字符串值來接收多個URL請求。

7. @Configuration 和 @Bean 註解

@Configuration 的註解類表示這個類可使用 Spring IoC 容器做爲 bean 定義的來源。@Bean 註解告訴 Spring,一個帶有 @Bean 的註解方法將返回一個對象,該對象應該被註冊爲在 Spring 應用程序上下文中的 bean。具體解釋可見: http://www.javashuo.com/article/p-mguhaynl-ha.html  

8. @EnableAutoConfiguration 

做用是從classpath中搜索全部META-INF/spring.factories配置文件,而後將其中org.springframework.boot.autoconfigure.EnableAutoConfiguration key對應的配置項加載到spring容器
只有spring.boot.enableautoconfiguration爲true(默認爲true)的時候,才啓用自動配置。

9. @ComponentScan

自定掃描路徑下邊帶有@Controller,@Service,@Repository,@Component註解加入spring容器
經過includeFilters加入掃描路徑下沒有以上註解的類加入spring容器
經過excludeFilters過濾出不用加入spring容器的類。具體參見 https://blog.51cto.com/4247649/2118342

10. @SpringBootApplication

@SpringBootApplication=@Configuration+@EnableAutoConfiguration+@ComponentScan

11. @Primary和@Qualifier

使用場景:若是在經過@Autowired自動注入時,注入的接口存在多個實現類且當咱們不具體指定哪一個實現類時,SpringBoot會報錯,此時可使用@Primary指定一個類爲默認偏好(preference)的實現類,在JPA的多數據源實現中就使用到了@Primary。
1      /**
2      * EntityManager profile.
3       */
4     @Primary
5     @Bean(name = "entityManagerPrimary")
6     public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
7         return entityManagerFactoryPrimary(builder).getObject().createEntityManager();
8     }

使用場景:若是在@Autowired自動注入時有多個候選實現類的Bean,能夠經過@Qualifier在自動注入的地方傳入一個限定名(也就是類的別名)來選取指定的實現類,此時自動注入的策略就從 byType 轉變成 byName,一樣在JPA的多數源實現中也使用到了@Qualifier。html

 1 @Configuration
 2 public class DataSourceConfig {
 3     @Bean(name = "primaryDataSource")
 4     @Qualifier("primaryDataSource")
 5     @Primary
 6     @ConfigurationProperties(prefix = "spring.datasource.primary")
 7     public DataSource primaryDataSource() {
 8         return DataSourceBuilder.create().build();
 9     }
10 
11     @Bean(name = "secondaryDataSource")
12     @Qualifier("secondaryDataSource")
13     @ConfigurationProperties(prefix = "spring.datasource.secondary")
14     public DataSource secondaryDataSource() {
15         return DataSourceBuilder.create().build();
16     }
17 }

12. @Slf4j

用它不用每次都寫private final Logger logger = LoggerFactory.getLogger(XXX.class); 

13. Lombok

使用lombok優雅的編碼前端

⚠️注意:lombok中的@Builder註解默認生成的構造器是「default」的,能夠被同package的類調用(default限制不一樣package類的調用),而咱們但願構造器設爲private,此時須要用到「@AllArgsConstructor(access = AccessLevel.PRIVATE)」。因此最終寫法:java

1 @Builder
2 @AllArgsConstructor(access = AccessLevel.PRIVATE)

14. URL命名規則

  • URL儘可能所有小寫,用戶方便輸入;
  • 不建議駝峯或者下劃線_鏈接,搜索引擎會把下劃線自動忽略掉,可使用中劃線‘-’鏈接,sou;
  • 對於CURD,URL相同,請求方法(get、post、put、delete)不一樣,也做爲不一樣的接口;
  • URL參數儘可能不超過3個
  • 資源必須採用資源名詞複數的形式,好比https://api.github.com/user/emails 

15. URL和URI

URI(Uniform Resource Identifier)字面上的意思是,統一資源 標示
URL(Uniform Resource Locator),統一資源 定位
可是 標示是什麼意思? 定位又是什麼意思?
舉個簡單的栗子🌰
好比說咱們查到東北大學校長趙X,辦公室地址遼寧省瀋陽市東北大學xx教xx號。這樣你們都知道了東北大學的校長姓趙,這樣趙校長就和這個頭銜對應了起來。一樣地咱們能夠經過一個URI來肯定它表明着什麼,好比baidu.com表明百度,xxx@qq.com表明QQ郵箱,這樣就是一個標示。URI就是網絡資源的頭銜,經過URI標記能夠把網絡世界裏面的每個事物都加以標記並區分。
若是有一天,咱們去拜訪咱們學校的校長,只知道咱們學校的校長姓趙,在東北大學,可是他不知道準確的辦公室地址,也不能去找到他。因此咱們爲了可以使網絡上的資源能被普遍的大多數的人能訪問到,還須要給他添加一個地址,好比經過東北大學xx教xx號能能夠找到趙校長的辦公室。反應到網絡世界中去就是,咱們知道baidu.com表明是一個百度,標示它是百度,當有一天咱們想要訪問百度地圖的時候,咱們只有一個baidu.com是找不到百度地圖的,可是若是map.baidu.com這樣和百度地圖對應起來,咱們就能夠直接找到百度地圖的網絡資源。至關於給咱們提供了資源存放的地址門牌號,咱們只是去取得資源。

16. IDEA中的classpath問題

Thread.currentThread().getContextClassLoader().getResource("")獲得當前的classpath的絕對路徑的URI表示。如:file:/Users/admin/akia/data/bin/
通常狀況下,用到的資源文件(各類xml,properites,xsd文件等)都放在src/main/resources下面,maven打包時能把這些資源文件打包到相應的jar或者war裏。
例如:

 

17. Springboot中日誌打印問題

springboot默認是logback日誌,初始構建日誌有顏色,但因爲某種操做以後顏色消失了,一種解決方法是在相應目錄resource下增長logback.xml,以下:git

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 
 3 <!-- Logback configuration. See http://logback.qos.ch/manual/index.html -->
 4 <configuration scan="true" scanPeriod="10 seconds">
 5     <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
 6         <encoder>
 7             <!--格式化輸出:%d表示日期,%thread表示線程名,%-5level:級別從左顯示5個字符寬度%msg:日誌消息,%n是換行符 :
 8             |%blue(%thread)  線程 如 :DiscoveryClient-CacheRefreshExecutor-0-->
 9             <pattern>%yellow(%date{yyyy-MM-dd HH:mm:ss}) |%highlight(%-5level)  |%green(%logger:%line) |%black(%msg%n)</pattern>
10         </encoder>
11     </appender>
12 
13     <!-- 日誌輸出級別 -->
14     <root level="INFO">
15         <appender-ref ref="STDOUT" />
16     </root>
17 </configuration>

 效果以下:github

 

 

 

 

 

 

 

若是採用log4j日誌打印,可使用log4j.properties文件配置,該文件默認從resources目錄下讀取,好比:web

 1 #設置日誌打印級別
 2 log4j.rootLogger = INFO, FILE
 3 
 4 log4j.appender.FILE=org.apache.log4j.RollingFileAppender
 5 #設置日誌存放位置
 6 log4j.appender.FILE.File=/home/log/report-start.log
 7 #每一個日誌達到100MB時切塊
 8 log4j.appender.FILE.MaxFileSize=100MB
 9 #保存10個備份日誌文件
10 log4j.appender.FILE.MaxBackupIndex=10
11 log4j.appender.FILE.Append=true
12 log4j.appender.FILE.Threshold=INFO
13 log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
14 log4j.appender.FILE.layout.ConversionPattern=%d{HH:mm:ss,SSS} %-5p %-60c %x - %m%n

18. JPA清空數據庫

Repository層裏定義該方法:spring

@Transactional
@Modifying
@Query(value = "truncate table t",nativeQuery = true)
public void truncateTable(); 數據庫

@Transactional和@Modifying很重要apache

19. 切面小例子

今天看大佬代碼,發現個很好玩的東西,他用切面作url的訪問量和時長統計,這麼棒的小例子收了,若是有侵權立刻刪除哈😂。json

 1 // 實體類,存數據庫
 2 @Data
 3 @Entity
 4 @AllArgsConstructor
 5 @NoArgsConstructor
 6 @Accessors(chain = true)
 7 @Table(name = "user_action")
 8 @EntityListeners(AuditingEntityListener.class)
 9 public class UserActionEntity {
10   @Id
11   @GeneratedValue
12   private Long id;
13 
14   @Column
15   private String email;
16 
17   @Column
18   private String uri;
19 
20   @Column
21   private Long duration;
22 
23   @Column
24   @CreatedDate
25   private Date date;
26 
27   @Column
28   private String ip;
29 
30   @Column
31   private String action;
32 }
View Code

再寫註解

1 @Inherited
2 @Documented
3 @Target({ElementType.METHOD})
4 @Retention(RetentionPolicy.RUNTIME)
5 public @interface UserAction {
6   String value();
7 }
View Code

而後在訪問以前設置start-time,訪問以後統計時長

 1 @Aspect
 2 @Component
 3 @Order(4)
 4 public class UserActionAspect {
 5   private final UserActionDao userStatisticDao;
 6   private static final String START_TIME = "startTime";
 7 
 8   @Autowired
 9   public UserActionAspect(UserActionDao userStatisticDao) {
10     this.userStatisticDao = userStatisticDao;
11   }
12 
13   @Pointcut(value = "@annotation(yidian.data.bear.annotation.UserAction)")
14   public void userActionAspect() {
15     //fix the target
16   }
17 
18   @Before("userActionAspect()")
19   public void doBefore(JoinPoint joinPoint) {
20     Signature signature = joinPoint.getSignature();
21     Method method = ((MethodSignature) signature).getMethod();
22     UserAction annotation = method.getAnnotation(UserAction.class);
23     if (null == annotation) {
24       return;
25     }
26     HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
27         .getRequestAttributes()).getRequest();
28     request.setAttribute(START_TIME, Instant.now());
29   }
30 
31   @AfterReturning(pointcut = "userActionAspect()")
32   public void doAfterReturning(JoinPoint joinPoint) {
33     HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
34         .getRequestAttributes()).getRequest();
35     Instant endTime = Instant.now();
36     Instant startTime = (Instant) request.getAttribute(START_TIME);
37     long duration = endTime.toEpochMilli() - startTime.toEpochMilli();
38     String ip = request.getRemoteAddr();
39     String uri = request.getRequestURI();
40     String email = request.getHeader("email");
41     Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
42     String action = method.getAnnotation(UserAction.class).value();
43     UserActionEntity userAction = new UserActionEntity();
44     userAction.setUri(uri).setDuration(duration).setEmail(email).setAction(action).setIp(ip);
45     userStatisticDao.save(userAction);
46   }
47 }
View Code

最後在ctroller裏邊方法上加註解就歐了

1 @UserAction(value = "xxx")
View Code
相關文章
相關標籤/搜索