SpringBoot-MyBatis资源分享网站项目笔记

本文档记录了使用SpringBoot+MyBatis框架搭建资源分享网站的过程,包括项目概述、数据库建立、后端核心功能实现,如用户注册、登录、密码找回、资源管理等。并介绍了Redis缓存、Shiro安全框架的应用,以及涉及的MySQL知识,如外键约束、事务管理。此外,还涵盖了资源分页查询、评论管理等其他功能。
摘要由CSDN通过智能技术生成

1 项目概述

1.1项目介绍
    基于SpringBoot+Mybatis框架和MySql数据库做了一个资源分享网站。该网站可以用于资源分享,也可以充当百度云盘重要资料整理说明的文档。其主要功能按照权限进行划分可分成游客、用户和管理员三大部分,游客:游客可进行注册,阅览资源;用户:注册用户可进行登录,密码找回,对自己的资源进行管理(分享资源或充值可获得积分)对他人的资源下载(下载需要消耗积分),对下载的资源进行评价评价、发布资源获取积分积分等;管理员:管理员可对资源类型进行管理、对资源和评价进行审核、并可以完成对登录人数、各类别资源发布数目等信息进行统计的任务。为减少用户对数据库的操作以提高系统效率,本项目采用了Redis数据库充当缓存,并用Shiro框架实现认证和权限管理。
1.2技术选型
    SpringBoot作为主体框架;MyBatis作为持久层框架;数据库选用MySql;并用Redis实现了对热门数据和常用数据的缓存(是不是也可以进行阅读量的增加)以减少对MySql的操作提高效率;Javamail实现:密码找回;Shiro作为Java安全框架,执行身份验证与授权。具体功能及核心实现如下所示。
1.3 项目流程
    1 建立数据库和数据表;
    2 利用IDEA创建SpringBoot项目;
    3 对Maven工程的Pom.xml进行配置,以导入依赖;
    4 在application.yml对Datasource等信息进行配置;
    5 引入前端资源文件;
    6 根据业务需求编写实体类Entity代码和Mapper层代码、Mapper.xml、service层接口和实现类、controller层的接口和实现类;
    7测试并部署(这一步实际没进行);

2 数据库建立

2.1数据库中的表以及表间关系
    创建数据库,并建立用户表、资源表、资源类型表、消息表、评价表、资源下载表和友情链接表,各个表之间的关系如图1所示。

在这里插入图片描述
2.2所用mysql知识点总结
    1 建立表的过程中,各个表要满足三大范式;
    2 存储引擎选择上,必须是InnoDB存储引擎,而不能是MyISAM存储引擎,因为MyISAM存储引擎是不支持外键的;
    3 涉及多表查询;
    4 外键约束的对业务逻辑来讲,也很重要;Mysql包含四种外键约束:
        CASCADE:父表delete、update的时候,子表会delete、update掉关联记录;
        SET NULL:父表delete、update的时候,子表会将关联记录的外键字段所在列设为null,所以注意在设计子表时外键不能设为not null;
        RESTRICT:如果想要删除父表的记录时,而在子表中有关联该父表的记录,则不允许删除父表中的记录;
        NO ACTION:同 RESTRICT,也是首先先检查外键;

3 后端核心功能及代码实现

    在此部分进行之前要先解决掉项目热更新热部署的问题,来减少启动,同时加入filter过滤规则,对所有页面进行过滤(注意要把filter声明为配置类)。
3.1 用户主页相关功能
3.1.1 注册功能
    用户通过添加用户名、密码、昵称、邮箱和性别几个属性进行注册,同时具备通过QQ进行注册的功能。(QQ注册的功能后面完善)。在进行存储注册之前,要先写好user Entity,再写Mapper层同时注入Sql,再写service层并进行事务和权限验证方面的操作,最后再对controller进行定义。
在这个功能中用到的UserService方法主要包含如下几种:

     // 根据用户名查找用户实体
    public User findByUserName(String userName);
     //根据邮箱查找用户实体
    public User findByEmail(String email);
     // 添加或修改用户信息
    public void save(User user);
     * 根据id获取用户信息
    public User getById(Integer id);

UserController中的关于注册的方法如下,其中BindingResult提供了参数校验功能。在项目当中少不了入参校验,服务器和浏览器互不信任,不能因为前端加入参判断了后台就不处理了,这样是不对的。比如前台传过来一个对象作为入参参数,这个对象中有些属性允许为空,有些属性不允许为空,那么我们可以使用@Valid+BindingResult进行controller参数校验。同时用户注册的过程中为了信息安全,不应将明文密码存入数据库,要进行MD5加密处理。controller如下:

   /**
     * 用户注册
     */
    @ResponseBody
    @PostMapping("/register")
    public Map<String,Object> register(@Valid User user, BindingResult bindingResult){
   
        Map<String,Object> map = new HashMap<>();
        if(bindingResult.hasErrors()){
   
            map.put("success",false);
            map.put("errorInfo",bindingResult.getFieldError().getDefaultMessage());
        }else if(userService.findByUserName(user.getUserName())!=null){
   
            map.put("success",false);
            map.put("errorInfo","用户名已存在,请更换!");
        }else if(userService.findByEmail(user.getEmail())!=null){
   
            map.put("success",false);
            map.put("errorInfo","邮箱已存在,请更换!");
        }else{
   
            //CryptographyUtil.md5()是自定义的用于MD5加密的方法
            user.setPassword(CryptographyUtil.md5(user.getPassword(),CryptographyUtil.SALT));
            user.setRegistrationDate(new Date());
            user.setLatelyLoginTime(new Date());
            user.setHeadPortrait("tou.jpg");
            userService.save(user);
            map.put("success",true);
        }
        return map;
    }

