後端Web開發
Maven
Apache Maven 是一個專案管理和構建工具,它基於專案物件模型(POM)的概念,透過一小段描述資訊來管理專案的構建。
Maven作用
依賴管理
統一的專案結構
專案構建
倉庫
安裝Maven
<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>
測試:
mvn -v
配置Maven環境
建立Maven專案
座標
匯入Maven專案
依賴配置
倉庫網址:https://mvnrepository.com/
依賴傳遞
顯示關係圖
A的依賴關係圖
B的依賴關係圖
C的依賴關係圖
排除依賴
依賴範圍
生命週期
在同一套生命週期中,當執行後面的階段時,前面的階段都會執行,上圖三套
SpringBoot
入門
入門程式碼
package com.itheima.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@RequestMapping("/Hello")
public String hello() {
System.out.println("Hello!!!");
return "Hello world!!!";
}
}
啟動
HTTP協議
請求協議
相應協議
狀態碼大類
狀態碼分類 | 說明 |
---|---|
1xx | 響應中——臨時狀態碼,表示請求已經接受,告訴客戶端應該繼續請求或者如果它已經完成則忽略它 |
2xx | 成功——表示請求已經被成功接收,處理已完成 |
3xx | 重定向——重定向到其它地方:它讓客戶端再發起一個請求以完成整個處理。 |
4xx | 客戶端錯誤——處理發生錯誤,責任在客戶端,如:客戶端的請求一個不存在的資源,客戶端未被授權,禁止訪問等 |
5xx | 伺服器端錯誤——處理發生錯誤,責任在服務端,如:服務端丟擲異常,路由出錯,HTTP版本不支援等 |
常見的響應狀態碼
狀態碼 | 英文描述 | 解釋 |
---|---|---|
200 | OK |
客戶端請求成功,即處理成功,這是我們最想看到的狀態碼 |
302 | Found |
指示所請求的資源已移動到由Location 響應頭給定的 URL,瀏覽器會自動重新訪問到這個頁面 |
304 | Not Modified |
告訴客戶端,你請求的資源至上次取得後,服務端並未更改,你直接用你本地快取吧。隱式重定向 |
400 | Bad Request |
客戶端請求有語法錯誤,不能被伺服器所理解 |
403 | Forbidden |
伺服器收到請求,但是拒絕提供服務,比如:沒有許可權訪問相關資源 |
404 | Not Found |
請求資源不存在,一般是URL輸入有誤,或者網站資源被刪除了 |
405 | Method Not Allowed |
請求方式有誤,比如應該用GET請求方式的資源,用了POST |
428 | Precondition Required |
伺服器要求有條件的請求,告訴客戶端要想訪問該資源,必須攜帶特定的請求頭 |
429 | Too Many Requests |
指示使用者在給定時間內傳送了太多請求(“限速”),配合 Retry-After(多長時間後可以請求)響應頭一起使用 |
431 | Request Header Fields Too Large |
請求頭太大,伺服器不願意處理請求,因為它的頭部欄位太大。請求可以在減少請求頭域的大小後重新提交。 |
500 | Internal Server Error |
伺服器發生不可預期的錯誤。伺服器出異常了,趕緊看日誌去吧 |
503 | Service Unavailable |
伺服器尚未準備好處理請求,伺服器剛剛啟動,還未初始化好 |
狀態碼大全:https://cloud.tencent.com/developer/chapter/13553
協議解析
Tomcat
基本使用
配置埠號:
部署:將檔案移動到webapps資料夾下即可
https://docs.spring.io/spring-boot/docs/2.7.4/reference/htmlsingle/#using.build-systems.starters
請求響應
請求
postman
簡單引數
如果方法形參名稱與請求引數名稱不匹配,可以使用 @RequestParam 完成對映
原始方法(不要求掌握)
//原始方法
@RestController
public class HelloController {
@RequestMapping("/simpleParam")
public String simpleParam(HttpServletRequest request) {
// 獲取請求引數
String name = request.getParameter("name");
String ageStr = request.getParameter("age");
int age = Integer.parseInt(ageStr);
System.out.println(name + ":" + age);
return "OK";
}
}
Springboot方式
@RestController
public class HelloController {
// Springboot方式
@RequestMapping("/simpleParam")
public String simpleParam(String name, int age) {
System.out.println(name + ":" + age);
return "OK";
}
}
GET請求
POST請求
請求引數名與方法變數名不同,不能傳遞
@RequestMapping("/simpleParam")
public String simpleParam(String userName, int age) {
System.out.println(userName + ":" + age);
return "OK";
}
強制傳遞:註釋@RequestParam(name/value="請求引數名", require = true(預設,必須傳遞name))
@RequestMapping("/simpleParam")
public String simpleParam(@RequestParam(name = "name") String userName, int age) {
System.out.println(userName + ":" + age);
return "OK";
}
不傳遞會報錯,因為預設required=true,除非required=false
required=false,不傳遞name:
實體引數
要求:請求引數名與形參物件屬性名相同
簡單實體引數
實體類
public class User {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
Springboot方法
@RestController
public class HelloController {
// 實體引數
@RequestMapping("/simplePojo")
public String simplePojo(User user) {
System.out.println(user);
return "OK";
}
}
複雜實體引數
實體類:address實體類不要封裝有參建構函式,否則報錯
public class Address {
private String province;
private String city;
// 不要寫有參建構函式
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
@Override
public String toString() {
return "Address{" +
"province='" + province + '\'' +
", city='" + city + '\'' +
'}';
}
}
public class User {
private String name;
private int age;
private Address address;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
", address=" + address +
'}';
}
}
Springboot方法
@RestController
public class HelloController {
// 複雜實體方法
@RequestMapping("/complexPojo")
public String complexPojo(User user) {
System.out.println(user);
return "OK";
}
}
陣列集合引數
@RestController
public class HelloController {
// 陣列集合引數
@RequestMapping("/arrayParam")
public String arrayParam(String[] hobby) {
System.out.println(Arrays.toString(hobby));
return "OK";
}
}
陣列引數
集合引數
請求引數名與形參集合名稱相同且請求引數為多個,@RequestParam 繫結引數關係
注意:一定要加註解
@RestController
public class HelloController {
// 集合引數
@RequestMapping("/listParam")
public String listParam(@RequestParam List<String> hobby) {
System.out.println(hobby);
return "OK";
}
}
日期時間引數
使用 @DateTimeFormat 註解完成日期引數格式轉換
@RestController
public class HelloController {
// 日期時間引數
@RequestMapping("/dateParam")
// 方法形參:加註解指定日期格式,宣告一個日期時間物件updateTime
public String dateParam(@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime updateTime) {
System.out.println(updateTime);
return "OK";
}
}
JSON引數
JSON資料鍵名與形參物件屬性名相同,定義POJO型別形參即可接收引數,需要使用 @RequestBody 標識
注意:實體類不要寫有參構造器
@RestController
public class HelloController {
@RequestMapping("/jsonParam")
public String jsonParam(@RequestBody User user) {
System.out.println(user);
return "OK";
}
}
// Json引數如下
{
"name": "itheima",
"age": 22,
"address": {
"province": "安徽",
"city": "阜陽"
}
}
路徑引數
如果方法形參名稱與請求引數名稱不匹配,可以使用 @RequestParam 完成對映
@RestController
public class HelloController {
// 路徑引數-單個引數
@RequestMapping("/path/{id}")
public String pathParam(@PathVariable Integer id) {
System.out.println(id);
return "OK";
}
}
多個引數
// 多個引數
@RequestMapping("/path/{id}/{name}")
public String pathParam(@PathVariable Integer id, @PathVariable String name) {
System.out.println(id + ":" + name);
return "OK";
}
總結-引數
響應
@RestController
public class RequestController {
// 響應-字串
@RequestMapping("/Hello")
public String hello() {
System.out.println("Hello!!!");
return "Hello world!!!";
}
// 響應-物件
@RequestMapping("/getAddr")
public Address getAddr() {
Address addr = new Address();
addr.setProvince("廣東");
addr.setCity("深圳");
return addr;
}
// 響應-集合
@RequestMapping("/listAddr")
public List<Address> listAddr() {
List<Address> list = new ArrayList<>();
Address addr1 = new Address();
addr1.setProvince("廣東");
addr1.setCity("深圳");
Address addr2 = new Address();
addr2.setProvince("陝西");
addr2.setCity("西安");
list.add(addr1);
list.add(addr2);
return list;
}
}
響應資料形式不一,不便管理,難以維護
統一響應結果
Result類
/**
* 統一響應結果封裝類
*/
public class Result {
private Integer code ;//1 成功 , 0 失敗
private String msg; //提示資訊
private Object data; //資料 data
public Result() {
}
public Result(Integer code, String msg, Object data) {
this.code = code;
this.msg = msg;
this.data = data;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public static Result success(Object data){
return new Result(1, "success", data);
}
public static Result success(){
return new Result(1, "success", null);
}
public static Result error(String msg){
return new Result(0, msg, null);
}
@Override
public String toString() {
return "Result{" +
"code=" + code +
", msg='" + msg + '\'' +
", data=" + data +
'}';
}
}
@RestController
public class ResponseController {
// 統一響應結果
// 響應-字串
@RequestMapping("/Hello")
public Result hello() {
System.out.println("Hello!!!");
return Result.success("Hello world!!!");
}
// 響應-物件
@RequestMapping("/getAddr")
public Result getAddr() {
Address addr = new Address();
addr.setProvince("廣東");
addr.setCity("深圳");
System.out.println(addr);
return Result.success(addr);
}
// 響應-集合
@RequestMapping("/listAddr")
public Result listAddr() {
List<Address> list = new ArrayList<>();
Address addr1 = new Address();
addr1.setProvince("廣東");
addr1.setCity("深圳");
Address addr2 = new Address();
addr2.setProvince("陝西");
addr2.setCity("西安");
list.add(addr1);
list.add(addr2);
System.out.println(addr1);
System.out.println(addr2);
System.out.println(list);
return Result.success(list);
}
}
響應-案例
Springboot專案的靜態資源(html,css,js等前端資源)預設存放目錄為:classpath:/static 、 classpath:/public、 classpath:/resources
empController
package com.itheima.controller;
import com.itheima.pojo.Emp;
import com.itheima.pojo.Result;
import com.itheima.utils.XmlParserUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class empController {
@RequestMapping("/listEmp")
public Result listEmp() {
// 動態獲取獲取靜態檔案路徑,路徑中不含中文
String file = this.getClass().getClassLoader().getResource("emp.xml").getFile();
// 實在不行就拿絕對路徑
// String file = "C:\\Users\\bfs\\Desktop\\JavaWeb\\study\\JavaWeb_project\\springboot-web-quickstart\\src\\main\\resources\\emp.xml";
// 載入emp.xml,並解析資料
List<Emp> empList = XmlParserUtils.parse(file, Emp.class);
// 處理gender、job欄位
empList.stream().forEach(emp -> {
String gender = emp.getGender(); // gender: 1 男 2 女
if("1".equals(gender)) {
emp.setGender("男");
} else if("2".equals(gender)) {
emp.setGender("女");
}
String job = emp.getJob(); // job: 1:講師 2:班主任 3:就業指導
if("1".equals(job)) {
emp.setJob("講師");
} else if("2".equals(job)) {
emp.setJob("班主任");
} else if("3".equals(job)) {
emp.setJob("就業指導");
}
});
// 返回結果
return Result.success(empList);
}
}
介面除錯
前端
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>員工資訊</title>
</head>
<link rel="stylesheet" href="element-ui/index.css">
<script src="./js/vue.js"></script>
<script src="./element-ui/index.js"></script>
<script src="./js/axios-0.18.0.js"></script>
<body>
<h1 align="center">員工資訊列表展示</h1>
<div id="app">
<el-table :data="tableData" style="width: 100%" stripe border >
<el-table-column prop="name" label="姓名" align="center" min-width="20%"></el-table-column>
<el-table-column prop="age" label="年齡" align="center" min-width="20%"></el-table-column>
<el-table-column label="影像" align="center" min-width="20%">
<template slot-scope="scope">
<el-image :src="scope.row.image" style="width: 80px; height: 50px;"></el-image>
</template>
</el-table-column>
<el-table-column prop="gender" label="性別" align="center" min-width="20%"></el-table-column>
<el-table-column prop="job" label="職位" align="center" min-width="20%"></el-table-column>
</el-table>
</div>
</body>
<style>
.el-table .warning-row {
background: oldlace;
}
.el-table .success-row {
background: #f0f9eb;
}
</style>
<script>
new Vue({
el: "#app",
data() {
return {
tableData: []
}
},
mounted(){
axios.get('/listEmp').then(res=>{
if(res.data.code){
this.tableData = res.data.data;
}
});
},
methods: {
}
});
</script>
</html>
渲染效果
分層解耦
三層結構
檔案結構
dao介面
package com.itheima.dao;
import com.itheima.pojo.Emp;
import java.util.List;
public interface EmpDao {
List<Emp> listEmp();
}
dao介面的實現類
package com.itheima.dao.impl;
import com.itheima.dao.EmpDao;
import com.itheima.pojo.Emp;
import com.itheima.utils.XmlParserUtils;
import java.util.List;
public class EmpDaoA implements EmpDao {
@Override
public List<Emp> listEmp() {
// 動態獲取獲取靜態檔案路徑,路徑中不含中文
String file = this.getClass().getClassLoader().getResource("emp.xml").getFile();
// 實在不行就拿絕對路徑
// String file = "C:\\Users\\bfs\\Desktop\\JavaWeb\\study\\JavaWeb_project\\springboot-web-quickstart\\src\\main\\resources\\emp.xml";
// 載入emp.xml,並解析資料
List<Emp> empList = XmlParserUtils.parse(file, Emp.class);
return empList;
}
}
service介面
package com.itheima.service;
import com.itheima.pojo.Emp;
import java.util.List;
public interface EmpService {
List<Emp> listEmp();
}
service介面實現類
package com.itheima.service.impl;
import com.itheima.dao.EmpDao;
import com.itheima.dao.impl.EmpDaoA;
import com.itheima.pojo.Emp;
import com.itheima.service.EmpService;
import java.util.List;
public class EmpServiceA implements EmpService {
private EmpDao empDao = new EmpDaoA();
@Override
public List<Emp> listEmp() {
List<Emp> empList = empDao.listEmp();
// 處理gender、job欄位
empList.stream().forEach(emp -> {
String gender = emp.getGender(); // gender: 1 男 2 女
if("1".equals(gender)) {
emp.setGender("男");
} else if("2".equals(gender)) {
emp.setGender("女");
}
String job = emp.getJob(); // job: 1:講師 2:班主任 3:就業指導
if("1".equals(job)) {
emp.setJob("講師");
} else if("2".equals(job)) {
emp.setJob("班主任");
} else if("3".equals(job)) {
emp.setJob("就業指導");
}
});
return empList;
}
}
controller
package com.itheima.controller;
import com.itheima.pojo.Emp;
import com.itheima.pojo.Result;
import com.itheima.service.EmpService;
import com.itheima.service.impl.EmpServiceA;
import com.itheima.utils.XmlParserUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class empController {
private EmpService empService = new EmpServiceA();
@RequestMapping("/listEmpA")
public Result listEmpA() {
List<Emp> list = empService.listEmp();
return Result.success(list);
}
}
存在的問題:耦合
分層解耦
- 內聚:軟體中各個功能模組內部的功能聯絡。
- 耦合:衡量軟體中各個層/模組之間的依賴、關聯的程度。
- 軟體設計原則:高內聚,低耦合
控制反轉: Inversion Of Control,簡稱IOC。物件的建立控制權由程式自身轉移到外部(容器),這種思想稱為控制反轉。
依賴注入: Dependency Injection,簡稱DI。容器為應用程式提供執行時,所依賴的資源,稱之為依賴注入。
Bean物件:IOC容器中建立、管理的物件,稱之為bean。
IOC
Bean的宣告
要把某個物件交給IOC容器管理,需要在對應的類上加上如下註解之一
宣告bean的時候,可以透過value屬性指定bean的名字,如果沒有指定,預設為類名首字母小寫。
使用以上四個註解都可以宣告bean,但是在springboot整合web開發中,宣告控制器bean只能用@Controller。