https://github.com/leechenxiang/imooc-springboot-starter這是課程老師的github,大家可以去down代碼。
6 配置devtools熱部署工具(IDEA)
熱部署:熱部署
devtools可以實現頁面熱部署(即頁面修改後會立即生效,
這個可以直接在application.properties文件中配置spring.thymeleaf.cache=false來實現)
實現類文件熱部署(類文件修改後不會立即生效),實現對屬性文件的熱部署。
即devtools會監聽classpath下的文件變動,並且會立即重啓應用(發生在保存時機),
注意:因爲其採用的虛擬機機制,該項重啓是很快的
(1)base classloader (Base類加載器):加載不改變的Class,例如:第三方提供的jar包。
(2)restart classloader(Restart類加載器):加載正在開發的Class。
爲什麼重啓很快,因爲重啓的時候只是加載了在開發的Class,沒有重新加載第三方的jar包。
(1)配置maven
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<!-- optional=true, 依賴不會傳遞, 該項目依賴devtools;
之後依賴boot項目的項目如果想要使用devtools, 需要重新引入 -->
<optional>true</optional>
</dependency>
(2)配置application.properties文件
#關閉緩存, 即時刷新
#spring.freemarker.cache=false
#spring.thymeleaf.cache=true
#熱部署生效
spring.devtools.restart.enabled=true
#設置重啓的目錄,添加那個目錄的文件需要restart
spring.devtools.restart.additional-paths=src/main/java
#爲mybatis設置,生產環境可刪除
restart.include.mapper=/mapper-[\\w-\\.]+jar
restart.include.pagehelper=/pagehelper-[\\w-\\.]+jar
#排除那個目錄的文件不需要restart
#spring.devtools.restart.exclude=static/**,public/**
#classpath目錄下的WEB-INF文件夾內容修改不重啓
#spring.devtools.restart.exclude=WEB-INF/**
(3)如果你是eclipse或者sts,應該就可以了,然後IDEA需要再配置一下
1) “File” -> “Settings” -> “Build,Execution,Deplyment” -> “Compiler”,選中打勾 “Build project automatically” 。
2) 組合鍵:“Shift+Ctrl+Alt+/” ,選擇 “Registry” ,選中打勾 “compiler.automake.allow.when.app.running” 。
(4)修改自己的文件然後控制檯會顯示重新啓動
7 從配置文件讀取實體類數據
這裏有個問題沒解決,有思路的麻煩可以給我解答一下,就是Date方式的讀取
(1) 添加maven
<!--配置類與資源文件對應的依賴-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
(2) User.properties配置文件(放在resources路徑下就可以)
com.zpr.autouser.name = 菲菲
com.zpr.autouser.password = 345
com.zpr.autouser.age = 34
#com.zpr.autouser.birthday = 2016-11-11
(3)在實體類上添加註解(我看到還有別的添加註解的方式,所以不僅僅這種方式配置)
@Component //神奇,不知道爲什麼@Configuration沒有用,表明與配置文件對應
@ConfigurationProperties(prefix = “com.zpr.autouser”) //這裏是配置文件的參數前面對應的前綴
@PropertySource(value = “classpath:user.properties”) //配置文件路徑
(4)創建一個控制層方法
@RequestMapping("/getAutoUser")
public IMoocJSONResult getAutoUser(){
User bean = new User();
BeanUtils.copyProperties(user,bean);
return IMoocJSONResult.ok(bean);
}
返回數據:
{
"status": 200,
"msg": "OK",
"data": {
"name": "菲菲",
"age": 34,
"birthday": null
},
"ok": null
}
8 整合模板引擎(freemaker和thymeleaf)
敲黑板:前端頁面的要放在templates(動態模板)路徑下,兩種模板又分別放在自己的路徑下,好區分;
(1)添加maven
<!--添加freemaker模板-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
(2)添加配置(application.properties)
#freemarker 靜態資源配置
#
############################################################
#設定ftl文件路徑
spring.freemarker.template-loader-path=classpath:/templates
#關閉緩存, 即時刷新, 上線生產環境需要改爲true
spring.freemarker.cache=false
spring.freemarker.charset=UTF-8
spring.freemarker.check-template-location=true
spring.freemarker.content-type=text/html
spring.freemarker.expose-request-attributes=true
spring.freemarker.expose-session-attributes=true
spring.freemarker.request-context-attribute=request
spring.freemarker.suffix=.ftl
(3)添加index.ftl文件
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8" />
<title></title>
</head>
<body>
FreeMarker模板引擎
<h1>${user.name}</h1>
<h1>${user.password}</h1>
<h1>${user.age}</h1>
</body>
</html>
(4)控制層訪問路徑方法
@Controller
@RequestMapping("ftl")
public class FreemarkerController {
@Autowired
private User user;
@RequestMapping("/index")
public String index(ModelMap map) {
map.addAttribute("user", user);
return "freemarker/index";
}
}
(5)訪問結果
貼圖片得先保存,我這麼懶就直接貼頁面代碼
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8" />
<title></title>
</head>
<body>
FreeMarker模板引擎
<h1>菲菲</h1>
<h1>345</h1>
<h1>34</h1>
</body>
</html>
(6)thymleaf的配置和freemaker的配置大同小異
Maven
<!--添加thymeleaf模板-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
配置
############################################################
#
# thymeleaf 靜態資源配置
#
############################################################
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
spring.thymeleaf.mode=HTML5
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.content-type=text/html
# 關閉緩存, 即時刷新, 上線生產環境需要改爲true
spring.thymeleaf.cache=false
#設定靜態文件路徑,js,css等
spring.mvc.static-path-pattern=/static/**
控制層方法:
@RequestMapping("/index")
public String index(ModelMap map) {
map.addAttribute("name", "thymeleaf-imooc");
return "thymeleaf/index";
}
頁面:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8" />
<title></title>
</head>
<body>
Thymeleaf模板引擎
<h1 th:text="${name}">hello world~~~~~~~</h1>
</body>
</html>
顯示頁面代碼:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8" />
<title></title>
</head>
<body>
Thymeleaf模板引擎
<h1>thymeleaf-imooc</h1>
</body>
</html>
9 整合MyBatis和實現分頁
這個是MyBatis插件作者的github,可以去看看:
https://github.com/abel533/Mapper/wiki
(1)添加maven
<!--mybatis-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.1</version>
</dependency>
<!--mapper-->
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
<version>1.2.4</version>
</dependency>
<!--pagehelper-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.39</version>
</dependency>
(2)配置文件(數據庫要根據自己的)
############################################################
#
# 配置數據源相關 使用阿里巴巴的 druid 數據源
#
############################################################
spring.datasource.url=jdbc:mysql://localhost:3307/springboot1?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC&nullNamePatternMatchesAll=true
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.druid.initial-size=1
spring.datasource.druid.min-idle=1
spring.datasource.druid.max-active=20
spring.datasource.druid.test-on-borrow=true
spring.datasource.druid.stat-view-servlet.allow=true
############################################################
#
# mybatis 配置
#
############################################################
# mybatis 配置
mybatis.type-aliases-package=com.zpr.pojo
mybatis.mapper-locations=classpath:mapper/*.xml
# 通用 Mapper 配置
mapper.mappers=com.zpr.utils.MyMapper
mapper.not-empty=false
mapper.identity=MYSQL
# 分頁插件配置
pagehelper.helperDialect=mysql
pagehelper.reasonable=true
pagehelper.supportMethodsArguments=true
pagehelper.params=count=countSql
(3)生成逆向工程
添加generatorConfig.xml文件,用來從數據庫生成對應的實體類等的,跟pom.xml在同一個路徑
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<context id="MysqlContext" targetRuntime="MyBatis3Simple" defaultModelType="flat">
<property name="beginningDelimiter" value="`"/>
<property name="endingDelimiter" value="`"/>
<plugin type="tk.mybatis.mapper.generator.MapperPlugin">
<property name="mappers" value="com.zpr.utils.MyMapper"/>
</plugin>
<jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3307/springboot1?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC&nullNamePatternMatchesAll=true"
userId="root"
password="123456">
</jdbcConnection>
<!-- 對於生成的pojo所在包 -->
<javaModelGenerator targetPackage="com.zpr.pojo" targetProject="src/main/java"/>
<!-- 對於生成的mapper所在目錄 -->
<sqlMapGenerator targetPackage="mapper" targetProject="src/main/resources"/>
<!-- 配置mapper對應的java映射 -->
<javaClientGenerator targetPackage="com.zpr.mapper" targetProject="src/main/java"
type="XMLMAPPER"/>
<table tableName="sys_user"></table>
</context>
</generatorConfiguration>
在utils包下添加GeneratorDisplay.java類
package com.zpr.utils;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.internal.DefaultShellCallback;
public class GeneratorDisplay {
public void generator() throws Exception{
List<String> warnings = new ArrayList<String>();
boolean overwrite = true;
//指定 逆向工程配置文件
File configFile = new File("generatorConfig.xml");
ConfigurationParser cp = new ConfigurationParser(warnings);
Configuration config = cp.parseConfiguration(configFile);
DefaultShellCallback callback = new DefaultShellCallback(overwrite);
MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config,
callback, warnings);
myBatisGenerator.generate(null);
}
public static void main(String[] args) throws Exception {
try {
GeneratorDisplay generatorSqlmap = new GeneratorDisplay();
generatorSqlmap.generator();
} catch (Exception e) {
e.printStackTrace();
}
}
}
還有一個MyMapper,用來給Mapper接口們繼承的
/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2016 [email protected]
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.zpr.utils;
import tk.mybatis.mapper.common.Mapper;
import tk.mybatis.mapper.common.MySqlMapper;
/**
* 繼承自己的MyMapper
*
* @author liuzh
* @since 2015-09-06 21:53
*/
public interface MyMapper<T> extends Mapper<T>, MySqlMapper<T> {
//TODO
//FIXME 特別注意,該接口不能被掃描到,否則會出錯
}
然後在GeneratorDisplay.java類右鍵運行生成相應的實體類和Mapper接口
(4)在應用入口類添加註解,就是我們啓動的那個類
//掃描mybatis mapper的包路徑
@MapperScan(basePackages = "com.zpr.mapper")
//掃描需要的所有包,包含一些自用的工具類包所在的路徑,後面那個是工具類,用來生成id的
@ComponentScan(basePackages = {"com.zpr","org.n3r.idworker"})
這裏我後續的操作是需要在Mapper接口類上面添加@Component,不然注入的時候總是劃紅線,雖然不影響,強迫症。
其他是MyBatis的CRUD自己看代碼吧。
10 定時任務
(1)在應用類添加註解
@EnableScheduling
(2)定時處理類
package com.zpr.task;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class TestTask {
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
// 定義每過3秒執行任務
// @Scheduled(fixedRate = 3000)
// @Scheduled(cron = "3-45 * * * * ?")
public void reportCurrentTime() {
System.out.println("現在時間:" + dateFormat.format(new Date()));
}
}
啓動類會自動開始定時執行,這個是cron時間表達式轉換的工具網址: http://cron.qqe2.com/(記得年是不能用的,具體用法百度吧)
11 啓動異步任務
(1)在入口類添加註解
//啓動異步任務
@EnableAsync
(2)創建異步方法類
package com.zpr.task;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Component;
import java.util.concurrent.Future;
@Component
public class AsyncTask {
@Async
public Future<Boolean> doTask11() throws Exception {
long start = System.currentTimeMillis();
Thread.sleep(1000);
long end = System.currentTimeMillis();
System.out.println("任務1耗時:" + (end - start) + "毫秒");
return new AsyncResult<>(true);
}
@Async
public Future<Boolean> doTask22() throws Exception {
long start = System.currentTimeMillis();
Thread.sleep(700);
long end = System.currentTimeMillis();
System.out.println("任務2耗時:" + (end - start) + "毫秒");
return new AsyncResult<>(true);
}
@Async
public Future<Boolean> doTask33() throws Exception {
long start = System.currentTimeMillis();
Thread.sleep(600);
long end = System.currentTimeMillis();
System.out.println("任務3耗時:" + (end - start) + "毫秒");
return new AsyncResult<>(true);
}
}
(3)調用控制類:異步啓動時,時間取最長的那個,但是由於程序也需要消耗一些時間,所以會比最大的時間再大一點
package com.zpr.controller;
import com.zpr.task.AsyncTask;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.Future;
@RestController
@RequestMapping("tasks")
public class DoTask {
@Autowired
private AsyncTask asyncTask;
@RequestMapping("test1")
public String test1() throws Exception {
long start = System.currentTimeMillis();
Future<Boolean> a = asyncTask.doTask11();
Future<Boolean> b = asyncTask.doTask22();
Future<Boolean> c = asyncTask.doTask33();
while (!a.isDone() || !b.isDone() || !c.isDone()) {
if (a.isDone() && b.isDone() && c.isDone()) {
break;
}
}
long end = System.currentTimeMillis();
String times = "任務全部完成,總耗時:" + (end - start) + "毫秒";
System.out.println(times);
return times;
}
}
12 攔截器
(1)創建一個類繼承WebMvcConfigurerAdapter
package com.zpr.config;
import com.zpr.controller.interceptor.OneInterceptor;
import com.zpr.controller.interceptor.TwoInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@Configuration
public class WebMvcConfigurer extends WebMvcConfigurerAdapter {
@Override
public void addInterceptors(InterceptorRegistry registry) {
/**
* 攔截器按照順序執行
*/
registry.addInterceptor(new OneInterceptor()).addPathPatterns("/one/**");
// registry.addInterceptor(new TwoInterceptor()).addPathPatterns("/two/**")
// .addPathPatterns("/one/**");
super.addInterceptors(registry);
}
}
(2)創建一個攔截器類
package com.zpr.controller.interceptor;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.zpr.pojo.IMoocJSONResult;
import com.zpr.utils.JsonUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
public class OneInterceptor implements HandlerInterceptor {
final static Logger log = LoggerFactory.getLogger(TwoInterceptor.class);
/**
* 在請求處理之前進行調用(Controller方法調用之前)
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object object) throws Exception {
// System.out.println("被one攔截,放行...");
log.error("被one攔截,放行...");
return true;
/*if (true) {
returnErrorResponse(response, IMoocJSONResult.errorMsg("被one攔截..."));
}
return false;*/
}
/**
* 請求處理之後進行調用,但是在視圖被渲染之前(Controller方法調用之後)
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response,
Object object, ModelAndView mv)
throws Exception {
// TODO Auto-generated method stub
}
/**
* 在整個請求結束之後被調用,也就是在DispatcherServlet 渲染了對應的視圖之後執行
* (主要是用於進行資源清理工作)
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object object, Exception ex)
throws Exception {
// TODO Auto-generated method stub
}
public void returnErrorResponse(HttpServletResponse response, IMoocJSONResult result)
throws IOException, UnsupportedEncodingException {
OutputStream out=null;
try{
response.setCharacterEncoding("utf-8");
response.setContentType("text/json");
out = response.getOutputStream();
out.write(JsonUtils.objectToJson(result).getBytes("utf-8"));
out.flush();
} finally{
if(out!=null){
out.close();
}
}
}
}
(3)創建一個控制類方法測試
@Controller
@RequestMapping("one")
public class OneController {
@RequestMapping("/index")
public String index(ModelMap map) {
map.addAttribute("name", "imooc22");
return "thymeleaf/index";
}
}
(4)日誌顯示
2019-02-01 08:32:50.497 ERROR 5860 --- [nio-8080-exec-1] c.z.c.interceptor.TwoInterceptor : 被one攔截,放行...
這裏我沒有攔截,你們可以試着把另一個註釋去掉就可以看到攔截效果了。
如果你想看到我的拙略代碼,這裏是我的github:
https://github.com/momozpr/JavaCode/tree/com/springboot/zpr-springboot-demo
可以逛逛順便給我顆小星星,或者可以給我的博客點個贊,第二篇進階博客不是一邊學一邊寫的,是學完最後才寫的,所以說不定有一些步驟會遺漏,發現的小夥伴可以給我留言,謝謝,繼續加油!