網站首頁 編程語言 正文
目錄
一. 開發公共模塊,數據封裝和全局異常處理及application.properties
?編輯
二. 開發登陸要用的接收前端數據的dto,和封裝查詢結果的model
三. 開發登陸的控制層
四. 開發存儲當前用戶的model和常量類
五. 開發登陸的業務類
六. 開發持久化組件
七. 開發登錄前端(vue+ajax)
八. 動態菜單的開發
8.1 首先看數據庫查出來的數據
8.2 定義封裝查詢結果的model
8.3 定義封裝樹狀菜單結構的bean
8.4 開發控制層
8.5 開發業務層
8.6 開發持久層
8.7 編寫映射文件
8.8 編寫前端
一. 開發公共模塊,數據封裝和全局異常處理及application.properties
package com.xupt.ygq.oa.common;
public class Result<T> {
public static final int CODE_OK = 200;
public static final int CODE_ERR_BUSINESS = 500;
public static final int CODE_ERR_SYS = 530;
public static final int CODE_ERR_UNLOGINED = 520;
public static <T>Result<T> ok(){
return new Result(true,CODE_OK,null,null);
}
public static <T>Result<T> ok(String message){
return new Result(true,CODE_OK,message,null);
}
public static <T>Result<T> ok(T data){
return new Result(true,CODE_OK,null,data);
}
public static <T>Result<T> ok(String message,T data){
return new Result(true,CODE_OK,message,data);
}
public static <T>Result<T> err(int errCode ,String message){
return new Result(false,errCode,message,null);
}
public static <T>Result<T> err(int errCode ,String message,T data){
return new Result(false,errCode,message,data);
}
private boolean success;//是否成功
private int code;//200 成功 500 業務失敗,530 系統錯誤,520 未登錄
private String message;//概要信息
private T data;
public Result(boolean success, int code, String message, T data) {
this.success = success;
this.code = code;
this.message = message;
this.data = data;
}
public boolean isSuccess() {
return success;
}
public int getCode() {
return code;
}
public String getMessage() {
return message;
}
public T getData() {
return data;
}
}
import com.xupt.ygq.oa.exception.BusinessException;
import com.xupt.ygq.oa.exception.SysException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.TypeMismatchException;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
@Slf4j
@RestControllerAdvice//該注解說明本類是一個RestController的攔截器,
// 還可以對controller處理方法添加額外邏輯,做增強處理
public class DemoControllerAdvice {
//該注解說明本方法是一個異常處理器,即當被攔截的controller處理方法發生指定的異常時,即由本方法處理
@ExceptionHandler(ConstraintViolationException.class)
public Result handleConstraintViolationException(ConstraintViolationException e){
log.error("參數不匹配",e);
Set<ConstraintViolation<?>> set = e.getConstraintViolations();//獲取驗證錯誤集合
//將驗證錯誤集合中,每一個錯誤的信息取出來,組成一個新的集合,再將新集合中的元素用”,“連接成一個字符串,返回這個字符串
String msg = set.stream().map(item->item.getMessage()).collect(Collectors.joining(","));
msg.substring(0,msg.length()-1);
return Result.err(Result.CODE_ERR_SYS,msg);
}
//邦json沒綁好異常(post請求)
@ExceptionHandler(MethodArgumentNotValidException.class)
public Result handleMethodArgumentNotValidException(MethodArgumentNotValidException e){
log.error("參數不匹配",e);
//獲取參數綁定結果(包括綁定錯誤信息)
BindingResult bindingResult = e.getBindingResult();
//獲取屬性錯誤集合
List<FieldError> fieldErrorList = bindingResult.getFieldErrors();
String errMsg = fieldErrorList.stream()
.map(fieldError->fieldError.getField()+":"+fieldError.getDefaultMessage())
.collect(Collectors.joining(","));
return Result.err(Result.CODE_ERR_SYS,errMsg);
}
//綁普通字符串沒綁好異常
@ExceptionHandler(BindException.class)
public Result handleBindException(BindException e){
log.error("參數不匹配",e);
//獲取參數綁定結果(包括綁定錯誤信息)
BindingResult bindingResult = e.getBindingResult();
//獲取屬性錯誤集合
List<FieldError> fieldErrorList = bindingResult.getFieldErrors();
String errMsg = fieldErrorList.stream()
.map(fieldError->fieldError.getField()+":"+fieldError.getDefaultMessage())
.collect(Collectors.joining(","));
return Result.err(Result.CODE_ERR_SYS,errMsg);
}
//處理自定義系統異常
@ExceptionHandler(SysException.class)
public Result handleSysException(SysException e){
log.error("系統錯誤",e);
return Result.err(Result.CODE_ERR_SYS,"系統維護中");
}
//處理自定義業務異常
@ExceptionHandler(BusinessException.class)
public Result handleBusinessException(BusinessException e){
return Result.err(Result.CODE_ERR_BUSINESS,e.getMessage());
}
//參數格式異常
@ExceptionHandler(TypeMismatchException.class)
public Result handleTypeMismatchException(TypeMismatchException e){
log.error("系統錯誤",e);
return Result.err(Result.CODE_ERR_BUSINESS,"系統維護中");
}
//處理遺留的異常
@ExceptionHandler(Exception.class)
public Result handleException(Exception e){
log.error("系統錯誤",e);
return Result.err(Result.CODE_ERR_BUSINESS,"系統維護中");
}
}
二. 開發登陸要用的接收前端數據的dto,和封裝查詢結果的model
public class User {
private String u_id;
private String u_name;
private String u_pwd;
public String getU_id() {
return u_id;
}
public void setU_id(String u_id) {
this.u_id = u_id;
}
public String getU_name() {
return u_name;
}
public void setU_name(String u_name) {
this.u_name = u_name;
}
public String getU_pwd() {
return u_pwd;
}
public void setU_pwd(String u_pwd) {
this.u_pwd = u_pwd;
}
}
import javax.validation.constraints.NotEmpty;
public class LoginDto {
//@NotEmpty僅針對String ,集合等
@NotEmpty(message = "賬號不得為空")
private String u_id;
@NotEmpty(message = "密碼不得為空")
private String u_pwd;
public String getU_id() {
return u_id;
}
public void setU_id(String u_id) {
this.u_id = u_id;
}
public String getU_pwd() {
return u_pwd;
}
public void setU_pwd(String u_pwd) {
this.u_pwd = u_pwd;
}
}
dto里面加了數據驗證,所以在作為參數接收前端傳回來的數據的時候,前面要加@Validated注解
三. 開發登陸的控制層
import com.xupt.ygq.oa.common.Result;
import com.xupt.ygq.oa.common.page.CurrentUser;
import com.xupt.ygq.oa.common.page.OaConstants;
import com.xupt.ygq.oa.dto.LoginDto;
import com.xupt.ygq.oa.fun.security.service.LoginService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpSession;
@RestController
@RequestMapping("/security/login")//為本控制器處理方法的所有映射地址加統一前綴
public class LoginController {
@Autowired
private LoginService loginService;
@PostMapping("")//此方法地址:/security/login
public Result login(@Validated @RequestBody LoginDto dto,HttpSession session){
CurrentUser currentUser = loginService.checkLogin(dto);
//當前用戶信息存放在session中
session.setAttribute(OaConstants.SESSION_NAME_CURRENT_USER,currentUser);
return Result.ok();
}
}
六個注解:
①:@Restcontroller
②:@RequestMapping("+++") :為本控制器處理方法的所有映射地址統一加前綴
③:@Autowired
④:@PostMapping("") :此方法地址為項目根地址加上前面的前綴
⑤:@Validated:表示這個用來接收參數的javaBean里面添加了數據驗證
⑥:@RequestBody:表示這個Post請求傳遞的是json串的請求體
一個對象:
CurrentUser:表示當前登錄用戶
一個重要參數:
session:用來把查到的當前登錄用戶存到session中,本次會話都可以訪問的到
注意:session.setAttribute()存數據的時候,鍵用了一個常量來表示,可以避免后續使用出錯
四. 開發存儲當前用戶的model和常量類
public class CurrentUser {
private String UserId;
private String UserName;
public String getUserId() {
return UserId;
}
public void setUserId(String userId) {
UserId = userId;
}
public String getUserName() {
return UserName;
}
public void setUserName(String userName) {
UserName = userName;
}
}
//常量類
public class OaConstants {
/*
* session中用于存放當前用戶對象的屬性名稱
* */
public static final String SESSION_NAME_CURRENT_USER = "SESSION_NAME_CURRENT_USER";
}
五. 開發登陸的業務類
public interface LoginService {
//驗證用戶賬號或密碼是否正常,若正確返回表示當前用戶的對象,否則拋出業務異常(BusinessException)
public CurrentUser checkLogin(LoginDto loginDto);
}
@Service
@Transactional
public class LoginServiceImpl implements LoginService {
@Autowired
private LoginDao loginDao;
@Override
public CurrentUser checkLogin(LoginDto dto) {
User user = loginDao.findUserByIdAndPwd(dto);
if (user == null ){
throw new BusinessException("賬號或密碼錯誤!!");
}
CurrentUser currentUser = new CurrentUser();
currentUser.setUserId(user.getU_id());
currentUser.setUserName(user.getU_name());
return currentUser;
}
}
業務實現類中:
兩個注解:
①:@Service
②:@Transactional
要對當前有沒有用戶做出判斷,沒有的話拋出異常,到Controller里面再由專門處理異常的類去處理。有的話,把查到的用戶(User)封裝到當前用戶(CurrentUser)里面。
六. 開發持久化組件
import com.xupt.ygq.oa.dto.LoginDto;
import com.xupt.ygq.oa.model.User;
import org.apache.ibatis.annotations.Select;
public interface LoginDao {
@Select("select u_id,u_name from t_user where u_id=#{u_id} and u_pwd=#{u_pwd}")
public User findUserByIdAndPwd(LoginDto dto);
}
七. 開發登錄前端(vue+ajax)
<script>
//1.定義登陸數據
const loginData = {
u_id:'',//賬號
u_pwd:''//密碼
};
//2.定義登陸函數
const login = () =>{
//向服務端發送post請求,提交數據為loginData
//只有成功的情況下的success=true,同時code值為200時,才能執行then
ajax.post("/security/login",loginData).then(result=>{
//這里意味著成功
//then表示提示信息顯示完成后在進行的動作
xTip.success('登陸成功').then(()=>{
window.location.href='home.html';
});
});
};
const cfg = {
setup() {
return {
//3.導出數據在頁面上使用
loginData,
login,
};
}
};
Vue.createApp(cfg).use(XModal).use(XPagination).mount('#app');
</script>
<!-- 4. 將登錄數據與賬號框和密碼框綁定 -->
<div class="form-floating">
<input type="text" class="form-control" placeholder="賬號" v-model="loginData.u_id">
<label>賬號:</label>
</div>
<div class="form-floating">
<input type="password" class="form-control" placeholder="密碼" v-model="loginData.u_pwd">
<label>密碼:</label>
</div>
<!-- 5. 在登錄按鈕上設置事件綁定函數login -->
<button class="w-100 btn btn-lg btn-primary" type="button" @click="login">登錄</button>
八. 動態菜單的開發
8.1 首先看數據庫查出來的數據
?明顯的p代表的是父菜單,f代表子菜單
8.2 定義封裝查詢結果的model
public class Fun {
private Integer p_id;
private String p_name;
private Integer f_id;
private String f_name;
private String f_url;
public Integer getP_id() {
return p_id;
}
public void setP_id(Integer p_id) {
this.p_id = p_id;
}
public String getP_name() {
return p_name;
}
public void setP_name(String p_name) {
this.p_name = p_name;
}
public Integer getF_id() {
return f_id;
}
public void setF_id(Integer f_id) {
this.f_id = f_id;
}
public String getF_name() {
return f_name;
}
public void setF_name(String f_name) {
this.f_name = f_name;
}
public String getF_url() {
return f_url;
}
public void setF_url(String f_url) {
this.f_url = f_url;
}
}
8.3 定義封裝樹狀菜單結構的bean
//封裝樹狀菜單結構的bean
public class MenuDto {
private Integer menuId;
private String menuName;
private String menuUrl;
//子菜單集合
private List<MenuDto> chidren;
public Integer getMenuId() {
return menuId;
}
public void setMenuId(Integer menuId) {
this.menuId = menuId;
}
public String getMenuName() {
return menuName;
}
public void setMenuName(String menuName) {
this.menuName = menuName;
}
public String getMenuUrl() {
return menuUrl;
}
public void setMenuUrl(String menuUrl) {
this.menuUrl = menuUrl;
}
public List<MenuDto> getChidren() {
return chidren;
}
public void setChidren(List<MenuDto> chidren) {
this.chidren = chidren;
}
}
8.4 開發控制層
@RestController
@RequestMapping("/security/home")
public class HomeController {
@Autowired
private HomeService homeService;
@GetMapping("/menu")
public Result<List<MenuDto>> userMenuList(HttpSession session){
//sesssion中取出來的數據都是object的
CurrentUser currentUser = (CurrentUser) session.getAttribute(OaConstants.SESSION_NAME_CURRENT_USER);
List<MenuDto> menuDtoList = homeService.getUserMenuList(currentUser.getUserId());
return Result.ok(menuDtoList);
}
}
數據是由用戶id查出來的,所以需要從session中取出當前用戶傳給業務層。
8.5 開發業務層
import com.xupt.ygq.oa.dto.MenuDto;
import java.util.List;
public interface HomeService {
public List<MenuDto> getUserMenuList(String userId);
}
@Service
@Transactional
public class HomeServiceImpl implements HomeService {
@Autowired
private HomeDao homeDao;
@Override
public List<MenuDto> getUserMenuList(String userId) {
List<Fun> funList = homeDao.findUserFunList(userId);
//主菜單集合
List<MenuDto> mainList = new ArrayList<>();
MenuDto currentMainMenu = null;//當前主菜單
for (Fun fun:funList){
if (currentMainMenu == null || !fun.getP_id().equals(currentMainMenu.getMenuId())){
/*如果當前主菜單不存在,或者當前遍歷的數據中的父菜單編號與當前主菜單編號不相符
應當新創建一個當前主菜單,并放入主菜單集合*/
currentMainMenu = new MenuDto();
currentMainMenu.setMenuId(fun.getP_id());//設置主菜單編號
currentMainMenu.setMenuName(fun.getP_name());//設置主菜單名稱
currentMainMenu.setChidren(new ArrayList<MenuDto>());//設置子菜單集合
mainList.add(currentMainMenu);
}
//將當前遍歷數據中的子菜單部分分離出來,封裝到MenuDto對象中,并將該對象放入當前主菜單的子菜單集合中
MenuDto subMenu = new MenuDto();
subMenu.setMenuId(fun.getF_id());
subMenu.setMenuName(fun.getF_name());
subMenu.setMenuUrl(fun.getF_url());
currentMainMenu.getChidren().add(subMenu);
}
/*funList.forEach(fun->{
if (currentMainMenu == null || !fun.getP_id().equals(currentMainMenu.getMenuId())){
*//*
* 如果當前主菜單不存在,或者當前遍歷的數據中的父菜單編號與當前主菜單編號不相符
* 應當新創建一個當前主菜單,并放入主菜單集合
* *//*
currentMainMenu = new MenuDto();//內部類不能訪問外部的局部變量
}
});*/
return mainList;
}
}
業務類里面要把查詢到的結果封裝成MenuDto對象,再由控制器帶著MenuDto返回給前端。
8.6 開發持久層
import com.xupt.ygq.oa.model.Fun;
import java.util.List;
public interface HomeDao {
public List<Fun> findUserFunList(String userId);
}
8.7 編寫映射文件
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xupt.ygq.oa.fun.security.dao.HomeDao">
<select id="findUserFunList" resultType="com.xupt.ygq.oa.model.Fun">
select
p.f_id p_id,
p.f_name p_name,
c.f_id,
c.f_name,
c.f_url
from
t_fun c join t_fun p on c.f_pid = p.f_id
join t_rf rf on c.f_id = rf.f_id
join t_role r on rf.ro_id = r.ro_id
join t_ur ur on r.ro_id = ur.ro_id
where
c.f_ismenu = 1 and ur.u_id = #{userId}
</select>
</mapper>
8.8 編寫前端
<script>
//1.定義菜單數據
const menuList = Vue.ref([]);
//2.定義獲取菜單數據的函數
const getMenuList =()=>{
ajax.get('/security/home/menu').then(result=>{
menuList.value = result.data;
});
};
//3.執行獲取菜單數據的函數
getMenuList();
const cfg = {
setup(){
return {
menuList,//4.導出菜單數據(在頁面上使用)
};
}
};
Vue.createApp(cfg).use(XModal).use(XPagination).mount('#app');
</script>
<li v-for="main in menuList" class="mb-1">
<button class="btn btn-toggle align-items-center rounded collapsed" data-bs-toggle="collapse"
:data-bs-target=" '#main-' + main.menuId" aria-expanded="false">
{{main.menuName}}
</button>
<div class="collapse" :id=" 'main-' + main.menuId">
<ul class="btn-toggle-nav list-unstyled fw-normal pb-1 small">
<li v-for="sub in main.chidren">
<a :href="sub.menuUrl" target="mainFrame" class="link-dark rounded">
{{sub.menuName}}
</a>
</li>
</ul>
</div>
</li>
原文鏈接:https://blog.csdn.net/weixin_45836787/article/details/125916798
相關推薦
- 2022-05-27 C++超詳細分析單鏈表的實現與常見接口_C 語言
- 2023-05-22 shell腳本自動輸入用戶名和密碼的實現_linux shell
- 2022-12-25 Flutter開發通用頁面Loading組件示例詳解_Android
- 2023-02-25 Golang嵌入資源文件實現步驟詳解_Golang
- 2022-04-12 Python中BeautifulSoup模塊詳解_python
- 2022-10-29 STDC分割網絡:onnx推理
- 2022-08-29 Linux安裝Docker詳細教程_docker
- 2022-09-17 C++?中如何結束?while?(cin>>str)?的輸入_C 語言
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支