Step 1:最终效果

1.主页


2.登录注册

3.管理员后台

4.普通用户后台

以上是主要效果图,项目我目前已经放到服务器上面,有兴趣可以访问项目演示地址进行在线观看。

Step2:项目要点

1.Mybatis

这个和上一次的demo基本差不多,整合mybatis以管理和操作数据库,目前我主要使用注解的形式编写mysql语句。项目中一共有:Book、User、Rend三个实体类,在对Book的实体类操作:


@Mapper
public interface BookDao {
    String table_name="book";
    String insert_filed="name,author,price,image,description";
    String select_field = " id, status, " + insert_filed;
//查询全部书籍
    @Select({"select * from",table_name})
    List<Book> selectAll();
//根据name查找id
    @Select({"select id from",table_name,"where name=#{name}"})
    Book selectBookByName(String Name);
//根据id查找全部信息
    @Select({"select * from",table_name,"where id=#{id}"})
    Book selectBookById(@Param("id") int id);
//根据id删除指定书籍
    @Delete({"delete ","from",table_name,"where id=#{id}"})
    void deleteBookById(int id);
//根据指定的书名删除书籍
    @Delete({"delete ","from",table_name,"where name=#{name}"})
    void deleteBookByName(String name);
//添加新的书籍
    @Insert({"insert into",table_name,"(",insert_filed,")","values(#{name},#{author},#{price},#{image},#{description})"})
    void addBook(Book book);
//更新数据
    @Update({"update ", table_name, " set name=#{name},author=#{author},price=#{price},image=#{image},description=#{description} where id=#{id}"})
    void updateBookById(@Param("id") int id,@Param("name") String name,@Param("author") String author,
   

2.Bootstrap模板

这一次在前端界面上相较于上一次有明显的提升,主要是使用了bootstrap网页模板,当然光有模板是不行的也需要根据实际情况进行修改。

前端代码示例:(管理员后台书籍管理对应的前端代码主要部分)

     ...... 
 <main role="main" class="col-md-9 ml-sm-auto col-lg-10 px-4">
            <div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
                <h1 class="h2" >书籍管理</h1>
                <div class="btn-toolbar mb-2 mb-md-0">
                    <div class="btn-group mr-2">
                    </div>
                </div>
            </div>
            <a th:href="@{/book/newbook}" style="color: white;text-decoration: none" class="btn btn-success" role="button">添加书籍</a>
            <div class="table-responsive">
                <table class="table table-striped table-sm">
                    <thead>
                    <tr>
                        <th>ID</th>
                        <th>书名</th>
                        <th>作者</th>
                        <th>价格</th>
                        <th>操作</th>
                    </tr>
                    </thead>
                    <tbody>
                    <tr th:each="book : ${books}">
                        <td th:text="${book.id}"></td>
                        <td th:text="${book.name}"></td>
                        <td th:text="${book.author}"></td>
                        <td th:text="${book.price}"></td>
                        <td>
                            <a th:href="@{'/book/predit/'+${book.id}}" ><button class="btn btn-sm btn-primary">编辑</button></a>
                          <a th:href="@{'/book/del/'+${book.id}}" ><button class="btn btn-sm btn-danger" >删除</button></a>
                        </td>
                    </tr>
                    </tbody>
                </table>
            </div>
        </main>
    </div>
</div>

3.Shiro权限管理

Shiro简介: Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理。使用Shiro的易于理解的API,您可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序。

在上面的最终效果中可以看到管理员和普通用户登录后的后台界面是不一样的,这就是使用shiro区分管理员和普通用户展示不同的前端界面,Shiro的主要配置类如下:

@Configuration
public class ShiroConfig {
    /*
    关联SecurityManager
     */
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("defaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager){
        ShiroFilterFactoryBean shiroFilterFactoryBean= new ShiroFilterFactoryBean();
//        设置安全管理器
        shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
        Map<String,String> Map =new LinkedHashMap<String, String>();
//        参数含义
//user-------->rememberme 时使用

//role-------->得到对应的角色权限才可以访问

//-anon------->不需要认证就可以访问,下面设置不需要登录就可以访问的页面
        Map.put("/","anon");
        Map.put("/index.html","anon");
        Map.put("login.html","anon");
        Map.put("/css/**","anon");
        Map.put("/webjars/**","anon");
        Map.put("/login","anon");
//authc------>需要登录认证才能访问的资源,下面设置登录之后才能访问的页面
        Map.put("/book/**","authc");
        Map.put("/lookbook","authc");
        Map.put("/booklist.html","authc");
        Map.put("/background","authc");
        Map.put("/rend/**","authc");
        Map.put("/userinfo/**","authc");
//perms------->得到资源权限才可以访问,下面设置管理才能访问的页面
        Map.put("/user/**","perms[admin]");
        Map.put("/book/**","perms[admin]");
        Map.put("/lookbook","perms[admin]");
        Map.put("/booklist.html","perms[admin]");
//        设置认证跳转界面
        shiroFilterFactoryBean.setLoginUrl("/login.html");
//        设置未授权提示页面
        shiroFilterFactoryBean.setUnauthorizedUrl("/noauthoritypage");

        shiroFilterFactoryBean.setFilterChainDefinitionMap(Map);
        return  shiroFilterFactoryBean;
    }

    @Bean(name = "defaultWebSecurityManager")
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
    DefaultWebSecurityManager defaultWebSecurityManager =new DefaultWebSecurityManager();
    /*
    关联一个Realm
     */
    defaultWebSecurityManager.setRealm(userRealm);
    return defaultWebSecurityManager;
}
    @Bean(name ="userRealm")
    public UserRealm getRealm(){
        return new UserRealm();
    }

    /*
    配置一个ShiroDialect,用于Thymeleaf和shiro标签配合使用
     */
    @Bean
    public ShiroDialect getShiroDialect()
    {
        return new ShiroDialect();
    }
}

对应的Userealm:

public class UserRealm extends AuthorizingRealm {
    @Autowired
    private UserDao userDao;


