【平臺開發】— 6.從[登入]看前後端互動
上次瞭解到了後端程式碼的大概分層,作用都是幹嘛的。那今天就結合著前端,一起看下它們是怎麼互動的。
其實簡單來講,就是前端把資料傳遞給後端,後端拿到資料後一通處理再返回給前端。
一、登入功能
前面提到的前端模板vue-admin-template
,在本地run起來後,其實就可以看出一些端倪。
開啟登入頁後,按下F12
,點選到network
下,再點選登入
按鈕。
可以看到有2個請求:
- login
- info
其中,login
介面的返回中,有一個token
值。
而在info
介面的請求引數中,帶有這個token
值。
這就是常見的登入了,後端驗證使用者名稱密碼是否存在,存在的話返回一個token值給使用者,那此使用者後面的請求都需要帶上這個token
不過這個前端框架run起來裡的資料,都是通過mock模擬返回的,路徑如圖所示:
那其實一個道理,我在後端實現同樣的返回給前端處理不就可以了嘛?
二、登入-後端
根據前面講過的後端程式碼分層,我這裡直接貼上程式碼:
1.實體類User
@Entity @Table(name = "user") @JsonIgnoreProperties({"handler", "hibernateLazyInitializer"}) @Data public class User { @Id //宣告一個欄位“id”為資料庫表的主鍵 @GeneratedValue(strategy = GenerationType.AUTO) //標註主鍵的生成策略,通過strategy 屬性指定 @Column(name = "id") //被標註欄位在資料庫表中所對應欄位的名稱 private int id; //使用者id private String username; //使用者名稱稱 private String password; //密碼 @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private Date createTime; //建立時間 }
2.DAO類UserDAO
/**
* UserDAO類繼承JpaRepository,就提供了CRUD和分頁 的各種常見功能。
* JpaRepository<User, Integer>,引數分別是實體類,和這個實體類id的型別。
*/
public interface UserDAO extends JpaRepository<User, Integer> {
}
3.Service層UserService
這裡的isUserExist
方法就是用來判斷輸入的使用者名稱密碼是否可以查詢到。
並且我在資料庫裡已經手動的插入了使用者名稱“admin”``密碼“111111”
@Service //標記這是一個service類
public class UserService {
@Autowired //自動裝配UserDAO物件
UserDAO userDAO;
/**
* 判斷使用者是否存在,存在則返回true,不存在則返回false
* @param username 使用者名稱
* @param password 使用者密碼
* @return true,false
*/
public boolean isUserExist(String username, String password) {
List<User> userList = userList();
boolean isExist = false;
for (User user: userList) {
if (user.getUsername().equals(username) && user.getPassword().equals(password)) {
isExist = true;
}
}
return isExist;
}
}
4.Controller類UserController
這裡就是呼叫了userService.isUserExist()
判斷使用者是否在資料庫的user表裡.
存在的話,就返回一個code:20000
和一個寫死的token
值admin-token
;
不存在的話就返回code :50000
和一個錯誤資訊“msg”
。
@RestController //標記這是控制器,下面每個方法的返回值都會直接轉換成json資料格式
@RequestMapping("user")
public class UserController {
@Autowired //自動裝配 CategoryService
UserService userService;
@PostMapping("/login")
public Map<String, Object> login(@RequestBody JSONObject data) throws Exception {
String username = JSONPath.eval(data,"$.username").toString();
String password = JSONPath.eval(data,"$.password").toString();
Map<String, Object> result = new HashMap<>();
Map<String, Object> userToken = new HashMap<>();
Map<String, Object> msg = new HashMap<>();
if (userService.isUserExist(username, password)) {
userToken.put("token","admin-token");
result.put("code", 20000);
result.put("data", userToken);
} else {
msg.put("msg", "使用者或密碼錯誤");
result.put("code", 50000);
result.put("data", msg);
}
return result;
}
三、登入-前端
1. api目錄下的user.js
看過這個前端框架介紹你就知道了,要請求的後端API都是在這裡寫的,模組你自己分,好維護就行。
這裡我的後端介面url就是/my_platform/user/login
。 這個介面請求要提交的引數是username
和password
。
import request from '@/utils/request'
export function login(username, password) {
return request({
url: '/my_platform/user/login',
method: 'post',
data: { // 提交的資料
username,
password
}
})
}
2. store目錄下的/modules/user.js
這裡程式碼比較多,我只貼改動的地方。那就是actions
裡的login
方法。
裡面的login
方法就是呼叫了上面api模組下的login
,其他地方的程式碼暫時未動,以實現本章目標為主。
login({ commit }, userInfo) { //定義 login 方法,在元件中使用 this.$store.dispatch() 呼叫
const username = userInfo.username.trim()
const password = userInfo.password
return new Promise((resolve, reject) => {
login(username, password).then(response => { //使用 login 介面進行網路請求
const { data } = response
commit('SET_TOKEN', data.token)
setToken(data.token)
resolve()
}).catch(error => {
reject(error)
})
})
}
3. views目錄下的/login/index.vue
上面template
和下面style
都沒動,中間script
是重點。
其中,我註釋掉了一些程式碼,因為這是專案裡demo用的演示,必須使用者名稱填admin。
但是我的目的是隻要是資料庫裡有的,就可以登入,所以不要這個前端驗證。
<script>
import { validUsername } from '@/utils/validate'
import { login } from '@/api/user'
export default {
name: 'Login',
data() {
// const validateUsername = (rule, value, callback) => {
// if (!validUsername(value)) {
// callback(new Error('Please enter the correct user name'))
// } else {
// callback()
// }
// };
// const validatePassword = (rule, value, callback) => {
// if (value.length < 6) {
// callback(new Error('The password can not be less than 6 digits'))
// } else {
// callback()
// }
// };
return {
loginForm: {
username: '',
password: ''
},
// loginRules: {
// username: [{ required: true, trigger: 'blur', validator: validateUsername }],
// password: [{ required: true, trigger: 'blur', validator: validatePassword }]
// },
loading: false,
passwordType: 'password',
redirect: undefined
}
},
watch: {
$route: {
handler: function(route) {
this.redirect = route.query && route.query.redirect
},
immediate: true
}
},
methods: {
showPwd() {
if (this.passwordType === 'password') {
this.passwordType = ''
} else {
this.passwordType = 'password'
}
this.$nextTick(() => {
this.$refs.password.focus()
})
},
handleLogin() {
this.$refs.loginForm.validate(valid => {
if (valid) {
this.loading = true
this.$store.dispatch('user/login', this.loginForm).then(() => {
this.$router.push({ path: this.redirect || '/' })
this.loading = false
}).catch(() => {
this.loading = false
})
} else {
console.log('error submit!!');
return false
}
})
}
}
}
</script>
handleLogin()
就是對於登入的處理了, $store.dispatch
會呼叫 /modules/user.js
裡的login()
。
四、驗證登入功能
終於到了驗證時刻了,我已經在資料庫user
表裡添加了其他使用者,所以我輸入正確的使用者名稱和密碼就可以登入。
登入成功。
當然了,不管是前端還是後端程式碼,我知道都埋了很多坑,也寫的不規範,但是目前處於初級階段,一步步來。
有錯誤的地方,也歡迎各位指出,謝謝!