debug:
測試全局異常時自定義異常AyhException爲null
com.aiyouhui.common.advice.CommonExceptionHandler
@ControllerAdvice
public class CommonExceptionHandler {
@ControllerAdvice aop切面註解類要在啓動類AyhItemApplication的同級及子包下才能掃描到,否則自定義異常AyhException爲null
com.aiyouhui.AyhItemApplication
Vue父子組件通信
我們定義一個子組件:
const myList = {
template:'\
<ul>\
<li v-for="item in items" :key="item.id">{{item.id}} : {{item.name}}</li>\
</ul>\
',
props:{ // 通過props來接收父組件傳遞來的屬性
items:{// 這裏定義items屬性
type:Array,// 要求必須是Array類型
default:[] // 如果父組件沒有傳,那麼給定默認值是[]
}
}
}
這個子組件可以對 items 進行迭代,並輸出到頁面。
但是組件中並未定義items屬性。
通過props來定義需要從父組件中接收的屬性
items:是要接收的屬性名稱
type:限定父組件傳遞來的必須是數組,否則報錯
default:默認值
我們在父組件中使用它:
<div id="app">
<h2>已開設如下課程:</h2>
<!-- 使用子組件的同時,傳遞屬性,這裏使用了v-bind,指向了父組件自己的屬性lessons -->
<my-list :items="lessons"/>
var app = new Vue({
el:"#app",
components:{
myList // 當key和value一樣時,可以只寫一個
},
data:{
lessons:[
{id:1, name: 'java'},
{id:2, name: 'php'},
{id:3, name: 'ios'},
]
}
})
父向子的通信 通過中間屬性域props
num: {{num}}
子組件接收父組件的num屬性
子組件定義點擊按鈕,點擊後對num進行加或減操作
子向父的通信
通過v-on指令將父組件的函數綁定到子組件上:
<div id="app">
<h2>num: {{num}}</h2>
<counter :count="num" @inc="increment" @dec="decrement"></counter>
然後,當子組件中按鈕被點擊時,調用綁定的函數:
Vue.component("counter", {
template:'\
<div>\
<button @click="plus">加</button> \
<button @click="reduce">減</button> \
</div>',
props:['count'],
methods:{
plus(){
this.$emit("inc");
},
reduce(){
this.$emit("dec");
}
}
})
vue提供了一個內置的this.$emit函數,用來調用父組件綁定的函數
項目架構:
- 後臺管理系統使用vue.js框架建出單頁應用(SPA)
SPA:single page application。整個後臺管理系統只出現一個html頁面,頁面內容都由vue.js實現。 - webpack:前端資源打包工具,將js,image,css等資源當做一個模塊打包
webpack的作用:
將許多小碎文件打包成整體,減少單頁面內的衍生請求次數,提高網站效率
將es6等高級語法進行轉換編譯,已兼容瀏覽器
打包時將代碼混淆,提高安全性 - vue-cli:快速搭建vue項目的腳手架
安裝:npm install -g vue-cli
建立static web mnodule: vue-cli-demo
終端 cd vue-cli-demo, 建立webpack項目 vue init webpack
1 use ESline之前的選擇都選擇yes,最後一個選擇yes use npm
- 安裝好之後,npm run dev 運行
**
結構
**
build下是webpack的配置,裏面定義了webpack入口entry等等屬性
src
1.main.js是入口entry,裏面import了許多其他組件
2 寫的vue文件就是一個組件 分爲3部分 <template> <script> <style>
3 route對應的是相應的組件的路徑
4 menu.js:對應的菜單
config:
1 index.js裏面配置了端口
dist: 打包好的目錄,打包src
node_modules: 所有的依賴
根目錄:
1 index.html是網站的原始頁面,
2 package.json是寫引用的依賴文件
有3個腳本,dev,start,build(構建,運行後會把src打包到dist)
Vuetify框架
1 基於vue的ui框架,寫css樣式。類似bootstrap。
建立項目(後臺):
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Finchley.SR1</spring-cloud.version>
<mysql.version>5.1.32</mysql.version>
<pageHelper.starter.version>1.2.5</pageHelper.starter.version>
<mapper.starter.version>2.0.3</mapper.starter.version>
<fastDFS.client.version>1.26.1</fastDFS.client.version>
<test.version>2.0.6.RELEASE</test.version>
</properties>
<dependencyManagement> <!-- 用來管理版本不下載jar-->
<dependencies>
<!-- cloud依賴-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- 通用mapper-->
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
<version>${mapper.starter.version}</version>
</dependency>
<!-- 分頁助手-->
<dependency>
<groupId>com.github.pagehekper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>${pageHelper.starter.version}</version>
</dependency>
<!-- mysql驅動-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
<scope>runtime</scope>
</dependency>
<!-- fastDFS-->
<dependency>
<groupId>com.github.taobao</groupId>
<artifactId>fastDFS-client</artifactId>
<version>${fastDFS.client.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>${test.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies><!-- 實際下載jar-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.7</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
1 1.1 新建project:artifact :leyou griopid :com.leyou.parent 引入依賴
1 建立通用module
1 註冊中心 ly-registry com.leuyou.common 並寫好依賴,啓動類和配置
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
@SpringBootApplication
@EnableEurekaServer
public class LyRegistry {
server:
port: 10086
spring:
application:
name: ly-registry
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10086/eureka
register-with-eureka: false
fetch-registry: false
2 網關 ly-gateway com.leyou.common 並寫好依賴,啓動類和配置
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
@SpringCloudApplication
@EnableZuulProxy
public class lYGateway {
server:
port: 10010
spring:
application:
name: api-gateway
eureka:
client:
# registry-fetch-interval-seconds: 5 # 獲取服務列表的週期:5s
service-url:
defaultZone: http://127.0.0.1:10086/eureka
instance:
prefer-ip-address: true
ip-address: http://127.0.0.1
instance-id: ${spring.application.name}.${server.port}
zuul:
prefix: /api # 添加路由前綴
# routes:
# user-service: # 這裏是路由id,隨意寫
# path: /user-service/** # 這裏是映射路徑
# service-id: user-service # 指定服務名稱
# retryable: true #重試
ribbon:
ConnectTimeout: 1000 # 連接超時時間(ms)
ReadTimeout: 2500 # 通信超時時間(ms)
MaxAutoRetriesNextServer: 0 # 同一服務不同實例的重試次數
MaxAutoRetries: 0 # 同一實例的重試次數
# OkToRetryOnAllOperations: true # 是否對所有操作重試
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMillisecond: 6000 # 熔斷超時時長:6000ms
1.2微服務結構:
1 將來肯定會有其它系統需要來調用服務中提供的接口,因此肯定也會使用 到接口中關聯的實體類。因此這裏我們需要使用聚合工程,將要提供的接口及相關實體類放到獨立子工程中,以後別人引用的時候,只需要知道座標即可。
maven deploy到私服 就可以給別人引用
2 在ly-item中創建兩個子工程:
ly-item-interface:主要是對外暴露的接口及相關實體類
ly-item-service:所有業務邏輯及內部使用接口
3 寫好依賴,啓動類和配置,並在網關gateway配置文件裏添加路由routes
依賴有
1starter-web啓動器
2 mybatis啓動器 3中包含
3通用mapper啓動器
4分頁助手啓動器
5連接池,我們用默認的Hykira 3中包含
6 mysql驅動
7 Eureka客戶端
8千萬不能忘了,我們自己也需要ly-item-interface中的實體類
@SpringBootApplication
@EnableDiscoveryClient
public class AyhItemApplication {
server:
port: 8081
spring:
application:
name: ly-item-server
datasource:
username: root
password: 123456
url: jdbc:mysql://localhost:3306/test
hikari:
maximum-pool-size: 30
minimum-idle: 10
eureka:
client:
service-url: ,
defaultZone: http://127.0.0.1:10086/eureka
instance:
lease-renewal-interval-in-seconds: 5 # 每隔5秒發送一次心跳
lease-expiration-duration-in-seconds: 10 # 10秒不發送就過期
prefer-ip-address: true
ip-address: 127.0.0.1
instance-id: ${spring.application.name}:${server.port}
到gateway配
zuul:
prefix: /api # 添加路由前綴
# retryable: true # c重試
routes:
ly-item-server: # 這裏是路由id,隨意寫
3.10.測試路由規則
爲了測試路由規則是否暢通,我們是不是需要在item-service中編寫一個controller接口呢?
其實不需要,Spring提供了一個依賴:actuator
只要我們添加了actuator的依賴,它就會爲我們生成一系列的訪問接口:
/info
/health
/refresh
...
添加依賴:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
因爲我們沒有添加信息,所以是一個空的json,但是可以肯定的是:我們能夠訪問到item-service了。
接下來我們通過路由訪問試試,根據路由規則,我們需要訪問的地址是:
http://127.0.0.1:10010/api/item/actuator/info
1.3新建一個通用的基礎服務ly-common,放微服務共享的工具類。deploy私服任何人都能下載
1 新建包com.leyou.common.utils放入工具類
2 JsonUtils的用法複雜類型轉換List<Map<String, String>>
String json="[{\"name\":\"zhangsan\",\"gender\":\"man\" },{\"name\":\"lisi\",\"gender\":\"man\" }]";
List<Map<String, String>> maps = nativeRead(json, new TypeReference<List<Map<String, String>>>() {
});
1.4通用異常處理
REST風格規範!
uo
yi
異常
注意:
``****com.aiyouhui.common.advice.CommonExceptionHandler
@ControllerAdvice
public class CommonExceptionHandler {
@ControllerAdvice aop切面註解類要在AyhItemApplication的同級及子包下才能掃描到,否則AyhException爲null
com.aiyouhui.AyhItemApplication**
1 建立通用的異常處理工具類
1 注意:需引入webmvc依賴 並且在service微服務中引入common服務的依賴
2 注意:service服務啓動類在com.leyou下,異常處理類在com.leyou下的包所以能掃描到
2 處理的方法
@PostMapping
public ResponseEntity<Item> saveItem(Item item) {
if (item.getPrice()==null){
//return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(null);
throw new AyhException(ExceptionEnum.PRICE_NOT_BE_NULL);
}
item = itemService.saveItem(item);
return ResponseEntity.status(HttpStatus.CREATED).body(item);
}
拋出異常
@PostMapping
public ResponseEntity<Item> saveItem(Item item) {
if (item.getPrice()==null){
//return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(null);
throw new AyhException(ExceptionEnum.PRICE_NOT_BE_NULL);
}
item = itemService.saveItem(item);
return ResponseEntity.status(HttpStatus.CREATED).body(item);
}
捕獲和處理異常
@ControllerAdvice
public class CommonExceptionHandler {
@ExceptionHandler(AyhException.class)
public ResponseEntity<ExceptionResult> handleException(AyhException e) {
// return ResponseEntity.status(HttpStatus.CREATED).body(e.getMessage());
//ExceptionEnum em = e.getExceptionEnum();
//return ResponseEntity.status(em.getStatus()).body(em.getMessage());//字符串
return ResponseEntity.status(e.getExceptionEnum().getStatus())
.body(new ExceptionResult(e.getExceptionEnum()));//實體對象
}
}
創建由枚舉組成異常
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class AyhException extends RuntimeException {
private ExceptionEnum exceptionEnum;
}
創建異常枚舉
@Getter
@NoArgsConstructor
@AllArgsConstructor
public enum ExceptionEnum {
PRICE_NOT_BE_NULL(400, "價格不能爲空!"),
USERNAME_NOT_BE_NULL(400, "用戶名不能爲空!"),
;
int status;
String message;
}
創建異常結果實體
import java.util.Date;
@Data
public class ExceptionResult {
private int status;
private String message;
private Date timestamp;
public ExceptionResult(ExceptionEnum em) {
this.status = em.getStatus();
this.message = em.getMessage();
this.timestamp = new Date(System.currentTimeMillis());
}`
}**``