3.1.2 登录功能–Shrio认证
    本项目在认证和权限的实现上采用Shrio,Shiro是Apache下的一个开源项目。shiro主要有三大功能模块: Subject:主体,一般指用户,对应用提供的API的核心;SecurityManager:安全管理器,管理所有Subject,可以配合内部安全组件。(类似于SpringMVC中的DispatcherServlet);Realms:用于进行权限信息的验证,一般需要自己实现。相当于DataSource。在进行认证和权限管理之前,我们应该先定义好Shrio的配置类,并自定义Realms。
自定义Realm中要实现权限管理的方法和认证的方法,截止到目前只涉及认证方法,代码很固定,如下所示:

     // 权限认证
     //Token中包含了前端传来的userName+passWord
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
   
        String userName = (String) authenticationToken.getPrincipal();
        User user = userService.findByUserName(userName);
        if(user==null){
   
            return null;
        }else{
   
            AuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user.getUserName(),user.getPassword(),"xx");
            return authenticationInfo;
        }
    }

    Realm自定义完成后,需要定义Shrio的配置类,配置类中包含了三个核心方法,从上到下依次为:public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) 在这个方法中定义拦截器,过滤链;public SecurityManager securityManager() 用于返回SecurityManager;public MyRealm myRealm() 在这个方法中返回上文自定义的Realm。过滤链定义,从上往下执行,一般将/**放在最下面 这是个坑,一不小心代码就不好使了,authc:所有的url必须认证通过才可以访问 anon:所有url都可以匿名访问 ,配置不会被拦截的链接。(filters:管理全部过滤器,包括默认的关于身份验证和权限验证的过滤器,这些过滤器分为两组,一组是认证过滤器,有anon,authcBasic,auchc,user,一组是授权过滤器,有perms,roles,ssl,rest,port;)所以在定义拦截链的过程中,根目录、静态页面、静态资源、登录页面、登录方法、注册方法等都不需要进行过滤;除了不需要进行过滤的页面和方法以外,其他的直接定义为 filterChainDefinitionMap.put("/星星",“authc”)即可。代码如下所示(截止到目前还没涉及太多权限问题,这里的代码是项目整体的Shrio核心代码):

Bean
    public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager){
   
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        //必须设置securityManager
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        //如果不设置,默认会自动寻找Web工程根目录下的"login.jsp"页面
        shiroFilterFactoryBean.setLoginUrl("/");
        Map<String,String> filterChainDefinitionMap = new LinkedHashMap<>();
        filterChainDefinitionMap.put("/","anon");
        filterChainDefinitionMap.put("/static/**","anon");
        filterChainDefinitionMap.put("/ueditor/**","anon");
        filterChainDefinitionMap.put("/upload/**","anon");
        filterChainDefinitionMap.put("/user/register.html","anon");
        filterChainDefinitionMap.put("/user/login.html","anon");
        filterChainDefinitionMap.put("/user/findPassword.html","anon");
        filterChainDefinitionMap.put("/user/register","anon");
        filterChainDefinitionMap.put("/user/login","anon");
        filterChainDefinitionMap.put("/user/sendEmail","anon");
        filterChainDefinitionMap.put("/user/checkYzm","anon");
        filterChainDefinitionMap.put("/user/bindEmail","anon");
        filterChainDefinitionMap.put("/QQ/qqLogin","anon");
        filterChainDefinitionMap.put("/article/**","anon");
        filterChainDefinitionMap.put("/comment/**","anon");
        filterChainDefinitionMap.put("/connect","anon");
        filterChainDefinitionMap.put("/buyVIP","anon");
        filterChainDefinitionMap.put("/fbzyzjf","anon");
        filterChainDefinitionMap.put("/admin/login.html","anon");
        filterChainDefinitionMap.put("/user/bindEmail.html","anon");
        filterChainDefinitionMap.put("/user/logout","logout");
        filterChainDefinitionMap.put("/**","authc");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }

    @Bean
    public SecurityManager securityManager(){
   
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //设置realm
        securityManager.setRealm(myRealm());
        return securityManager;
    }

    /**
     * 身份认证realm
     * @return
     */
    @Bean
    public MyRealm myRealm(){
   
        MyRealm myRealm = new MyRealm();
        return myRealm;
    }

    在定义好Shrio配置类后,就要写登录的controller代码了,因为登录成功后一般会将用户信息添加到Session中,所以controller方法接受的参数中应该包含session。具体实现描述:当用户名和密码都不为空的时候,就要进行是否可以登录的判断了,这个判断是交给shrio来完成的,首先获取subject对象,然后将用户名和密码作为参数建立Token对象,再调用subject的login等,最后登录成功后将用户信息添加到session中,具体代码如下所示(其实整个登录过程完全可以由Realm来完成,具体实现并不唯一):

    /**
     * 用户登录
     * StringUtil.isEmpty()是个自定义的判断字符串是否为空的工具类,其实没太大实际意义;
     */
    @ResponseBody
    @PostMapping("/login")
    public Map<String,Object> login(User user, HttpSession session){
   
        Map<String,Object> map = new HashMap<>();
        if(StringUtil.isEmpty(user.getUserName())){
   
            map.put("success",false);
            map.put("errorInfo","请输入用户名!");
        }else if(StringUtil.isEmpty(user.getPassword())){
   
            map.put("success",false);
            map.put("errorInfo","请输入密码!");
        }else{
   
            Subject subject = SecurityUtils.getSubject();
            UsernamePasswordToken token = new UsernamePasswordToken
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值