    /**
     *授权逻辑
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("执行授权逻辑");
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        Subject subject = SecurityUtils.getSubject();
        User user = (User) subject.getPrincipal();
        User Dbuser=userDao.selectByEmail(user.getEmail());
        info.addStringPermission(Dbuser.getRole());
        return info;
    }
    /*
    认证逻辑
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("执行认证逻辑");
//        此处编写登录认证逻辑
        UsernamePasswordToken token= (UsernamePasswordToken)authenticationToken;
        User user=userDao.selectByEmail(token.getUsername());
        if(user==null)
        {
            System.out.println("认证结果为:用户不存在");
            return null;

        }
        return new SimpleAuthenticationInfo(user,user.getPassword(),"");

    }

}

在前端使用Thymeleaf结合Shiro标签根据认证状态和授权情况展示不同的标签:

<div class="container-fluid">
    <div class="row">
        <nav class="col-md-2 d-none d-md-block bg-light sidebar" th:fragment="sidebar">
            <div class="sidebar-sticky">
                <ul class="nav flex-column">
                    <li class="nav-item">
                        <a class="nav-link active"
                           href="/background.html">
                            <span data-feather="home"></span>
                        </a>
                        <a class="nav-link" href="/user" shiro:hasPermission="admin">//管理员可见
                            <span data-feather="shopping-cart"></span>
                            用户列表
                        </a>
                    </li>
                    <li class="nav-item" shiro:hasPermission="admin">//管理员可见
                        <a class="nav-link" href="#" th:href="@{/user/lookusers/}">
                            <span data-feather="layers"></span>
                            用户管理
                        </a>
                    </li>
                    <li class="nav-item" shiro:hasPermission="admin">//管理员可见
                        <a class="nav-link" href="/lookbook">
                            <span data-feather="bar-chart-2"></span>
                            书籍列表
                        </a>
                    </li>

                    <li class="nav-item" shiro:hasPermission="admin">//管理员可见
                        <a class="nav-link"
                           href="/book">
                            <span data-feather="users"></span>
                            书籍管理
                        </a>
                    </li>

                    <li class="nav-item">
                        <a class="nav-link" href="#" th:href="@{'/userinfo/predit/'+${session.user.getId()}}" shiro:Authenticated="true">//登录后可见
                            <span data-feather="shopping-cart"></span>
                            个人信息
                        </a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href="#" th:href="@{'/userinfo/rend/'+${session.user.getId()}}" shiro:Authenticated="true">////登录后可见
                            <span data-feather="shopping-cart"></span>
                            我的书架
                        </a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href="#" th:href="@{/index.html}">
                            <span data-feather="file"></span>
                            返回主页
                        </a>
                    </li>

                </ul>
            </div>
        </nav>
        <main role="main" class="col-md-9 ml-sm-auto col-lg-10 px-4">
        </main>
    </div>
</div>

Step3:项目说明

1.数据库字段:

在项目中我没有放对应Mysql建表语句,对于想要使用项目的小伙伴需要自己创建数据库和对应的表:

(1)数据库名称:spring

(2)user表字段如下:

(3)book表字段如下:

(4)rend表字段如下:

需要注意的是,在book表中,price为double类型,rend表中bookId为varchar类型,用于保存对应用户的书架。

2.项目不足之处

虽然是完成了这个小项目,但是我对他并不是很满意,在很多地方还是有问题,比如用户登录后点击放到书架虽然实现了功能,但是页面是重定向导致跳转的问题,这明显不符合正常情况下的使用,还有url传参带来的不安全问题也还没有解决,当然这方面我也还在学习,在后面应该会修复这些问题。

3.项目地址:

(1)github项目地址

(2)在线演示地址(移动端后台不兼容)

标签云

Bootstrap cdn Chevereto Editormd Hexo IDEA JavaScript jsDeliver JS樱花特效 Linux markdown Maven MyBatis MyBatis-plus MySQL Pictures Sakura SEO Spring Boot SpringMVC SSR Thymeleaf Web WebSocket Wechat Social WordPress Yoast SEO 代理 分页 图床 小幸运