精华内容
下载资源
问答
  • bootstrap后台管理系统前后台实现(含数据库)

    万次阅读 多人点赞 2019-07-01 17:47:33
    撰写本文档目的是让后续开发者在理解该系统架构的基础上遵循一定规范保持系统架构的合理性;同时也能够达到允许没有开发经验仅有web基础的入门开发者能够通过复制粘贴的方式仿照demo示例...2 系统实现... 3 2.1 实...

    系统版本更新

    版本

    说明

    时间

    V1.0.0

    菜单管理、角色用户、系统用户管理、权限分配、根据用户角色权限动态加载菜单、密码修改、插件整合等,详见本文说明

    20190701

    V1.1.0

    相对上一版本:

    1. 添加了bootstrap-table插件、实现了对数据表采用此插件进行增删改查的功能;
    2. 添加了layuidate插件,使日期选择功能更完善、UI交互更友好

    20190703

    V1.2.0

    相对上一版本:

    1.将项目服务端重构为springboot+mybatis架构;

    2.整合wangeditor编辑器;

    3.新增两个demo示例方便后续复制粘贴式并最少改动代码方式开发;

    4.新增文件管理(普通上传文件与wangeditor编辑器上传与文件访问统一控制器)

    20210714

    V1.2.1

    相对上一版本:
    1.添加图片裁剪插件;

    2.添加图片压缩处理;

    20210720

    撰写本文档目的是让后续开发者在理解该系统架构的基础上遵循一定规范保持系统架构的合理性;同时也能够达到允许没有开发经验仅有web基础的入门开发者能够通过复制粘贴的方式仿照demo示例进行开发的目的。

    目  录

    1       案例调研与选取... 3

    1.1       案例调研... 3

    1.2       UI选取... 4

    2       系统实现... 4

    2.1       实现效果... 4

    2.2       开发规范... 9

    3       详细设计... 10

    3.1       框架介绍... 10

    3.2       代码说明... 11

    3.3       数据库设计... 13

    3.4       菜单管理... 13

    3.5       权限管理/角色管理... 17

    3.6       权限管理/权限分配... 18

    3.7       权限管理/用户管理... 19

    3.8       Demo示例... 19

    3.9       文件管理... 20

    4       延伸思考... 20

    5       致谢! 20

    6       文档说明... 21

    7       参考文献... 21

    1. 案例调研与选取
      1. 案例调研

    1)easyUI(No1)

    图片

    2)easyUI(No2)

    图片

    3)Bootstrap

    图片

    4)vue/iview

    图片

    以上四套UI框架对比分析,可以得出如下结论

    结论:

    easyUI功能完善,界面简洁友好,非常方便后端开发人员开发,是优秀的前端开源框架,尤其适合后台管理,但是非响应式,页面不会随屏幕大小而变化,美观方面(仁者见仁);

    bootstrap是响应式开源框架,支持插件广泛,界面相对酷炫,美观方面(有目共睹),同样也非常适合管理平台的开发;

    至于Vue和其它一些前端人员自己写的UI框架,必须要承认Vue是不错的开源框架,但是个人感觉对管理平台来说Vue增加了开发人员的学习成本、兼容性、美观等方面的调试成本,开发周期偏长,至于是否适合管理品台开发就……;

    综上分析,对于管理平台开发建议选用easyUI或基于bootstrap搭建好的管理平台,本文选择基于bootstrap的管理平台进行说明。

      1. UI选取

    经过调研,选取了一套业内好评率较高的UI(ace-master),

    Ace是一个基于Twitter bootstrap3开发的后台模板。

    GitHub Ace地址:https://github.com/bopoda/ace

    Ace演示:http://ace.jeka.by/

    主体界面如下:

    此框架功能多多,详细功能请看演示。

    1. 系统实现
      1. 实现效果
    1. 登录

    2)首页

    3)以下是权限管理的具体模块

     

     

      1. 开发规范

    下图为框架的三个区域,其中主面板区域采用为一个div(没有采用iframe设计),每个菜单的内容均会更新主面板区域,故在主面板区域内容需要遵循一定的规范:

    1. 建议每个一级菜单在一个包中,每个包中的二级菜单均为一个单独的控制器。建议页面也需按同样方式设计。
    2. 每个页面中的字段必须全局唯一very import

    每个页面中的字段可采用驼峰式也可用下划线式,但必须确保每个页面以及下面多级页面中的每个字段名必须不同(即使业务上为同一张表的同一个字段),不可在模态框与主面板区用同一个页面。(如此设计的原因是:由于主页面采用div设计,故为防止js检测异常)

    1. (important)由于主面板区域采用div设计,父页面(main.jsp)中已经有了

    <script src="view/manage/assets/js/jquery-2.1.4.min.js"></script>

    故子页面面不要引入这个js了(也无需引入),否则会引起密码修改的模态框无法弹出;

    如果想要引入的话,请修改密码修改的模态框弹出效果。

    命名规范示例:

    每个页面中字段命名(包括方法名、表单字段、div等元素的id等):  模块名+页面名+数据库字段名

    示例:userManageListAccountName

           或者    user_manage_list_account_name

    这样组成了全局唯一字段,防止浏览器缓存导致的页面插件功能异常和表单提交异常等问题;

    此问题已经在最新版本中修复

    1. 详细设计
      1. 框架介绍

    1)页面布局

    页面布局见开发规范中截图,三个主要区域。

    2)功能

    功能上主要为权限管理和其它的项目相关的开发人员自定义的菜单模块。前后端交互采用ajax技术,页面核心的公共区域的交互在

    <script src="view/manage/assets/js-ylz/utils.js"></script> 该文件中封装了菜单url调用和菜单效果切花、主面板区域更新的ajax、菜单树的动态加载、解析、拼装等功能。

    3)权限

    权限管理中包括用户管理、菜单管理、角色管理、权限分配和密码修改。

    4)菜单加载

    用户状态为启用时可登录到系统,进入到主板面后根据用户对应角色查找相应的菜单加载到菜单区域,从而实现不同角色的用户能够看到不同的菜单权限。

    5)插件

    框架中整合的插件主要如下(部分):

    Bootstrap-table、bootstrap-datetimepicker、jquery.gritter(右上角弹框插件)、bootstrap-treeview、bootstrap-switch、jQuery.ui(确认框)。

    其中datetimepicker样式似乎并没有想象中的好,需要进一步确认原因还是切换其它插件,如果对样式要求不高可临时使用,但考虑到后续扩展,故而建议尽快确认(修复or更换)。

      1. 代码说明

      1. 数据库设计

    数据库中权限管理模块设计了用户表、角色表、菜单表、用户角色关联表、角色菜单关联表,共计5张表,sql代码详见数据库文件。

    用户表:

    角色表:

    菜单表:

    用户角色关联表:

    角色菜单关联表:

      1. 菜单管理

    菜单包括主页面菜单区域的菜单也包含“权限管理à菜单管理”中的菜单。

    1)主页菜单封装:

    菜单表设计,见数据库设计。

    菜单最大设计四级菜单,拼装的json格式(下文为大致示例,以实际为准);

    读取库中菜单信息,拼接采用何种算法?

    方案一:循环遍历,多重循环遍历

    方案二:递归

    此处选择递归,原因一是效率高(内存需要或许也高,完全可容忍),二是不受限于菜单级别,

    递归核心代码如下(详见源码

    /**
    
          * 递归查找子菜单
    
          * @param id
    
          * @param rootMenu
    
          * @return
    
          */
    
         private List<Map> getChilds(Long id, List<SysMenu> rootMenu){
    
             // 子菜单
    
             List<Map> childList = new ArrayList<Map>();
    
            
    
             Iterator<SysMenu> it = rootMenu.iterator();
    
             while(it.hasNext()) {
    
                  SysMenu menu = it.next();
    
                  // 遍历所有节点,将父菜单id与传过来的id比较
    
                  if (String.valueOf(menu.getLong("menu_pa_id")).equals(String.valueOf(id))){
    
                       Map<String,Object> mapcc = new HashMap<String,Object>();
    
                       mapcc.put("id", menu.getLong("id"));
    
                       mapcc.put("menu_name", menu.getStr("menu_name"));
    
                       mapcc.put("menu_url", menu.getStr("menu_url"));
    
                       childList.add(mapcc);
    
                       it.remove();
    
                  }
    
             }
    
             // 把子菜单的子菜单再循环一遍
    
             for (Map map : childList) {
    
                  //递归
    
                  map.put("childMenus", getChilds(Long.parseLong(map.get("id").toString()), rootMenu));
    
             }
    
             //递归退出条件
    
             if (childList.size() == 0) {
    
                  return null;
    
             }
    
             return childList;
    
         }
    
    拼接得到json菜单格式为(如下为二级菜单示例,其它详见源码、界面操作):
    
    {
        "status":"200",
        "data":[
            {
                "id":1,
                "childMenus":null,
                "menu_url":"/manage/systemInfo.do",
                "menu_name":"系统信息"
            },
            {
                "id":2,
                "childMenus":[
                    {
                        "id":5,
                        "childMenus":null,
                        "menu_url":"/redis/main.do",
                        "menu_name":"查询redis"
                    },
                    {
                        "id":6,
                        "childMenus":null,
                        "menu_url":"/redis/writeRdisPage.do",
                        "menu_name":"写redis"
                    }
                ],
                "menu_url":null,
                "menu_name":"redis管理"
            },
            {
                "id":3,
                "childMenus":[
                    {
                        "id":7,
                        "childMenus":null,
                        "menu_url":null,
                        "menu_name":"榴莲短视频"
                    },
                    {
                        "id":8,
                        "childMenus":null,
                        "menu_url":"/haohuolab/haohuoPage.do",
                        "menu_name":"东龙实验室"
                    }
                ],
                "menu_url":null,
                "menu_name":"东龙实验室"
            },
            {
                "id":4,
                "childMenus":[
                    {
                        "id":9,
                        "childMenus":null,
                        "menu_url":"/system/users/userPages.do",
                        "menu_name":"用户管理"
                    },
                    {
                        "id":10,
                        "childMenus":null,
                        "menu_url":null,
                        "menu_name":"角色管理"
                    },
                    {
                        "id":11,
                        "childMenus":null,
                        "menu_url":null,
                        "menu_name":"权限分配"
                    },
                    {
                        "id":12,
                        "childMenus":null,
                        "menu_url":null,
                        "menu_name":"菜单管理"
                    },
                    {
                        "id":13,
                        "childMenus":null,
                        "menu_url":"/manage/updatePwdPages.do",
                        "menu_name":"密码修改"
                    }
                ],
                "menu_url":null,
                "menu_name":"权限管理"
            }
        ],
        "msg":"success"
    }

    2)菜单解析

    上面是拼接菜单代码,下面是解析菜单代码:

    解析菜单的时候踩了一个坑,就是二级菜单在浏览器端始终无法打开,反复调试到晚上十一二点始终不知道什么原因,第二天来了之后继续调试,最终发现是a标签上缺少了一个属性(class='dropdown-toggle'),有时可能就是很小的一个问题让你耽误很长很长的时间还弄的自己焦头烂额,深感有时阻碍你前进的可能不是那万里征程(搭建整套完善框架),却可能是脚下的一粒沙子。

    废话少说,直接上递归核心代码(实际略有改动,详见源码):

    /**
    
     * 递归遍历子树
    
     * @param list
    
     */
    
    function mainPageRecurSubTree(ctx,list){
    
             if(null==list || ""==list || "null"==list){
    
                       return "";
    
             }
    
             var mainPageRecurSubTreeStr = "";
    
             mainPageRecurSubTreeStr +=
    
                       "<ul class='submenu'>";
    
             for(var m=0;m<list.length;m++){
    
                       var menuSub = list[m];
    
                       mainPageRecurSubTreeStr +=
    
                                "<li class='' id='mainPageMenuTreeId"+menuSub.id+"'>"+
    
                                         "<a onclick=\"javascript:updateMenuTree('mainPageMenuTreeId"+menuSub.id+"','"+ctx+"','"+menuSub.menu_url+"');\" class='dropdown-toggle'>"+
    
                                                   "<i class='menu-icon fa fa-caret-right'></i>"+
    
                                                   menuSub.menu_name;
    
                                                   if(null!=menuSub.childMenus && ""!=menuSub.childMenus && "null"!=menuSub.childMenus){
    
                                                            mainPageRecurSubTreeStr +=
    
                                                            "<b class='arrow fa fa-angle-down'></b>";
    
                                                   }
    
                       mainPageRecurSubTreeStr +=
    
                                         "</a>"+
    
                                         "<b class='arrow'></b>"+
    
                                         mainPageRecurSubTree(ctx,menuSub.childMenus)+
    
                                "</li>";
    
             }
    
             mainPageRecurSubTreeStr +=
    
                       "</ul>";
    
             return mainPageRecurSubTreeStr;
    
    }

    3)权限管理/菜单管理

    菜单插件采用bootstrap-treeview插件,

    开关按钮采用bootstrap-switch插件;注意:将所需的开关插件放入到main.jsp中,开关样式方可正常引用,否则如果放到每个功能模块的子页面中会导致插件无法完全加载而导致的样式显示的问题。

    菜单管理页面中添加根菜单,也可添加子菜单,选择/修改菜单的上级菜单,修改菜单信息等功能。

      1. 权限管理/角色管理

    权限管理à角色管理:

    角色管理中的菜单权限修改(修改角色对应的菜单信息):

    也采用了bootstrap-TreeView插件,但是此原生的树菜单没有级联选项,故添加级联选择的js,核心代码如下:

    //级联选择:选中
    
                          $("#roleManageUpdateRoleMenuAllTreeMes").on('nodeChecked',function(event,node){
    
                                         roleManageUpdateRoleMenuNodeChecked(event, node);;
    
                                     });
    
                                     //级联选择:取消选中
    
                                     $("#roleManageUpdateRoleMenuAllTreeMes").on('nodeUnchecked',function(event,node){
    
                                         roleManageUpdateRoleMenuNodeUnchecked(event, node);;
    
                                     });
    
    //如下是响应菜单选中和取消选中的操作
    
                  var roleManageUpdateRoleMenuNodeCheckedSilent = false;
    
                  function roleManageUpdateRoleMenuNodeChecked(event, node){
    
                       if(roleManageUpdateRoleMenuNodeCheckedSilent){
    
                            return;
    
                       }
    
                       roleManageUpdateRoleMenuNodeCheckedSilent = true;
    
                       roleManageUpdateRoleMenuCheckAllParent(node);
    
                       roleManageUdpateRoleMenuCheckAllSon(node);
    
                       roleManageUpdateRoleMenuNodeCheckedSilent = false;
    
                  }
    
    
    
                  var roleManageUpdateRoleMenuNodeUncheckedSilent = false;
    
                  function roleManageUpdateRoleMenuNodeUnchecked(event, node){
    
                       if(roleManageUpdateRoleMenuNodeUncheckedSilent){
    
                           return;
    
                       }
    
                       roleManageUpdateRoleMenuNodeUncheckedSilent = true;
    
                       roleManageUpdateRoleMenuUncheckAllParent(node);
    
                       roleManageUpdateRoleMenuUncheckAllSon(node);
    
                       roleManageUpdateRoleMenuNodeUncheckedSilent = false;
    
                  }
    
    
    
                  //选中全部父节点
    
                  function roleManageUpdateRoleMenuCheckAllParent(node){
    
                       $("#roleManageUpdateRoleMenuAllTreeMes").treeview('checkNode',node.nodeId,{silent:true});
    
                       var parentNode = $("#roleManageUpdateRoleMenuAllTreeMes").treeview('getParent',node.nodeId);
    
                       if(!("nodeId" in parentNode)){
    
                           return;
    
                       }else{
    
                           roleManageUpdateRoleMenuCheckAllParent(parentNode);
    
                       }
    
                  }
    
                  //取消全部父节点
    
                  function roleManageUpdateRoleMenuUncheckAllParent(node){
    
                       $("#roleManageUpdateRoleMenuAllTreeMes").treeview('uncheckNode',node.nodeId,{silent:true});
    
                       var siblings = $("#roleManageUpdateRoleMenuAllTreeMes").treeview('getSiblings', node.nodeId);
    
                       var parentNode = $("#roleManageUpdateRoleMenuAllTreeMes").treeview('getParent',node.nodeId);
    
                       if(!("nodeId" in parentNode)) {
    
                           return;
    
                       }
    
                       var isAllUnchecked = true;  //是否全部没选中
    
                       for(var i in siblings){
    
                           if(siblings[i].state.checked){
    
                                isAllUnchecked=false;
    
                                break;
    
                           }
    
                       }
    
                       if(isAllUnchecked){
    
                           roleManageUpdateRoleMenuUncheckAllParent(parentNode);
    
                       }
    
                  }
    
    
    
                  //级联选中所有子节点
    
                  function roleManageUdpateRoleMenuCheckAllSon(node){
    
                       $("#roleManageUpdateRoleMenuAllTreeMes").treeview('checkNode',node.nodeId,{silent:true});
    
                       if(node.nodes!=null&&node.nodes.length>0){
    
                           for(var i in node.nodes){
    
                                roleManageUdpateRoleMenuCheckAllSon(node.nodes[i]);
    
                           }
    
                       }
    
                  }
    
                  //级联取消所有子节点
    
                  function roleManageUpdateRoleMenuUncheckAllSon(node){
    
                       $("#roleManageUpdateRoleMenuAllTreeMes").treeview('uncheckNode',node.nodeId,{silent:true});
    
                       if(node.nodes!=null&&node.nodes.length>0){
    
                           for(var i in node.nodes){
    
                                roleManageUpdateRoleMenuUncheckAllSon(node.nodes[i]);
    
                           }
    
                       }
    
                  }

      1. 权限管理/权限分配

    权限管理à权限分配:为不同用户分配不同角色。

    在权限分配è角色分配  页面中,使用了一个多选框的插件(用于选择多个角色),如下图:

    在使用中发现这个选择框第一次打开时正常,之后再打开始终不正常,调试发现是因为select中动态添加了一个div并且这个div的style=“width:0px”;导致select的展示出现问题。试了各种方式,网上搜了各种方案均失败。最终万般无奈之下猜想可能是引用的js文件中生成这个内部div时导致宽度获取的问题,于是便修改引用的js源码,修改如下:

    <script src="view/manage/assets/js/chosen.jquery.min.js"></script>

    至此问题解决。

    问:如何知道要修改这个宽度(如何定位到是要修改这个宽度的)?

    答:在浏览器中调试时发现在select中生成的div的id是在select的id的基础之上添加了“_chosen”,于是搜索“_chosen”发现整个js源码中只有一个“_chosen”,于是在此附近寻找width相关的代码,终于发现了并尝试修改成功。

      1. 权限管理/用户管理

    权限管理à用户管理:功能为对能够登录到系统的管理用户的增、查、修改、停用操作。

    此页面中的table采用bootstrap原生表格,增改查的逻辑完全为自己实现。没有使用bootstrap-table插件。

    本系统设计者建议使用bootstrap-table插件(why? 我也不知道,就是感觉成熟开源的业内小有名气的东东一定比自己写的好),插件demo见系统demo示例。

    此模块中的用户为系统的管理人员。

      1. 文件管理

    此项目将文件全部存储到了域项目同级目录下并提供文件访问的controller,这么设计的好处:1)避免因为项目发布导致文件误删;2)项目迁移同步拷贝文件即可,无需关心机器、地址等问题;

    文件结构:

    1. 延伸思考

    1. Iframe为子页面,可不受父页面干扰,但是究竟用还是不用好,有待深思的问题;
    2. bootstrap-switch boostrap的开关按钮插件并未能初始化开或者关状态,此功能关乎开关的美观,需探究如何修改或选用其它插件待进一步深思。

    3)系统待优化之处:

    权限访问控制该如何优化(内存?redis?)

    1. 致谢!

    初级入门:泽宇、老申、昊总

    前端顾问:张走召

    问题修复:金凤

    问题修复:系统参与的全体java同仁

    开发者:战神,彭玉,ylz,东龙;

    零碎不重要的整理工作(高大上的名字:秘书):本人。

    向以上四位开发者致敬!

    1. 文档说明

    本文档由四位开发者在开发过程中心得记录,由秘书整理汇总而成。最终解释权归四位开发者所有。

    1. 参考文献

    https://blog.csdn.net/weixin_41981080/article/details/81912941

    文末福利:

    想要与大家一起交流,可进企鹅群:589847567

    群共享文件中有源码下载。

    说明:该系统由以上四位开发者在工作之余抽时间分工开发完成,因工作较忙,时间有限等原因,系统中难免有瑕疵不足之处需进一步完善,望大家谅解,在后续版本中我们会不断完善。同时诚邀大才雄心的有志之士加入我们共同开发。

    展开全文
  • django 提供了比较完善的后台管理数据库的接口,可供开发过程中调用和测试使用 django 会搜集所有已注册的模型类,为这些模型类提拱数据管理界面,供开发者使用 使用步骤: 创建后台管理帐号: 后台管理–创建管理员...

    admin 后台数据库管理

    • django 提供了比较完善的后台管理数据库的接口,可供开发过程中调用和测试使用
    • django 会搜集所有已注册的模型类,为这些模型类提拱数据管理界面,供开发者使用
    • 使用步骤:
      1. 创建后台管理帐号:
        后台管理–创建管理员帐号
        -$ python3 manage.py createsuperuser

            $ python3 manage.py createsuperuser
            Username (leave blank to use 'tarena'): tarena  # 此处输入用户名
            Email address: laowei@tedu.cn  # 此处输入邮箱
            Password: # 此处输入密码(密码要复杂些,否则会提示密码太简单)
            Password (again): # 再次输入重复密码
            Superuser created successfully.
            $ 
            ```
        
        
      2. 用注册的帐号登陆后台管理界面

    自定义后台管理数据表

    • 若要自己定义的模型类也能在 /admin 后台管理界中显示和管理,需要将自己的类注册到后台管理界面
    • 添加自己定义模型类的后台管理数据表的,需要用admin.site.register(自定义模型类) 方法进行注册
      • 配置步骤如下:
        1. 在应用app中的admin.py中导入注册要管理的模型models类, 如:
          from . import models
          
        2. 调用 admin.site.register 方法进行注册,如:
          from django.contrib import admin
          admin.site.register(自定义模型类)
          
      • 如: 在 bookstore/admin.py 添加如下代码对Book类进行管理
      • 示例:
        # file: bookstore/admin.py
        from django.contrib import admin
        # Register your models here.
        
        from . import models
        ...
        admin.site.register(models.Book)  # 将Book类注册为可管理页面
        

    修改后台Models的展现形式

    • 在admin后台管理数据库中对自定义的数据记录都展示为 XXXX object 类型的记录,不便于阅读和判断
    • 在用户自定义的模型类中可以重写 def __str__(self): 方法解决显示问题,如:
      • 在 自定义模型类中重写 str(self) 方法返回显示文字内容:
      class Book(models.Model):
          ...
          def __str__(self):
              return "书名" + self.title
      

    模型管理器类

    • 作用:

      -为后台管理界面添加便于操作的新功能。

    • 说明:

      -后台管理器类须继承自 django.contrib.admin 里的 ModelAdmin

    • 模型管理器的使用方法:

      1. <应用app>/admin.py 里定义模型管理器类
        class XXXXManager(admin.ModelAdmin):
            ......
        
      2. 注册管理器与模型类关联
        from django.contrib import admin
        from . import models
        admin.site.register(models.YYYY, XXXXManager) # 注册models.YYYY 模型类与 管理器类 XXXXManager 关联
        
      • 示例:
        # file : bookstore/admin.py
        from django.contrib import admin
        from . import models
        
        class BookManager(admin.ModelAdmin):
            list_display = ['id', 'title', 'price', 'market_price']
        
        admin.site.register(models.Book, BookManager)
        
    • 模型管理器类ModelAdmin中实现的高级管理功能

      1. list_display 去控制哪些字段会显示在Admin 的修改列表页面中。
      2. list_display_links 可以控制list_display中的字段是否应该链接到对象的“更改”页面。
      3. list_filter 设置激活Admin 修改列表页面右侧栏中的过滤器
      4. search_fields 设置启用Admin 更改列表页面上的搜索框。
      5. list_editable 设置为模型上的字段名称列表,这将允许在更改列表页面上进行编辑。
      6. 其它参见https://docs.djangoproject.com/en/1.11/ref/contrib/admin/

    数据库表管理

    1. 修改模型类字段的显示名字
      • 模型类各字段的第一个参数为 verbose_name,此字段显示的名字会在后台数据库管理页面显示
      • 通过 verbose_name 字段选项,修改显示名称示例如下:
        title = models.CharField(
            max_length = 30,
            verbose_name='显示名称'
        )
        
    2. 通过Meta内嵌类 定义模型类的属性及展现形式
      • 模型类可以通过定义内部类class Meta 来重新定义当前模型类和数据表的一些属性信息
      • 用法格式如下:
        class Book(models.Model):
            title = CharField(....)
            class Meta:
                1. db_table = '数据表名'
                    - 该模型所用的数据表的名称。(设置完成后需要立马更新同步数据库)
                2. verbose_name = '单数名'
                    - 给模型对象的一个易于理解的名称(单数),用于显示在/admin管理界面中
                3. verbose_name_plural = '复数名'
                    - 该对象复数形式的名称(复数),用于显示在/admin管理界面中
        

    数据表关联关系映射

    • 常用的表关联方式有三种:
      1. 一对一映射
        -如: 一个身份证对应一个人
      2. 一对多映射
        -如: 一个班级可以有多个学生
      3. 多对多映射
        -如: 一个学生可以报多个课程,一个课程可以有多个学生学习

    一对一映射

    • 一对一是表示现实事物间存在的一对一的对应关系。
    • 如:一个家庭只有一个户主,一个男人有一个妻子,一个人有一个唯一的指纹信息等

    语法

    class A(model.Model):
        ...
    class B(model.Model):
        属性 = models.OneToOneField(A)
    

    外键类字段选项

    • 特殊字段参数:

      • on_delete
        1. models.CASCADE 级联删除。 Django模拟SQL约束ON DELETE CASCADE的行为,并删除包含ForeignKey的对象。
        2. models.PROTECT 抛出ProtectedError 以阻止被引用对象的删除;[等同于mysql默认的RESTRICT]
        3. SET_NULL 设置ForeignKey null;需要指定null=True
        4. SET_DEFAULT 将ForeignKey设置为其默认值;必须设置ForeignKey的默认值。
        5. … 其它参请参考文档 https://docs.djangoproject.com/en/1.11/ref/models/fields/#foreignkey ForeignKey部分
    • 其余常用的字段选项如:

      1. null
      2. unique 等

    用法示例

    1. 创建作家和作家妻子类
      # file : xxxxxxxx/models.py
      from django.db import models
      
      class Author(models.Model):
          '''作家模型类'''
          name = models.CharField('作家', max_length=50)
      
      class Wife(models.Model):
          '''作家妻子模型类'''
          name = models.CharField("妻子", max_length=50)
          author = models.OneToOneField(Author)  # 增加一对一属性 
      
    2. 创建一对一的数据记录
      from . import models
      
      #方案1  外键属性名 = 对象
      author1 = models.Author.objects.create(name='王先生')
      wife1 = models.Wife.objects.create(name='王夫人', author=author1)  # 关联王老师
      
      #方案2  外键字段名 = 关联对象的主键值
      author2 = models.Author.objects.create(name='吕先生')  # 一对一可以没有数据对应的数据 
      w2 = Wife.objects.create(name='吕夫人', author_id=author2.id)
      
      
      
      
    3. 数据查询
      1. 正向查询 wife -> author
        -直接通过关联属性查询即可

        # 通过 wife 找 author
        from . import models
        wife = models.Wife.objects.get(name='王夫人')
        print(wife.name, '的老公是', wife.author.name)
        
      2. 反向查询 author -> wife

        • 通过反向关联属性查询
        • 反向关联属性为实例对象.引用类名(小写),如作家的反向引用为作家对象.wife
        • 当反向引用不存在时,则会触发异常
        # 通过 author.wife 关联属性 找 wife,如果没有对应的wife则触发异常
        author1 = models.Author.objects.get(name='王先生')
        print(author1.name, '的妻子是', author1.wife.name)
        author2 = models.Author.objects.get(name='吕先生')
        try:
            print(author2.name, '的妻子是', author2.wife.name)
        except:
            print(author2.name, '还没有妻子')
        
    • 作用:

    • 主要是解决常用数据不常用数据的存储问题,把经常加载的一个数据放在主表中,不常用数据放在另一个副表中,这样在访问主表数据时不需要加载副表中的数据以提高访问速度提高效率和节省内存空间,如经常把书的内容和书名建成两张表,因为在网站上经常访问书名等信息,但不需要得到书的内容。

    • 1, 第三方授权

    • 2,数据分离

    • 3,开发过程 - > 新手问题

    一对多映射

    • 一对多是表示现实事物间存在的一对多的对应关系。
    • 如:一个学校有多个班级,一个班级有多个学生, 一本图书只能属于一个出版社,一个出版社允许出版多本图书
    1. 用法语法

      • 当一个A类对象可以关联多个B类对象时
      class A(model.Model):
          ...
      
      class B(model.Model):
          属性 = models.ForeignKey("一"的模型类, ...)
      
    2. 用法示例

      • 有二个出版社对应五本书的情况.
        1. 清华大学出版社 有书

          1. C++
          2. Java
          3. Python
        2. 北京大学出版社 有书

          1. 西游记
          2. 水浒
      1. 创建数据
      # file: one2many/models.py
      from django.db import models
      class Publisher(models.Model):
      '''出版社'''
          name = models.CharField('名称', max_length=50, unique=True)
      
      class Book(models.Model):
          title = models.CharField('书名', max_length=50)
          publisher = models.ForeignKey(Publisher)
          
      #创建数据
      from . import models
      #方案1
      pub1 = models.Publisher.objects.create(name='清华大学出版社')
      models.Book.objects.create(title='C++', publisher=pub1)
      models.Book.objects.create(title='Java', publisher=pub1)
      models.Book.objects.create(title='Python', publisher=pub1) 
      
      #方案2
      pub2 = models.Publisher.objects.create(name='北京大学出版社')
      

    models.Book.objects.create(title=‘西游记’, publisher_id=pub2.id)
    models.Book.objects.create(title=‘水浒’, publisher_id=pub2.id)

    1. 数据查询
     通过 Book 查询 Publisher【正向】
    ```
    通过 publisher 属性查询即可
    book.publisher
     
    abook = models.Book.objects.get(id=1)
    print(abook.title, '的出版社是:', abook.publisher.name)
    ```
    
    通过 Publisher 查询 对应的所有的 Books 【反向】
    ```python
    Django会在Publisher中增加一个属性来表示对对应的Book们的查询引用
    属性:book_set  等价于 objects
    
    # 通过出版社查询对应的书
    pub1 = models.Publisher.objects.get(name='清华大学出版社')
    books = pub1.book_set.all()  # 通过book_set 获取pub1对应的多个Book数据对象
    #books = models.Book.objects.filter(publisher=pub1)  # 也可以采用此方式获取
    print("清华大学出版社的书有:")
    for book in books:
       print(book.title)
    ```
    

    多对多映射

    • 多对多表达对象之间多对多复杂关系,如: 每个人都有不同的学校(小学,初中,高中,…),每个学校都有不同的学生…
    1. 语法
      -在关联的两个类中的任意一个类中,增加:

      属性 = models.ManyToManyField(MyModel)
      
    2. 示例
      -一个作者可以出版多本图书
      -一本图书可以被多名作者同时编写

      class Author(models.Model):
          ...
      
      class Book(models.Model):
          ...
          authors = models.ManyToManyField(Author)
      
    3. 数据查询

      1. 通过 Book 查询对应的所有的 Authors【正向】
        book.authors.all() -> 获取 book 对应的所有的author的信息
        book.authors.filter(age__gt=80) -> 获取book对应的作者中年龄大于80岁的作者的信息
        
      2. 通过 Author 查询对应的所有的Books【反向】
        • Django会生成一个关联属性 book_set 用于表示对对应的book的查询对象相关操作
        author.book_set.all()
        author.book_set.filter()
        author.book_set.create(...)  # 创建新书并关联author
        author.book_set.add(book)   # 添加已有的书给当前作者author
        author.book_set.clear()  # 删除author所有并联的书
        
    4. 用法示例:

      • 多对多模型
      class Author(models.Model):
          '''作家模型类'''
          name = models.CharField('作家', max_length=50)
          def __str__(self):
              return self.name
          
      class Book(models.Model):
          title = models.CharField('书名', max_length=50)
          author = models.ManyToManyField(Author)
          def __str__(self):
         		return self.title 
      
      • 多对多视图操作

    from django.http import HttpResponse
    from . import models

    def many2many_init(request):
        # 创建两人个作者
        author1 = models.Author.objects.create(name='吕先生')
        author2 = models.Author.objects.create(name='王先生')
    
        # 吕先生和王先生同时写了一本Python
        book11 = author1.book_set.create(title="Python")
        author2.book_set.add(book11)  #
    
        # 王先生还写了两本书
        book21 = author2.book_set.create(title="C")  # 创建一本新书"C"   
        book22 = author2.book_set.create(title="C++")  # 创建一本新书"C++"
    
        return HttpResponse("初始化成功")
    
    def show_many2many(request):
        authors = models.Author.objects.all()
        for auth in authors:
            print("作者:", auth.name, '发出版了', auth.book_set.count(), '本书: ')
            for book in books:
                print('    ', book.title)
        print("----显示书和作者的关系----")
        books = models.Book.objects.all()
        for book in books:
            auths = book.author.all()
            print(book.title, '的作者是:', '、'.join([str(x.name) for x in auths]))
        return HttpResponse("显示成功,请查看服务器端控制台终端")
    ```
    - 多对多最终的SQL结果
    ```sql
    mysql> select * from many2many_author;
    +----+-----------+
    | id | name      |
    +----+-----------+
    | 11 | 吕先生     |
    | 12 | 王先生   |
    +----+-----------+
    2 rows in set (0.00 sec)
    
    mysql> select * from many2many_book;
    +----+--------+
    | id | title  |
    +----+--------+
    | 13 | Python |
    | 14 | C      |
    | 15 | C++    |
    +----+--------+
    3 rows in set (0.00 sec)
    
    mysql> select * from many2many_book_author;
    +----+---------+-----------+
    | id | book_id | author_id |
    +----+---------+-----------+
    | 17 |      13 |        11 |
    | 20 |      13 |        12 |
    | 18 |      14 |        12 |
    | 19 |      15 |        12 |
    +----+---------+-----------+
    4 rows in set (0.00 sec)
    ```
    
    展开全文
  • 实现简单网页上对数据内容进行增删改查,需要用到三个部分,分别是jsp网页部分+java后台部分+数据库表 我用一个新闻的例子来实现,首先编写java后台程序 java后台程序: 我们用三层的模式进行设计:分别是...

    在实现简单网页上对数据内容进行增删改查,需要用到三个部分,分别是jsp网页部分+java后台部分+数据库表

    我用一个新闻的例子来实现,首先编写java后台程序

     

    java后台程序:

    我们用三层的模式进行设计:分别是servlet,service,dao层,并且建立个实体包用来打包数据库和后台要用到的属

    性截个图

    首先是写功能写的顺序分别是从servlet,service,dao层:

    servlet层代码如下:

     

    public class TypeServlet {
    
    	TypeService ts=new TypeServiceImp();//调用service层
    	/*******添加************************************************************************************/
    	public int addtype(String name){
    		int a=0;
    		a=ts.addtype(name);
    		return a;
    	}
    	/*******查看************************************************************************************/
    	public List<types> selets(){
    		List<types> list=new ArrayList<types>();
    		list=ts.selets(null);
    		return list;	
    	}
    	/*******删除************************************************************************************/
    	public int delete(int id){
    		int a=0;
    		types t=new types();
    		t.setId(id);
    		a=ts.delete(t);
    		return a;
    	}
    	/*******修改************************************************************************************/
    	public int update(types t){
    		int a=0;
    		a=ts.update(t);
    		return a;
    	}
    	/*******查找一个************************************************************************************/
    	public types selectone(int id){
    		types t=new types();
    		t.setId(id);
    		types nt=ts.selectone(t);
    		return  nt;
    	}
    }

     

    Service层分为两层分别为接口层和实现层

     

    接口程序如下:

     

    public interface TypeService {
    
    	public int addtype(String name);
    	
    	public List<types> selets(types t);
    	
    	public int delete(types t);
    	
    	public int update(types t);
    	
    	public types selectone(types t);
    	
    }


    接口实现程序:

     

     

    public class TypeServiceImp implements TypeService{
    
    	TypeDao td= new TypeDaoImp();
    	
    	public int addtype(String name) {    //注意返回数据不要忘记修改
    		int a=0;
    		a=td.addtype(name);
    		return a;
    	}
    
    	public List<types> selets(types t) {
    		List<types> list=new ArrayList<types>();
    		list=td.selets(t);
    		return list;
    	}
    	/*******删除************************************************************************************/
    	public int delete(types t) {
    		int a=0;
    		a=td.delete(t);
    		return a;
    	}
    	/*******修改************************************************************************************/
    	public int update(types t) {
    		int a=0;
    		a=td.update(t);
    		return a;
    	}
    
    	/*******查找单个************************************************************************************/
    	public types selectone(types t){
    		types tp=new types();
    		tp=td.selectone(t);
    		return tp;
    		
    	}
    }

     

     

     

    Dao层程序同样分为接口层和实现层

    接口层程序:

     

    public interface TypeDao {
    
    	public int addtype(String name);
    	
    	public List<types> selets(types t);
    	
    	public int delete(types t);
    	
    	public int update(types t);
    	
    	public types selectone(types t);
    	
    }


    实现类程序:

     

     

    public class TypeDaoImp implements TypeDao{
    	Connection con=null;
    	PreparedStatement ps=null;
    	ResultSet rs=null;
    	
    	public int addtype(String name){
    		int a=0;
    		try {
    			//连接数据库
    			con=Shujuku.conn();
    			String sql="insert into typesname values(?)";   //设置id自增
    			ps=con.prepareStatement(sql);
    			ps.setString(1, name);
    			a=ps.executeUpdate();
    		} catch (SQLException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		return a;
    	}
    
    	public List<types> selets(types t) {
    		List<types> list=new ArrayList<types>();
    		try {
    			//连接数据库
    			con=Shujuku.conn();
    			String sql="select*from typesname";  
    			ps=con.prepareStatement(sql);
    			rs=ps.executeQuery();
    			while(rs.next()){
    				types ty=new types();
    				ty.setId(rs.getInt("id"));
    				ty.setTypename(rs.getString("typename"));
    				list.add(ty);
    			}
    		} catch (SQLException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		return list;
    	}
    	/*******删除************************************************************************************/
    	public int delete(types t) {
    		int a=0;		
    		try {
    			con=Shujuku.conn();
    			String sql="delete from typesname where id="+t.getId();
    			ps=con.prepareStatement(sql);
    			a=ps.executeUpdate();
    		} catch (SQLException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		return a;
    	}
    	/*******修改************************************************************************************/
    	public int update(types t) {
    		int a=0;
    		try {
    			con=Shujuku.conn();
    			String sql="update typesname set typename=? where id=?";
    			ps=con.prepareStatement(sql);
    			ps.setString(1, t.getTypename());
    			ps.setInt(2, t.getId());
    			a=ps.executeUpdate();
    		} catch (SQLException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		return a;
    	}
    	/*******查找一个************************************************************************************/
    	public types selectone(types t) {
    		types tp=new  types();
    		try {
    			con=Shujuku.conn();
    			String sql="select * from typesname where id=?";
    			ps=con.prepareStatement(sql);
    			ps.setInt(1, t.getId());
    			rs=ps.executeQuery();
    			if(rs.next()){
    				tp.setId(rs.getInt("id"));
    				tp.setTypename(rs.getString("typename"));
    			}
    		} catch (SQLException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}	
    		return tp;
    	}
    }

     

     

     

    最后就是数据库包,为了方便使用,将数据库的驱动连接信息建立一个包存放:

    代码如下:

     

    public class Shujuku {
    
    	public static Connection conn(){
    		//定义地址
    		String url="jdbc:sqlserver://localhost:1433;DatabaseName=test;";
    	    //定义连接初始值
    		Connection connection=null;	
    		try {
    			//加载驱动
    			Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
    			//建立连接
    		     connection=DriverManager.getConnection(url, "sa", "DCX5201314");
    			} catch (SQLException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			
    		} catch (ClassNotFoundException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}	
    		return connection;	
    	}
    }


    属性包,代码如下:

     

     

    public class types {
    	private int id;
    	private String typename;
    	public int getId() {
    		return id;
    	}
    	public void setId(int id) {
    		this.id = id;
    	}
    	public String getTypename() {
    		return typename;
    	}
    	public void setTypename(String typename) {
    		this.typename = typename;
    	}
    }

     

     

     

    java后台程序就这么多;

     

    接下来是数据库部分:

    数据库部分主要就是建立一张表,笔者使用的是SQL Server 2008,首先建个数据库test,建立个表typesname,设置两列分别为id typename,id设为主键,int 型,自增为1;typename设置类型为varchar型,不能为空。

     

    好了,数据库和java后台都搭建好了,现在来到前端网页部分,

     

    网页部分

    在myeclipse中新建7个jsp文件

     

    index.jsp是一个总的网页

    设置代码如下:

     

    </head>
    	<frameset rows="20%,80%">
    		<frame src="head.jsp">
    		<frameset cols="20%,80%">
    			<frame src="left.jsp">
    			<frame src="right.jsp" name="rights">
    		</frameset>
    	</frameset>
    	<body>
    	</body>

    head.jsp

     

     

    <body>  
    <h1>这是头部</h1>
    </body>

     

    left.jsp

     

    <body>
        <h1>这是左边</h1>
        <ul>
           <li><a href="addtype.jsp" target="rights">添加新闻类型</a></li>
           <li><a href="showtype.jsp" target="rights">查看新闻类型</a></li>
        </ul>
      </body>

    right.jsp

     

     

    <body>
        <h1>这是右边</h1>
     </body>

    addtype.jsp

     

     

    </head>
      <%
        request.setCharacterEncoding("UTF-8");
        String name= request.getParameter("typename");
        if(name!=null){
        	TypeServlet tp=new TypeServlet();
        	int a=tp.addtype(name);
        	if(a>0){
        		RequestDispatcher rd = request
    			.getRequestDispatcher("showtype.jsp");
        		rd.forward(request, response);
        	}else{
        		RequestDispatcher rd = request
    			.getRequestDispatcher("addtype.jsp");
        		rd.forward(request, response);
        	}
        }
      %>
      <body>
        <h1>添加新闻类型</h1><hr/>
        <form action="addtype.jsp" method="post">
        新闻类型:<input type="text" name="typename"></br>
            <input type="submit" value="提交">
        </form>
      </body>

    showtype.jsp

     

     

    <script type="text/javascript">
    function deletes_(id){
    	 
       var f=confirm("是否确定删除?");
       if(f){
       location.href="showtype.jsp?ids="+id;
       }else{
       alert("您取消删除");
       }
    }
    
    function update(id){
    	location.href="updatetype.jsp?ids="+id;
    }
    </script>
      </head>
      <%
      request.setCharacterEncoding("UTF-8");
      String id=request.getParameter("ids");
      String type=request.getParameter("type");
      if(id!=null){	
    	      TypeServlet ts=new TypeServlet();
    		  int a = ts.delete(Integer.parseInt(id));
    		  response.sendRedirect("showtype.jsp"); 
    	      
      }
       %>
      <body>
        <h1> 展示类型</h1>
        <table border="1">
        <tr><td>编号</td><td>类型名称</td><td>操作</td></tr>
        <%
        //直接调用后台数据
         TypeServlet ts=new TypeServlet();
         List<types> list=ts.selets();
         for(int i=0;i<list.size();i++){
         types n=list.get(i);
         %>
         <tr>
      <td><%=n.getId() %></td>
      <td><%=n.getTypename() %></td>
      <td><input type="button" onclick="update(<%=n.getId() %>)" value="修改"/>
        
         <input type="button" onclick="deletes_(<%=n.getId() %>)" value="删除"/></td>
      </tr>
        <%
         }
         %>
      </body>

    updatetype.jsp

     

    <body>
        <% 
        request.setCharacterEncoding("UTF-8");
         String id=request.getParameter("ids");
        TypeServlet tsl=new TypeServlet();
        types ts=new types();
        String type= request.getParameter("type");
        if(type!=null){
        	String typename=request.getParameter("newtype");//从下面的输入取值
        	String id1=request.getParameter("id");
        	ts.setId(Integer.parseInt(id1));//强转
        	ts.setTypename(typename);
        	int a=tsl.update(ts);
        	response.sendRedirect("showtype.jsp");
        }else{
        	  if(id!=null){
        		     ts=tsl.selectone(Integer.parseInt(id));
        		  }
        		  }
        %>
        
        <h1>修改新闻类型界面</h1>
        <hr/>
        <form action="updatetype.jsp" method="post">
        <input type="hidden" name="type" value="3">
        <input type="hidden" name="id" value="<%=ts.getId() %>">
          新闻类型:<input type="text" value="<%=ts.getTypename() %>" name="newtype"><br/>
          <input type="submit" value="提交">
        </form>
      </body>

     

     

     

    最终项目在tomcat上发布。

    下面的地址积分系统调的太高了,我重新上传了一份内容是一样的地址在这:http://download.csdn.net/download/qq_34178998/10154005

    高积分下载打包文件在这:http://download.csdn.net/download/qq_34178998/9920064

    也可以参考在这篇基础上的两个表关联操作:http://blog.csdn.net/qq_34178998/article/details/77017760

    有问题也希望各位提出,一起进步,

    没积分的留言。留下邮箱,我看到会给你发的,但是太多的,可能会漏发,见谅!!!

    也欢迎转载!!!也欢迎转载!!!也欢迎转载!!!

    需要代码的人多,直接上传百度云了,大家自己下载,喜欢的话给我点个赞 链接:https://pan.baidu.com/s/1YPUWpI4A3Q54V0_d-cunxg 提取码:pzey

    点个赞点个赞点个赞点个赞点个赞

     

     

    展开全文
  • 这是一个基于MVC用Java实现的一个简易的购物网站后台管理,还和数据库有连接,可以实现查询、修改、删除操作,有需要的可以看看。
  • 后台数据库采用Mysql数据库进行支持,界面美化是利用Adobe PhotoshopCS6图片处理软件进行处理的。本系统从使用者角度出发,界面友好美观,人机信息交互灵活、方便、快捷,安全可靠,系统同时具有很大的可扩充性。...
  • 自由宿主后台管理系统是一套通用后台管理系统,之所以给他加上“宿主”2个字,是因为这套系统本身没有自己的数据库,而必须依赖于其他数据库才能运行,自由指的是系统灵活性强,能够根据数据库表结构做一些简单的...
  • Jsp制作企业后台数据库管理系统

    千次阅读 2018-07-05 23:01:08
    一、在任何管理网站都需要的一个是登录系统登录界面,所以先制作一个登录界面。㈠、命名login.jsp 下面是我制作此表单页面的代码 表单name/id为Login登录名username,为了美观我在前面加了图片01.gif密码框...

    一、在任何管理网站都需要的一个是登录系统登录界面,所以先制作一个登录界面。

    ㈠、

    命名login.jsp

     

    下面是我制作此表单页面的代码

     

    表单name/idLogin

    登录名username,为了美观我在前面加了图片01.gif


    密码框possword,为了美观我在前面加了图片02.gif

     

    提交/重置按钮,可用空格来调整他的位置

    我在提交/重置按钮的这个单元格里面,在它们的右边添加了“用户注册”加上超链接,当点击他时跳转到“用户注册”页面

     

    ㈡、在这个表单页面里面我加入了一个显示动态时间的一个功能,也就是能够动态的显示时间,没分每秒都在变化的。

    利用获取静态时间的方法制作动态时间效果:在之前做的项目中用到显示时间的都是一些静态的时间也就是当你进入这个网页时获取的时间,然后若想用这个静态时间的方法来实现动态时间的效果则需要将页面分为框架形式,然后将显示静态时间的js放到这个框架里面再不断的刷新这个框架才能实现动态时间的效果。

    直接利用js来实现动态时间的效果:这里我用一个div来装这个js,大部分都是用div来装这个js才能有效果

     

    代码:


    <div id="time"><script>

    document.getElementById('time').innerHTML='当前时间: '+new Date().toLocaleString()+' 星期'+'日一二三四五六'.charAt(new Date().getDay());

    setInterval("document.getElementById('time').innerHTML='当前时间: '+new Date().toLocaleString()+' 星期'+'日一二三四五六'.charAt(new Date().getDay());",1000);

    </script></div>

    记得在页面顶部导入包


    ㈢、我在这个页面中加入了之前项目中的头文件,将之前的头文件head.jsp复制到项目中,然后在login.jsp头部加入 <%@include file="head.jsp" %>

     

    ㈣、在用户没有输入任何东西就点击登录时,我们给他一个弹出窗口进行提示,在这里需要加入一个js来实现。

     

    代码:    <script language=javascript>

    <!-- 

    function CheckForm(){

    if(document.Login.username.value==""){

    alert("请输入用户名!");

    document.Login.username.focus();

    return false;}

    if(document.Login.password.value == ""){

    alert("请输入密码!");

    document.Login.password.focus();

    return false;}}

    </script>

    //alert为弹出窗口时所需要显示的提示内容


    ㈤、设计数据库新建qiye.mdb

    1)建立data文件夹

         新建qiye.mdb

    2)建立表admin,表结构如下图

    输入数据

     

    在后期的增删查改可用到

    ㈥、新版本JDK没有带jdbc-odbc链接桥,如何实现链接?

    1、下载数据库链接驱动程序Access_JDBC30.jar

    2、把驱动部署到WEB-INF\lib目录下。

    刷新,能识别驱动。

     


     

    3装载驱动程序

       Class.forName("com.hxtt.sql.access.AccessDriver");

    4连接数据库

       String path="jdbc:Access:///"+getServletContext().getRealPath("/").replaceAll("\\\\", "/")+"qiye.mdb";

    //数据库路径从根文件WebContent开始算

    Connection con = DriverManager.getConnection(path);

     

    二、在完成登录页面后需要一个检查的页面

    ㈠命名为chk_login.jsp

    整体的代码

     

    首先导入数据库的包<%@page import="java.sql.*" %>,凡是有用到数据库的页面都必须导入此包

    对于数据库的操作我一起放在最下面,同时需要对数据库操作完毕后 才能对以下的页面进行连接

    三、建立一个总页面session.jsp此页面为一个大框架

     

    代码:

    此页面又三部分组成top.jsp  zb.jsp  yb.jsp三个页面

    阻止非法用户绕过登陆访问管理员页面:在用户没有登录的时候访问这个页面页面将弹出一个提示窗口然后会跳转会登录界面(要直接将session.jsp网页直接打开才看得出效果)

     

    此效果要在session.jsp中加入

    <%

    if((String)session.getAttribute("login_name")==null){

    out.println("<script LANGUAGE='javascript'>alert('请先登陆');window.location.href='login.jsp';</script>");

    return;

    }

    %>

     

    这种效果在往后的登录系统中都可以用上

    2. 分页框架top.jsp

    总体代码:

    加上某某某欢迎登录效果

     

    “企业欢迎你”字体的前面加上<%=session.getAttribute("login") %>用户,用来获取登录名

     

    “企业欢迎您”字体的后面加上图片“重新登录”加上超链接让点击他时跳转到登录界面

     

    然后再在总体的table后面加上非法阻止登录的代码(和上面的那句一样的)

     

    3. 分页框架zb.jsp


    “注册用户管理”上加上超链接点击它时跳转到regester.jsp让它在mainframe中显示,也就是在中间的框架上显示。

     

    同理在“后台用户管理”上加超链接点击时跳转到user_info.jsp

     

    四、在点击后台管理时跳转到用户后台管理系统用于浏览用户的信息

    1. 命名为user_info.jsp

     

    页面整体代码:

     


    2. 做好这个表单布局后在表单中的大表格中加入连接数据库的语句

      <%

    try{

    Class.forName("com.hxtt.sql.access.AccessDriver");

    }

    catch(ClassNotFoundException e){}

    try {

    String path="jdbc:Access:///"+getServletContext().getRealPath("/").replaceAll("\\\\", "/")+"qiye.mdb";

        Connection con = DriverManager.getConnection(path);     

    Statement sql=con.createStatement();

          ResultSet rs; //建立ResultSet(结果集)对象

          rs = sql.executeQuery("Select * from admin"); //执行SQL语句

    %>   记得导入<%@page import="java.sql.*" %>

    这个语句几乎是固定的,在往后的 数据库连接中也可以借鉴这个语句

    3. 在表格的登录名以及权限位置的下面这个表格上(也就是j0所在的单元格里)分别

     

    加入<%=rs.getString("username")%><%=rs.getString(4)%>

     

    此操作就是使用上面的ResultSet对象的rs.getString()读取数据表字段的数据,读出账号和权限放到相应的单元格。

    4.在这一行所在的单元的大表格代码上面加循环语句  <%

      while(rs.next()){

     

      int id=rs.getInt("id");

    //在列表中列出id

     

    %>

    让表格可以不断的列下去

     

    5.在后面就要把数据库给关闭了:

     <%

      }

      con.close();

      }

    catch(SQLException e1){}

      %>

      放在最外面的表格结束标签内

     

    6. 若你所做的这个user_info.jsp页面不在session页面中的中间框架中显示时可在“用户管理”后面加一个返回照片加上链接让点击它时可跳回到session页面中

     

    五、注册表单页面

    1. 命名为regester.jsp

    页面效果:

     

    整体代码:

     


    表单属性<form action="add.jsp" method="post" name="Login" target="_parent" id="Login" onSubmit="return CheckForm();">

    账号:username

    密码:password

    权限:purview,普通管理员值0,超级管理员值1

     

    2. 其实也就是将登录页面login.jsp页面改了一下,加多了一个权限列表

     

     

    3. 在提交按钮的右边像登录页面那样加“用户登录”字体,加上超链接,点击时可跳转到登录界面

     

     

    六、

    1创建一个add.jsp页面与regester.jsp对接,在注册时可把新用户添加进数据库

    1.命名add.jsp

    页面整体代码:

     


    1.基本语句和chk_login.jsp差不多,先数据库连接 然后记得加上int purview=Integer.parseInt(request.getParameter("purview"));来获取他的“权限”

     

    2. chk_login.jsp不同的是重点、难点语句:String condition="insert into admin(username,password,purview)values('"+username+"','"+password+"',"+purview+")";

    这里的瑕疵在于:注册功能的实现其实就是将用户信息添加到数据表user_info,所以可以改为*/

    //String condition="insert into user_info values('"+username+"','"+password+"',"+purview+")";

    3. 在注册时如果所注册的用户名已经存在了则需要一个弹出窗口进行提示


    点击确定按钮后重新跳转回注册页面regester.jsp页面。

    代码:  

    out.print("<script LANGUAGE='javascript'>alert('您输入的用户名已经存在!请重新输入!');window.location.href='regester.jsp';</script>");


    4.同理,如果注册成功则跳出一个窗口提示“注册成功”并且跳转到用户后台编辑页面user_info.jsp

     

     

     

     

    2把所添加的用户信息从数据库和表中删除

    1.(下面的操作在user_info中进行)

    修改user_info.jsp在循环语句后面添加获取记录id语句

    <%

      while(rs.next()){

      int id=rs.getInt("id");

    %>  (前面的user_info.jsp已经给出来了)

    在表格后面加图片“删除.png”在图片上添加链接,点击时可提交到del.jsp处理,达到删除。

    <a href="del.jsp?id=<%=id%>"><img src="imgbey/删除.png" width="30" height="30"></a>

     

    2. 创建一个del.jsp页面


    整体代码:

    前面就是数据库的连接,记得导入包就行,重点在String condition="delete from admin where id="+id;语句,这里要之前的那些语句改为“delete from”删除语句。

     

    然后就是重复前面页面上的提示窗口操作了(其实我觉得在这个加一个形式为“是否删除”-“确定”“返回” 然后当点击确定时再弹出“删除用户成功”的这种提示窗口,在后面我会努力改进一下)

     


    3修改编辑用户信息

    1.(下面的操作在user_info中进行)

    修改user_info.jsp,“修改”下面的单元格种加入图片“编辑.png

     

    再在图片上加上超链接,点击时提交给edit.jsp进行操作,在超链接标签中加入href="edit.jsp?id=<%=id%>"进行传递参数

     

    2.创建进行编辑处理的edit.jsp页面

    整体效果:

    整体代码:

    3. 首页对edit页面表单的布置(可将login.jsp登录界面或者regester.jsp注册页面复制归来进行改动一下就可以了)

     

    表单名称为:update

    <form action="Update.jsp?id=<%=rs.getInt("id")%>" method="post" name="update" target="" id="update" οnsubmit="return CheckForm();">

    增加确认密码:密码文本框,名称为password2

    然后添加js,作用为检查确认密码是否空,检查密码和确认密码是否一致。

         <script language=javascript>

    function CheckForm()

    {

    if(document.update.password.value=="")

    {

    alert("请输入密码!");

    document.update.password.focus();

    return false;

    }

    if(document.update.password2.value=="")

    {

    alert("请输入确认密码!");

    document.update.password2.focus();

    return false;

    }

    if(document.update.password.value !=document.update.password2.value)

    {

    alert("密码和确认密码不一致!");

    document.update.password2.focus();

    return false;}}</script>

     


    4. 完成edit.jsp动态部分:取出原用户数据,获取传递过来的id,连接数据库,按id查询出该用户数据,把相应的字段在相应表单中显示:

     

    这段代码最好放在表单标签的前面。

    ⑴取出用户账号,在单元格中显示出来,账号不可修改:

    <%=rs.getString("username")%>

     

     

    ⑵取出用户密码给密码密码文本框设置初始值(在第一个密码框中操作):

    <%=rs.getString("password")%>

     

     

    ⑶对管理员的身份进行判断,在权限列表中添加

    <%

      String ch1,ch2;

      if(rs.getInt("purview")==1){

      ch1="selected='selected'";

      ch2=null;

      }

      else{

      ch1=null;

      ch2="selected='selected'";

      }

     %>

     

    记得在下面的“普通管理员”“超级管理员”中给他们赋个值ch1ch2

     

    ⑷最后数据库连接关闭

    <%

    con.close();

    }

    catch(SQLException event){}

     

    %>

    在最后一个</table>前加

     

    3更新用户信息,在修改用户信息后需要在数据库中更新

    1.创建Update.jsp

     

    在后面加上一个跳转页面 out.print("<script LANGUAGE='javascript'>alert('修改用户成功');window.location.href='user_info.jsp';</script>");

     

     

    最后我们整个项目的进程近乎结尾了,下面就是我们数据库连接技术了

    七、

    以下便为数据库的连接步骤

    Sqlmysql在上面的页面中连接的方式不同)

    例如

    途中我注释了sqlmysql连接的语句,而且记得将jar放在bin

     

    八、JSP连接SQL Server

    1、登录常见问题

    如果连接不上数据库,请看服务器名称为是否为主机名加实例名SQLEXPRESS

     

    例如,我这里就要改为B40391\SQLEXPRESS才能连上

    2、验证模式

    选择服务器→属性→安全性

     

     

    服务器身份验证选择SQL ServerWindows身份验证模式

     

    设置登录名和密码选择资源管理器服务器安全性登录名→sa” 

     

    右键打开属性面板,设置登录密码,这里设置为123456。

     

    选择状态”选项设置是否允许连接到数据库引擎设置授予登录设置 启用”。

     

    3、打开SQL Server配置管理器

    SQL Server网络配置 – SQLEXPRESS的协议

     

    TCP/IP右键启用

     

    然后右键属性IP地址为127.0.0.1启用选择是

     

    IPAII设置TCP端口为1433

     

    然后重启SQL Server服务器 SQL Server服务 --  SQL Server(SQLEXPRESS)右键重新启动

     

    4、测试sa用户名是否成功:

     

    正常登录,验证设置成功。

     

    6、加载驱动。

    JDBC驱动sqljdbc42.jar下载分别放到JDK安装目录的jre/lib/ext文件夹中,和Tomcat的安装目录的lib目录下

     

    sqljdbc”sqljdbc42”粘贴到Webcontent中的WEB-INF中的lib文件夹中

     

     

     

    chk_login.jsp

    //连接mysql数据库

       /*String path="jdbc:Access:///"+getServletContext().getRealPath("/").replaceAll("\\\\", "/")+"qiye.mdb";/*获取数据库路径*/

    //数据库路径从根文件WebContent开始算

          /*Connection con = DriverManager.getConnection(path);*/注释

    然后在下面加一段Connection con = DriverManager.getConnection("jdbc:sqlserver://localhost;DatabaseName=qiye;user=sa;password=111111");

    7、测试应用程序

    JSP连接SQL Server配置已经成功了,接下来测试是否连接成功

    测试代码:

    <%@ page language="java" contentType="text/html; charset=UTF-8"

          pageEncoding="UTF-8"%>

    <%@page import="java.sql.*" %>

    <!DOCTYPE HTML>

    <html>

    <head>

    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

    <title>test_sql</title>

    </head>

    <body>

    <%

    try{

        Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");//加载驱动

      //Connection conn= DriverManager.getConnection("jdbc:sqlserver://localhost;DatabaseName=Test;user=sa;password=123456");//数据库名test,用户名sa,密码123456

      Connection conn= DriverManager.getConnection("jdbc:sqlserver://localhost;DatabaseName=qiye;user=sa;password=123456");//数据库名qiye,用户名sa,密码123456

        String sql = "select * from admin";//查询语句

       Statement stmt=conn.createStatement();

       ResultSet rs = stmt.executeQuery(sql);

    ResultSetMetaData rsMetaData = rs.getMetaData();

        int numberOfColumns = rsMetaData.getColumnCount();//获取查询结果的列数

         while(rs.next()){

         for(int i=1;i<=numberOfColumns;i++){

         out.print(rs.getString(i)+"\t");

         }

         out.print("<br>");

       }

         out.println("successful!");//连接数据库成功时输出successful!

     }catch(Exception e){

     e.printStackTrace();

     out.println("数据库驱动加载错误");

        }

    %>

    </body>

    </html>

    显示数据表的内容:

     

    则表示连接数据库成功!

     

    6. 若数据库的源添加不了

    方法一:Mdf文件和ldf文件右击-属性-安全-Authenticated Users-编辑-勾选完全控制-应用

    方法二:打开数据库实例的安装目录,打开DATA文件夹。(如我的实例目录地址为:D:\Microsoft SQL Server\MSSQL10.MSSQLSERVER\MSSQL\DATA 也可能当时安装时装在C盘了)
    将要附加的数据库.mdf文件和.ldf文件,剪切或复制到DATA文件夹里。

     

    九、JSP连接MySQL

    把mysql-connector-java-5.1.45-bin.jar下载文件复制jdk的安装目录下的jre\lib\ext的文件夹下Tomcatlib目录下。

     

     

    测试代码:

    <%@ page language="java" contentType="text/html; charset=UTF-8"

          pageEncoding="UTF-8"%>

    <%@page import="java.sql.*" %>

    <!DOCTYPE HTML>

    <html>

    <head>

    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

    <title>mysql</title>

    </head>

    <body>

    <%

    try{

         Class.forName("com.mysql.jdbc.Driver");//加载驱动

         Connection conn= DriverManager.getConnection("jdbc:mysql://localhost/world?user=root&password=123456");//数据库名world,用户名root,密码123456

         String sql = "select * from city";//查询语句

         Statement stmt=conn.createStatement();

         ResultSet rs = stmt.executeQuery(sql);

         ResultSetMetaData rsMetaData = rs.getMetaData();

        int numberOfColumns = rsMetaData.getColumnCount();//获取查询结果的列数

         while(rs.next()){

         for(int i=1;i<=numberOfColumns;i++){

         out.print(rs.getString(i)+"\t");

         }

         out.print("<br>");

         }     out.println("successful!");//连接数据库成功时输出successful!

     }catch(Exception e){

     e.printStackTrace();

        }

    %>

    </body>

    </html>

    显示successful!则表示连接数据库成功!

     

    以上便是数据库连接教程,需对应其中的页面进行操作,在这个企业后台管理项目中还可以加入分页技术,浮窗效果等等的技术,有待添加。谢谢

    展开全文
  • 网站后台管理系统框架(修正版) 发布一个网站后台管理框架.源作者非本人.只是借用做了下修改,感觉蛮实用的. 仅仅是一个Access数据库实现的后台框架,比较精美实用 可以实现菜单的多级控制并结合js进行动态显示 ...
  • 自由宿主后台管理系统是一套通用后台管理系统,之所以给他加上“宿主”2个字,是因为这套系统本身没有自己的数据库,而必须依赖于其他数据库才能运行,自由指的是系统灵活性强,能够根据数据库表结构做一些简单的...
  • 网站管理后台帐号密码暴力破解方法

    万次阅读 多人点赞 2018-07-30 17:12:43
    对于网站运行的个人站长而言,最担心的是应如何有效且安全的去管理自己的网站,否则自己辛辛苦苦经营的网站就会被不请自来的不速之客给攻破,轻则站点数据被窃取,重则整个网站都被攻陷,导致无法恢复。 本文主要从...
  • Pycharm+Django+Python+MySQL开发(一)后台管理数据库

    万次阅读 多人点赞 2016-08-19 18:51:53
    Django搭建后台管理系统,对接数据库
  • 前言 ´・ᴗ・` 创建ROOT账户 admin注册ORM模型 打开服务器运行吧 修改一下语言 进一步修改... 对更新数据的页面 我们可以这么魔改 inline 内联式的录入数据 `__str__` 总结 ´◡`
  • 自由宿主后台管理系统是一套通用后台管理系统,之所以给他加上“宿主”2个字,是因为这套系统本身没有自己的数据库,而必须依赖于其他数据库才能运行,自由指的是系统灵活性强,能够根据数据库表结构做一些简单的...
  • 古诗网站后台实现

    千次阅读 2018-11-14 16:21:06
    用户输入用户名和密码,点击登录系统按钮,在后台首先在cookie中获取用户登录相关信息,如果获取失败再获取用户的输入,对用户输入的数据进行校验并再数据库中查询用户,如果查询失败,再前台页面显示相应的提示信息...
  • 发布一个网站后台管理框架.源作者非本人.只是借用做了下修改,感觉蛮实用的. 仅仅是一个Access数据库实现的后台框架,比较精美实用 可以实现菜单的多级控制并结合js进行动态显示 后台地址:manage/...
  • 自由宿主后台管理系统是一套通用后台管理系统,之所以给他加上“宿主”2个字,是因为这套系统本身没有自己的数据库,而必须依赖于其他数据库才能运行,自由指的是系统灵活性强,能够根据数据库表结构做一些简单的...
  • 1、 网站后台:主要包括登陆、主页管理、分类管理、文章管理、评论管理、标签管理、图片管理、用户管理添加的功能、删除、查询的功能。单页面实现bootstrap模态框ajax数据操作,使用SqlBulkCopy批量添加,js标签增...
  • 网站管理后台被破解实例

    万次阅读 多人点赞 2018-03-12 00:00:00
    本文来自作者 泰泰 在 GitChat 上分享 「网站管理后台被破解原理分析及实例演示」编辑 | 哈比对网站运行的个人站长而言,最担心的是应如何有效且安全的去管理自己的网站。一旦自己辛辛苦苦经营的网站被不速之客...
  • urls.properties中需要修改为你本地的静态文件的访问路径。 使用Java平台,采用SpringMVC+Mybatis等主流框架 数据库:使用免费MYSQL 前端:使用Jquery和Easyui技术.界面清晰简洁,易操作 权限:对菜单,按钮控制.仅展示...
  • 项目说明:用PHP实现电影信息添加,修改,删除,分为前台管理和后台管理,前台用户可以浏览信息和发布留言,后台分页可以管理电影信息和管理留言+3713字说明文档。 一、功能说明 1、管理员添加、删除、修改、查询...
  • 网站后台管理快速构建一、基于XML定制的列表查询及图表展现,快速构建信息管理系统或数据查询分析系统二、列表实现了复杂查询条件、合并行列(分组求和的处理)、汇总行及钻取数据和图表三、编辑配置支持单表数据的...
  • contentManagerSystem,后台管理系统,采用SpringBoot构建整个项目框架,apacheShiro权限验证,mybatis+druid数据持久化动作,前端采用layui(http://www.layui.com/)展示, 整个项目全部通过注解方式进行配置,具体大家...
  • 电子商务网站后台管理系统

    千次阅读 2010-07-08 00:51:00
    一、订单管理系统完善的电子商务网站就像一个ERP系统一样,可以在网站实现订单管理、物流管理、财务管理等诸多功能。对于中小企业来说,由于自身技术实力的限制,难以构建基于网络的ERP系统,在这种情况下,退而求...
  • 网上商店后台管理系统的设计与实现,本系统是一个典型的网上交友系统,在技术上主要使用了ASP开发技术和SQL Server 2000数据库技术。前台功能模块:该模块主要包括查询交友信息、显示交友信息、会员登录、会员信息...
  • SSM + Layui实现后台管理系统

    万次阅读 多人点赞 2019-08-22 13:11:44
    适合于刚学习了SSM框架,想找项目练手的同学,那么本例非常适合你,...SSM+Layui 后台管理 如果对您有帮助,点点关注,加个 star,会不断更新噢! 宠辱不惊,闲看庭前花开花落 去留无意,漫随天外云卷云舒
  • 我一直以来就在纳闷意见事情,就是像csdn一样,用户...首先这个显然不可能通过前端的来实现,因为前段的东西到用户那里最终是放到内存里面,内存是有易失性,那么就应该是放在后台,同样的,我们也不可能去直接修改
  • 网站后台管理系统模板
  • 后台管理系统 – 权限管理

    万次阅读 多人点赞 2018-11-21 14:23:35
    不管是开发手机APP,网站还是小程序等项目,基本上都需要一个后台管理系统的支撑。而每个后台管理系统都有一个通用的功能就是用户权限管理。最近基于Antd+React.js做了一个后台管理系统。
  • 基于Python搭建Django后台管理系统

    万次阅读 多人点赞 2018-01-05 10:54:33
    一个好的项目数据库管理后台是必须的,今天代码君教大家搭建Django网站后台,当然做网站后台的前提是需要有Python以及Django的开发环境,至于如何搭建这些开发环境,请查看我的上一篇文章 Mac 基于Python搭建Django...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 65,307
精华内容 26,122
关键字:

网站数据库后台管理实现修改