springboot整合jwt与vue的后端管理系统6

接下来我们写一下如何实现增删改查

菜单接口开发

我们先来开发菜单的接口,因为这3个表:用户表、角色表、菜单表,才有菜单表是不需要通过其他表来获取信息的。比如用户需要关联角色,角色需要关联菜单,而菜单不需要主动关联其他表。因此菜单表的增删改查是最简单的。

再回到我们的前端项目,登录完成之后我们通过JWT获取项目的导航菜单和权限,那么接下来我们就先编写这个接口。

获取菜单导航和权限的链接是/sys/menu/nav,然后我们的菜单导航的json数据应该是这样的:

{
   title: '角色管理',
   icon: 'el-icon-rank',
   path: '/sys/roles',
   name: 'SysRoles',
   component: 'sys/Role',
   children: []

然后返回的权限数据应该是个数组:

["sys:menu:list","sys:menu:save","sys:user:list"...]

注意导航菜单那里有个children,也就是子菜单,是个树形结构,因为我们的菜单可能这样:

系统管理 - 菜单管理 - 添加菜单

可以看到这就已经有3级了菜单了。
所以在打代码时候要注意这个关系的关联。我们的SysMenu实体类中有个parentId,但是没有children,因此我们可以在SysMenu中添加一个children,当然了其实不添加也可以,因为我们也需要一个dto,这样我们才能按照上面json数据格式返回。

我们还是来添加一个children吧:

  • com.rao.entity.SysMenu
@Data
@EqualsAndHashCode(callSuper = true)
public class SysMenu extends BaseEntity {
   ...
   @TableField(exist = false)
   private List<SysMenu> children = new ArrayList<>();
}

然后我们也先来定义一个SysMenuDto吧,知道要返回什么样的数据,我们就只需要去填充数据就好了

  • com.rao.common.dto.SysMenuDto
@Data
public class SysMenuDto implements Serializable {
   private Long id;
   private String title;
   private String icon;
   private String path;
   private String name;
   private String component;
   List<SysMenuDto> children = new ArrayList<>();
}

ok,我们来开始我们的编码

  • com.rao.controller.SysMenuController#nav

package com.rao.controller;



import cn.hutool.core.map.MapUtil;
import com.rao.common.lang.Result;
import com.rao.entity.SysUser;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

import java.security.Principal;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 *
 * @since 2022-03-09
 */
@RestController
@RequestMapping("/sys/menu")
public class SysMenuController extends BaseController {

    @GetMapping("/nav")
    public Result nav(Principal principal){
        String name = principal.getName();
        SysUser sysUser = sysUserService.getByUsername(name);
        String[] authoritys = StringUtils.tokenizeToStringArray(sysUserService.getUserAuthoriyInfo(sysUser.getId()), ",");
        return Result.succ(
                MapUtil.builder()
                        .put("nav",sysMenuService.getcurrentUserNav())
                      .put("authoritys",authoritys)
                .map()
        );
    }

}

方法中Principal principal表示注入当前用户的信息,getName就可以获取当当前用户的用户名了。sysUserService.getUserAuthorityInfo方法我们之前已经说过了,就在我们登录完成或者身份认证时候需要返回用户权限时候编写的。然后通过StringUtils.tokenizeToStringArray把字符串通过逗号分开组成数组形式。
重点在与sysMenuService.getcurrentUserNav,获取当前用户的菜单导航,

package com.rao.service.impl;

import com.rao.common.dto.SysMenuDto;
import com.rao.entity.SysMenu;
import com.rao.entity.SysUser;
import com.rao.mapper.SysMenuMapper;
import com.rao.mapper.SysUserMapper;
import com.rao.service.SysMenuService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.rao.service.SysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * 
 * @since 2022-03-09
 */
@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements SysMenuService {

    @Autowired
    SysUserService sysUserService;

    @Autowired
    SysUserMapper sysUserMapper;
    @Override
    public List<SysMenuDto> getcurrentUserNav() {
        String username = (String) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        SysUser sysUser = sysUserService.getByUsername(username);
        List<Long> navMenuIds = sysUserMapper.getNavMenuIds(sysUser.getId());
        List<SysMenu> menus=buildTreeMenu(this.listByIds(navMenuIds));

        return conver(menus);
    }



    private List<SysMenu> buildTreeMenu(List<SysMenu> listByIds) {
        List<SysMenu> finalMenus=new ArrayList<>();
        for (SysMenu menu:listByIds){
            for (SysMenu e:listByIds){
                if (e.getParentId()==menu.getId()){
                    menu.getChildren().add(e);
                }
            }
            if (menu.getParentId()==0){
                finalMenus.add(menu);
            }
        }
        return finalMenus;
    }
    /**
     * menu转dto
     */
    private List<SysMenuDto> conver(List<SysMenu> menus) {
        List<SysMenuDto> menuDtos=new ArrayList<>();
        menus.forEach(m->{
            SysMenuDto sysMenuDto = new SysMenuDto();
             sysMenuDto.setId(m.getId());
             sysMenuDto.setName(m.getPerms());
             sysMenuDto.setTitle(m.getName());
             sysMenuDto.setComponent(m.getComponent());
             sysMenuDto.setIcon(m.getIcon());
             sysMenuDto.setPath(m.getPath());
             if (m.getChildren().size()>0){
                 sysMenuDto.setChildren(conver(m.getChildren()));
             }
             menuDtos.add(sysMenuDto);

        });
        return menuDtos;
    }

 @Override
    public List<SysMenu> tree() {
        // 获取所有菜单信息
        List<SysMenu> sysMenus = this.list(new QueryWrapper<SysMenu>().orderByAsc("orderNum"));

        // 转成树状结构
        return buildTreeMenu(sysMenus);
    }

}

接口中sysUserMapper.getNavMenuIds我们之前就已经写过的了,通过用户id获取菜单的id,然后后面就是转成树形结构,buildTreeMenu方法的思想很简单,我们现实把菜单循环,让所有菜单先找到各自的子节点,然后我们在把最顶级的菜单获取出来,这样顶级下面有二级,二级也有自己的三级。最后就是convert把menu转成menuDto。这个比较简单,就不说了。
好了,导航菜单已经开发完毕,我们来写菜单管理的增删改查,因为菜单列表也是个树形接口,这次我们就不是获取当前用户的菜单列表的,而是所有菜单然后组成树形结构,一样的思想,数据不一样而已。

  • com.rao.controller.SysMenuController
package com.rao.controller;



import cn.hutool.core.map.MapUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.rao.common.lang.Const;
import com.rao.common.lang.Result;
import com.rao.entity.SysMenu;
import com.rao.entity.SysRoleMenu;
import com.rao.entity.SysUser;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.print.attribute.standard.RequestingUserName;
import java.security.Principal;
import java.time.LocalDateTime;
import java.util.List;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 *
 * @since 2022-03-09
 */
@RestController
@RequestMapping("/sys/menu")
public class SysMenuController extends BaseController {

    @GetMapping("/nav")
    public Result nav(Principal principal){
        String name = principal.getName();
        SysUser sysUser = sysUserService.getByUsername(name);
        String[] authoritys = StringUtils.tokenizeToStringArray(sysUserService.getUserAuthoriyInfo(sysUser.getId()), ",");
        return Result.succ(
                MapUtil.builder()
                        .put("nav",sysMenuService.getcurrentUserNav())
                      .put("authoritys",authoritys)
                .map()
        );
    }

    @GetMapping("/info/{id}")
    @PreAuthorize("hasAuthority('sys:menu:list')")

    public Result info(@PathVariable("id") Long id){
        return Result.succ(sysMenuService.getById(id));

    }
    @GetMapping("/list")
    @PreAuthorize("hasAuthority('sys:menu:list')")
    public Result list(){
        List<SysMenu> menus = sysMenuService.tree();
        return Result.succ(menus);
    }
    @PostMapping("/save")
    @PreAuthorize("hasAuthority('sys:menu:save')")
    public Result save(@Validated @RequestBody SysMenu sysMenu){
        sysMenu.setCreated(LocalDateTime.now());
        sysMenu.setStatu(Const.STATUS_ON);
        sysMenuService.save(sysMenu);
        return Result.succ(sysMenu);
        
    }
    @PostMapping("/update")
    @PreAuthorize("hasAuthority('sys:menu:update')")
    public Result update(@Validated @RequestBody SysMenu sysMenu){
        sysMenu.setCreated(LocalDateTime.now());
         sysMenuService.updateById(sysMenu);
         sysUserService.clearUserAuthorityInfoByMenuId(sysMenu.getId());
        return Result.succ(sysMenu);

    }
    @Transactional
    @PostMapping("/delete/{id}")
    @PreAuthorize("hasAuthority('sys:menu:delete')")
    public Result delete(@PathVariable("id") Long id){
        int count = sysMenuService.count(new QueryWrapper<SysMenu>().eq("parent_id", id));
        if (count>0){
            return Result.fail("请先删除子菜单");
        }
        //先清除所有与该菜单相关的权限缓存
        sysUserService.clearUserAuthorityInfoByMenuId(id);
        sysMenuService.removeById(id);
        //同步删除
        sysRoleMenuService.remove(new QueryWrapper<SysRoleMenu>().eq("menu_id",id));
                
        return Result.succ("");

    }


}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SpringBoot整合JWT是一种常用的实现权限验证功能的方式。JWT(Json Web Token)是一种基于JSON的开放标准,用于在网络应用环境中传递声明。在SpringBoot项目中整合JWT,可以实现用户身份验证和访问控制的功能。 整合JWT的步骤如下: 1. 在项目的pom文件中添加JWT依赖。可以使用com.auth0的java-jwt库,具体的依赖配置如下: ```xml <dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.4.0</version> </dependency> ``` 2. 创建用户实体类。可以使用@Data注解自动生成getter和setter方法,示例如下: ```java package com.example.manageserve.controller.dto; import lombok.Data; @Data public class UserDTO { private String username; private String password; private String nickname; private String token; } ``` 3. 将拦截器注入到SpringMVC。创建一个配置类,实现WebMvcConfigurer接口,并重写addInterceptors方法,如下所示: ```java package com.example.manageserve.config; import com.example.manageserve.config.interceptor.JwtInterceptor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class InterceptorConfig implements WebMvcConfigurer { @Override public void addInterceptors (InterceptorRegistry registry){ registry.addInterceptor(jwtInterceptor()) .addPathPatterns("/**") //拦截所有请求,通过判断token是否合法来决定是否需要登录 .excludePathPatterns("/user/login","/user/register"); } @Bean public JwtInterceptor jwtInterceptor(){ return new JwtInterceptor(); } } ``` 通过以上步骤,我们可以实现SpringBootJWT整合,实现了用户的登录和权限验证功能。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [xmljava系统源码-JWT-DEMO:SpringBoot整合JWT完成权限验证功能示例](https://download.csdn.net/download/weixin_38641764/19408331)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [springboot集成JWT](https://blog.csdn.net/weixin_67958017/article/details/128856282)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值