• asp.net学习_分页的设计


    分页是每一个程序员都每天都在打交道的东西,分页.

    一年前,刚接触的时候,根本不知道什么叫做分页,后台,xxx说,如果数据过多一次,成千上万条,你一次只看到10-20条,为什么要全部显示呢?当时感觉很震撼,为什么呢?

    以下内容是以前的代码(不要扔鸡蛋,我现在看了都有恨不得砸电脑的冲动)

    于是我们就用了第一个分页版本,当时,两个实验室的"战士"研究了好久,找到一个存储过程的分页,当时感觉好神奇!找找当时凌乱的分页调用程序:

    image

    现在看了都要砸电脑的冲动的东东.....

    后来做web,凌乱依旧,web版本的分页程序,

    image

    image

    后来才发现一个叫做aspnetpager的控件,发现好强大呀,易用,方便,而且不用写那么复杂的存储过程以及调用,

    image

    image

    慢慢的发现,这些控件都是死的,写死的东西,根本没有灵活性,特别是美工做个好看点的分页之类的,只能干瞪眼,要不就按照它的格式做分页样式,这是一个纠结的问题,

    既然不灵活,为什么不自己做控件?

    后来就自己写分页的用户控件....

    不过仍然不够灵活,上网找资料.

    发现,手写一个分页类就行了,分页不就是计算页面大小,然后输出页码和连接么?

    然后就是这个版本

       1:    //  //记录日志
       2:      private static readonly log4net.ILog logger = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
       3:      //输出的PagerHtml代码
       4:      public string PagerHtml = "";
       5:      protected void Page_Load(object sender, EventArgs e)
       6:      {
       7:          try
       8:          {
       9:              string TypeId = Request["TypeId"];
      10:              //查询条件
      11:              string strCondition = "";
      12:              //字符串注入检测
      13:              if (!string.IsNullOrEmpty(TypeId) && Tools.IsValidInput(ref TypeId, true))
      14:                  strCondition = "TypeId=" + TypeId;
      15:   
      16:              //分页实现
      17:              var pager = new Common.RupengPager();
      18:              pager.UrlFormat = "NewsList.aspx?pagenum={n}&TypeId=" + TypeId;
      19:              pager.PageSize = 30;
      20:              pager.TryParseCurrentPageIndex(Request["pagenum"]);
      21:   
      22:              //分页数据读取
      23:              newsBLL bll = new newsBLL();
      24:              DataTable dt = bll.ListByPaginationForView("Time", pager.PageSize, pager.CurrentPageIndex, "1", strCondition);
      25:   
      26:              //获取总页数
      27:              pager.TotalCount = bll.GetVNewsListCount(strCondition);
      28:              rpData.DataSource = dt;
      29:              rpData.DataBind();
      30:   
      31:              //渲染页码条HTML
      32:              PagerHtml = pager.Render();
      33:          }
      34:          catch (Exception ex)
      35:          {
      36:              logger.Error("错误:", ex);
      37:          }
      38:      }

    效果也就是这样:

    前台就是

       1:  <%@ Page Language="C#" MasterPageFile="~/InfoPage.master" AutoEventWireup="true" CodeFile="NewsList.aspx.cs" Inherits="News_NewsList" Title="新闻列表" %>
       2:   
       3:  <asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server">
       4:      <link href="../css/other.css" rel="stylesheet" type="text/css" />
       5:      <link href="../css/Pager.css" rel="stylesheet" type="text/css" />
       6:  </asp:Content>
       7:  <asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
       8:      <%--GetNewsTypeInfoForNewsByJson--%>
       9:   
      10:     <div class="list">
      11:          <div class="list_title"><h4>新闻列表</h4><span>当前位置:<a href="../Default.aspx">首页</a> > 新闻列表</span></div>
      12:          <ul>
      13:              <asp:Repeater ID="rpData" runat="server">
      14:              <ItemTemplate>
      15:               <li><a href='ViewNews.aspx?NewsId=<%#Eval("Id") %>'>[<%#Eval("TypeName")%>]<%#Eval("Title")%></a><span><%#Eval("Time")%></span></li>
      16:              </ItemTemplate>
      17:              </asp:Repeater>
      18:          </ul>
      19:          <div class="page">
      20:                <p><div class="pager"><%=PagerHtml%></div></p>
      21:                 
      22:          </div>
      23:      </div>
      24:   
      25:  </asp:Content>
      26:   

    效果图:

    image

    这样仍然有一些问题:

    为什么一定要后台处理呢?

    为什么后台要做这些显示相关的?

    后台只负责提供数据,而界面实现,完全应该由js解决......

    因此,就有了现在这个版本....

    上网研究了一下Jquery pager,然后在他的基础上,该改改,然后就有了现在这个版本,后台只负责提供数据(json格式)

    前台负责界面显示

    js分页:

       1:  //Download by http://www.codefans.net
       2:  //每次只显示5个页码
       3:  //修改:2012/4/26
       4:  //tianzhuanghu
       5:  //http://www.cnblogs.com/mysweet/ 我的博客
       6:  (function($) {
       7:      //设定页码方法,初始化
       8:      $.fn.setPager = function(options) {
       9:          var opts = $.extend({}, pagerDefaults, options);
      10:          return this.each(function() {
      11:          //修改,能够动态设置PageSize
      12:              pagerDefaults.PageSize=options.PageSize;
      13:              $(this).empty().append(setPagerHtml(parseInt(options.RecordCount), parseInt(options.PageIndex), options.buttonClick));
      14:               $('.pager a').mouseover(function() { document.body.style.cursor = "pointer"; }).mouseout(function() { document.body.style.cursor = "auto"; });
      15:          });
      16:      };
      17:      //设定页数及html
      18:      function setPagerHtml(RecordCount, PageIndex, pagerClick) {
      19:              
      20:          var $content = $("<div class=\"pager\"></div>");
      21:          var startPageIndex = 1;
      22:          //若页码超出
      23:          if (RecordCount <= 0) RecordCount = pagerDefaults.PageSize;
      24:          var    PageSize=pagerDefaults.PageSize;
      25:          //alert(pagerDefaults.PageSize);
      26:          //末页
      27:          var endPageIndex = parseInt(RecordCount % parseInt(PageSize)) > 0 ? parseInt(RecordCount / parseInt(PageSize)) + 1 : RecordCount / parseInt(PageSize);
      28:   
      29:          if (PageIndex > endPageIndex) PageIndex = endPageIndex;
      30:          if (PageIndex <= 0) PageIndex = startPageIndex;
      31:          var nextPageIndex = PageIndex + 1;
      32:          var prevPageIndex = PageIndex - 1;
      33:          if (PageIndex == startPageIndex) {
      34:              $content.append($("<span>首页</span>"));
      35:              $content.append($("<span>上一页</span>"));
      36:          } else {
      37:   
      38:              $content.append(renderButton(RecordCount, 1, pagerClick, "首页"));
      39:              $content.append(renderButton(RecordCount, prevPageIndex, pagerClick, "上一页"));
      40:          }
      41:          //这里判断是否显示页码
      42:          if (pagerDefaults.ShowPageNumber) {
      43:              // var html = "";
      44:              //页码部分隐藏 只显示中间区域
      45:              if (endPageIndex <= 5 && PageIndex <= 5) {
      46:                  for (var i = 1; i <= endPageIndex; i++) {
      47:                      if (i == PageIndex) {
      48:                          $content.append($("<span>" + i + "</span>"));
      49:                      } else {
      50:                          $content.append(renderButton(RecordCount, i, pagerClick, i));
      51:                      }
      52:   
      53:                  }
      54:   
      55:              } else if (endPageIndex > 5 && endPageIndex - PageIndex <= 2) {
      56:   
      57:                  $content.append($("<a>...</a>"));
      58:                  for (var i = endPageIndex - 4; i <= endPageIndex; i++) {
      59:                      if (i == PageIndex) {
      60:                          $content.append($("<span>" + i + "</span>"));
      61:                      } else {
      62:                          $content.append(renderButton(RecordCount, i, pagerClick, i));
      63:                      }
      64:   
      65:                  }
      66:              } else if (endPageIndex > 5 && PageIndex > 3) {
      67:   
      68:                  $content.append($("<a>...</a>"));
      69:                  for (var i = PageIndex - 2; i <= PageIndex + 2; i++) {
      70:                      if (i == PageIndex) {
      71:                         $content.append($("<span>" + i + "</span>"));
      72:                      } else {
      73:                          $content.append(renderButton(RecordCount, i, pagerClick, i));
      74:                      }
      75:   
      76:                  }
      77:                 $content.append($("<a>...</a>"));
      78:   
      79:              } else if (endPageIndex > 5 && PageIndex <= 3) {
      80:   
      81:                  for (var i = 1; i <= 5; i++) {
      82:                      if (i == PageIndex) {
      83:                          $content.append($("<span>" + i + "</span>"));
      84:                      } else {
      85:                          $content.append(renderButton(RecordCount, i, pagerClick, i));
      86:                      }
      87:   
      88:                  }
      89:                 $content.append($("<a>...</a>"));
      90:              }
      91:          }
      92:          if (PageIndex == endPageIndex) {
      93:              $content.append($("<span>下一页</span>"));
      94:              $content.append($("<span>末页</span>"));
      95:          } else {
      96:              $content.append(renderButton(RecordCount, nextPageIndex, pagerClick, "下一页"));
      97:              $content.append(renderButton(RecordCount, endPageIndex, pagerClick, "末页"));
      98:          }
      99:   
     100:   
     101:          return $content;
     102:      }
     103:      function renderButton(recordCount, goPageIndex, EventHander, text) {
     104:          var $goto = $("<a title=\"第" + goPageIndex + "页\">" + text + "</a>\"");
     105:          $goto.click(function() {
     106:   
     107:              EventHander(recordCount, goPageIndex,pagerDefaults.PageSize);
     108:          });
     109:          return $goto;
     110:      }
     111:      var pagerDefaults = {
     112:          DefaultPageCount: 1,
     113:          DefaultPageIndex: 1,
     114:          PageSize:20,
     115:          ShowPageNumber: true //是否显示页码
     116:      };
     117:  })(jQuery);
    前台页面显示:
       1:  <%@ Page Language="C#" MasterPageFile="~/InfoPage.master" AutoEventWireup="true"
       2:      CodeFile="MasterList.aspx.cs" Inherits="Master_MasterList" Title="大师风采" %>
       3:   
       4:  <asp:Content ID="Content1" ContentPlaceHolderID="head" runat="Server">
       5:      <link href="../css/other.css" rel="stylesheet" type="text/css" />
       6:   
       7:      <script src="../Admin/scripts/jquery-1.7.1.min.js" type="text/javascript"></script>
       8:   
       9:      <script src="../js/jquery-pager-1.0.js" type="text/javascript"></script>
      10:   
      11:      <link href="../css/pager.css" rel="stylesheet" type="text/css" />
      12:   
      13:      <script type="text/javascript">
      14:          $(document).ready(function() {
      15:              //加载PageSize和页码PageIndex
      16:              GetData(1,1);
      17:          });
      18:          function InitPager(RecordCount, PageIndex,PageSize,Data) {
      19:          $("#Pager").setPager({ RecordCount: RecordCount, PageIndex: PageIndex,PageSize:PageSize, buttonClick: PageClick });
      20:              //页面数据填充
      21:         $("#tBodyMaster").empty();
      22:         $.each(Data,function(key,value){
      23:            //图片回调(集中请求)
      24:           var PicSrc="../Admin/FileManage/GetImg.ashx?method=GetMasterPic&type=medium&fileName="+Data[key].Picturepath;
      25:              var item='<tr><td><a href="'+"#"+'"><img src="'+PicSrc+'" title="'+Data[key].Name+'" alt="'+Data[key].Name+'"/><br/>'+Data[key].Name+'</a></td>';
      26:              item+='<td class="jianjie"><span>'+Data[key].Introduction+'</span></td>';
      27:              item+='<td class="adress"><a href="'+"#"+'">'+Data[key].Name+'的主页</a></td></tr>';
      28:         $("#tBodyMaster").append(item);
      29:         }); 
      30:          };
      31:          PageClick = function(RecordCount,PageIndex,PageSize) {
      32:               GetData(PageSize,PageIndex);
      33:          };
      34:          //sortField排序字段
      35:         function GetData(PageSize,PageIndex){
      36:         $.ajax({
      37:         url:'../Admin/MasterManage/Data/MasterInfo.ashx?method=SearchMaster',
      38:         //注意后台分页存储过程的PageIndex是从0开始的,所以这里要-1
      39:         data:'sortField=Id&sortOrder=desc&pageIndex='+(PageIndex-1)+'&pageSize='+PageSize,
      40:         success:function(text){
      41:         var jsonData=$.parseJSON(text);
      42:         InitPager(jsonData.total, PageIndex,PageSize,jsonData.data);
      43:         }
      44:         
      45:         });
      46:         }
      47:          
      48:      </script>
      49:   
      50:  </asp:Content>
      51:  <asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="Server">
      52:      <div class="list">
      53:          <div class="list_load">
      54:              <h3>
      55:                  大师风采</h3>
      56:              <span><a href="../Default.aspx">首页</a> > 大师风采</span>
      57:          </div>
      58:          <div class="ol">
      59:              <table width="680" border="0" cellpadding="0" cellspacing="0">
      60:                  <thead>
      61:                      <tr>
      62:                          <th width="160">
      63:                              大师名称
      64:                          </th>
      65:                          <th width="310">
      66:                              大师简介
      67:                          </th>
      68:                          <th width="210">
      69:                              大师个人网页
      70:                          </th>
      71:                      </tr>
      72:                  </thead>
      73:                  <tbody id="tBodyMaster">
      74:                   
      75:                  </tbody>
      76:              </table>
      77:          </div>
      78:          <div id="Pager">
      79:          </div>
      80:      </div>
      81:  </asp:Content>

    后台则负责数据的提供:

       1:    /// <summary>
       2:      /// 搜索调用
       3:      /// </summary>
       4:      /// <param name="context"></param>
       5:      public void SearchMaster(HttpContext context)
       6:      {
       7:          //查询条件
       8:          string key = context.Request["key"];
       9:          //分页
      10:          int pageIndex = Convert.ToInt32(context.Request["pageIndex"]);
      11:          int pageSize = Convert.ToInt32(context.Request["pageSize"]);
      12:          //字段排序
      13:          String sortField = context.Request["sortField"];
      14:          String sortOrder = context.Request["sortOrder"];
      15:          string strCondition = "";
      16:          //对搜索内容进行验证
      17:          if (!Common.Tools.IsValidInput(ref key, false))
      18:          {
      19:              return;
      20:          }
      21:          else 
      22:              strCondition = masterBLL.ConfirmCondition(key);//判断查询条件
      23:          masterBLL bll = new masterBLL();
      24:          //分页数据读取
      25:          IEnumerable<master> list = bll.ListByPagination(sortField, pageSize, pageIndex + 1, sortOrder == "asc" ? "1" : "0", strCondition);
      26:          //获取总页数
      27:          int totalPage = bll.GetCount(strCondition);
      28:          //JSON 序列化
      29:          string json = masterBLL.MiniUiListToJson(list, totalPage, "");
      30:   
      31:   
      32:          context.Response.Write(json);
      33:      }

    BLL生成json方法:(这个方法我是代码生成器写成一个模板,然后每次自动生成,免得每次都要写,哈哈哈)

       1:      /// <summary>
       2:          /// 专门生成为MiniUi生成json数据(List->json)
       3:          /// </summary>
       4:          /// <typeparam name="T">泛型</typeparam>
       5:          /// <param name="list">实现了Ilist接口的list</param>
       6:          /// <param name="total">记录总数</param>
       7:          /// <param name="paramMaxMin">这里放排序的参数例如,string para=""maxAge":37,"avgAge":27,"minAge":24"</param>
       8:          /// <returns>返回json数据</returns>
       9:          public static string MiniUiListToJson(IEnumerable<master> masterInfo, int total, string paramMaxMinAvg)
      10:          {
      11:              StringBuilder Json = new StringBuilder();
      12:              Json.Append("{\"total\":"+total+",\"data\":");
      13:              Json.Append("[");
      14:                  foreach (master Info in masterInfo)
      15:                  {
      16:                      Json.Append("{");
      17:                      Json.Append("\"Id\":\"" + Info.Id + "\"");
      18:                      Json.Append(",");
      19:                      Json.Append("\"Username\":\"" + Info.Username + "\"");
      20:                      Json.Append(",");
      21:                      Json.Append("\"Password\":\"" + Info.Password + "\"");
      22:                      Json.Append(",");
      23:                      Json.Append("\"Name\":\"" + Info.Name + "\"");
      24:                      Json.Append(",");
      25:                      Json.Append("\"Introduction\":\"" + Info.Introduction + "\"");
      26:                      Json.Append(",");
      27:                      Json.Append("\"Isrecommend\":\"" + Info.Isrecommend + "\"");
      28:                      Json.Append(",");
      29:                      Json.Append("\"Isshow\":\"" + Info.Isshow + "\"");
      30:                      Json.Append(",");
      31:                      Json.Append("\"Picturepath\":\"" + Info.Picturepath + "\"");
      32:                      Json.Append(",");
      33:                      Json.Append("\"Sex\":\"" + Info.Sex + "\"");
      34:                      Json.Append(",");
      35:                      Json.Append("\"Nation\":\"" + Info.Nation + "\"");
      36:                      Json.Append(",");
      37:                      Json.Append("\"mobilephone\":\"" + Info.mobilephone + "\"");
      38:                      Json.Append(",");
      39:                      Json.Append("\"Telephone\":\"" + Info.Telephone + "\"");
      40:                      Json.Append(",");
      41:                      Json.Append("\"Email\":\"" + Info.Email + "\"");
      42:                      Json.Append(",");
      43:                      Json.Append("\"QQ\":\"" + Info.QQ + "\"");
      44:                      Json.Append(",");
      45:                      Json.Append("\"Zipcode\":\"" + Info.Zipcode + "\"");
      46:                      Json.Append(",");
      47:                      Json.Append("\"Address\":\"" + Info.Address + "\"");
      48:                      Json.Append(",");
      49:                      Json.Append("\"appreciation\":\"" + Info.appreciation + "\"");
      50:                      Json.Append(",");
      51:                      Json.Append("\"website\":\"" + Info.website + "\"");
      52:                      Json.Append(",");
      53:                      Json.Append("\"Reward\":\"" + Info.Reward + "\"");
      54:                      Json.Append(",");
      55:                      Json.Append("\"BirthDay\":\"" + Info.BirthDay + "\"");
      56:                      Json.Append(",");
      57:                      Json.Append("\"state\":\"" + Info.state + "\"");
      58:                      Json.Append(",");
      59:                      Json.Append("\"state1\":\"" + Info.state1 + "\"");
      60:                      Json.Append(",");
      61:                      Json.Append("\"hit\":\"" + Info.hit + "\"");
      62:                      Json.Append(",");
      63:                      Json.Append("\"rank\":\"" + Info.rank + "\"");
      64:                      Json.Append("}");
      65:                      if(Info != masterInfo.Last())
      66:                      {
      67:                          Json.Append(",");
      68:                      }
      69:                  }
      70:              Json.Append("]}");
      71:              return Json.ToString();
      72:          }

    存储过程:一直就用的上网找的,一个非常完美的存储过程:(感觉优化的很好,我做了多次封装,用起来非常方便):

       1:  USE [czcraft]
       2:  GO
       3:  /****** 对象:  StoredProcedure [dbo].[pagination]    脚本日期: 04/26/2012 21:04:21 ******/
       4:  SET ANSI_NULLS ON
       5:  GO
       6:  SET QUOTED_IDENTIFIER ON
       7:  GO
       8:  CREATE PROCEDURE [dbo].[pagination]
       9:       @tblName varchar(255), -- 表名
      10:       @innerJohn varchar(500),  --inner john连接的表
      11:     --  @innerJohnCondition varchar(255),  --inner john连接条件 
      12:       @strGetFields varchar(1000) = '*', -- 需要返回的列
      13:       @fldName varchar(255)='', -- 排序的字段名
      14:       @PageSize int = 10, -- 页尺寸
      15:       @PageIndex int = 1, -- 页码
      16:       @doCount bit = 0, -- 返回记录总数, 非0 值则返回
      17:       @OrderType bit = 0, -- 设置排序类型, 非0 值则降序
      18:       @strWhere varchar(1500) = '' -- 查询条件(注意: 不要加where) 
      19:  AS 
      20:   
      21:  declare @strSQL varchar(5000) -- 主语句
      22:  declare @strTmp varchar(110) -- 临时变量
      23:  declare @strOrder varchar(400) -- 排序类型
      24:   
      25:  if @doCount != 0 
      26:       begin 
      27:           if @strWhere !='' 
      28:               set @strSQL = 'select count(*) as Total from [' + @tblName + '] '+@innerJohn +' where '+@strWhere 
      29:           else 
      30:               set @strSQL = 'select count(*) as Total from [' + @tblName + '] '+@innerJohn +' ' 
      31:       end 
      32:       --以上代码的意思是如果@doCount传递过来的不是0,就执行总数统计。以下的所有代码都是@doCount为0的情况
      33:   
      34:  else 
      35:       begin 
      36:           if @OrderType != 0 
      37:               begin 
      38:                   set @strTmp = '<(select min' 
      39:                   set @strOrder = ' order by [' + @fldName +'] desc' 
      40:                   --如果@OrderType不是0,就执行降序,这句很重要!
      41:               end 
      42:          
      43:           else 
      44:               begin 
      45:                   set @strTmp = '>(select max' 
      46:                   set @strOrder = ' order by [' + @fldName +'] asc' 
      47:               end 
      48:               if @PageIndex = 1 
      49:                   begin 
      50:                       if @strWhere != '' 
      51:                           set @strSQL = 'select top ' + str(@PageSize) +' '+@strGetFields+ ' from [' + @tblName + '] '+@innerJohn +' where ' + @strWhere + ' ' + @strOrder 
      52:                       else 
      53:                           set @strSQL = 'select top ' + str(@PageSize) +' '+@strGetFields+ ' from ['+ @tblName + '] '+@innerJohn + @strOrder 
      54:                           --如果是第一页就执行以上代码,这样会加快执行速度
      55:                   end 
      56:               else 
      57:                   begin 
      58:                       --以下代码赋予了@strSQL以真正执行的SQL代码
      59:                       set @strSQL = 'select top ' + str(@PageSize) +' '+@strGetFields+ ' from ' 
      60:                           + @tblName + ' '+@innerJohn+ ' where [' + @fldName + ']' + @strTmp + '(['+ @fldName + ']) from (select top ' + str((@PageIndex-1)*@PageSize) + ' ['+ @fldName + '] from [' + @tblName + '] '+@innerJohn +' ' + @strOrder + ') as tblTmp)'+ @strOrder 
      61:                           if @strWhere != '' 
      62:                       set @strSQL = 'select top ' + str(@PageSize) +' '+@strGetFields+ ' from ' 
      63:                           + @tblName + ' '+@innerJohn+ ' where [' + @fldName + ']' + @strTmp + '([' 
      64:                           + @fldName + ']) from (select top ' + str((@PageIndex-1)*@PageSize) + ' [' 
      65:                           + @fldName + '] from [' + @tblName + '] '+@innerJohn +'  where ' + @strWhere + ' ' 
      66:                           + @strOrder + ') as tblTmp) and ' + @strWhere + ' ' + @strOrder
      67:       end 
      68:  end 
      69:   
      70:  print(@PageIndex)
      71:   
      72:  exec (@strSQL)

    现在的页面效果图:

    image

    是不是蛮不错的????

    可能有人会问,为什么要做这么多工作?

    可是试想想,如果要把这些列表页生成静态页面,那么,这个页面就非常容易生成了,这个ajax分页更好更完美,

    如果用服务器控件,只要存在VIEWSTATE,生成静态页面就没辙了.

    而且这么设计结构清晰,更以维护,分离也更彻底!

  • 相关阅读:
    Sogou C++ Workflow 安装与使用例子
    Ubuntu c++ 使用mysql++ 链接mysql 使用cmake 构建
    现代cmake 从github引入三方库,使用FetchContent ( 3.14 以上版本)
    Vue3 + TypeScript 开发实践总结
    Spring MVC 学习总结(十)——Spring+Spring MVC+MyBatis框架集成(IntelliJ IDEA SSM集成)
    Spring MVC 学习总结(九)——Spring MVC实现RESTful与JSON(Spring MVC为前端提供服务)
    Spring MVC 学习总结(八)——Spring MVC概要与环境配置(IDEA+Maven+Tomcat7+JDK8、示例与视频)
    Spring MVC 学习总结(六)——Spring+Spring MVC+MyBatis框架集成
    Spring MVC 学习总结(五)——校验与文件上传
    Spring MVC 学习总结(四)——视图与综合示例
  • 原文地址:https://www.cnblogs.com/mysweet/p/2472038.html
Copyright © 2020-2023  润新知