jqgrid mvc_jqGrid,REST,AJAX和Spring MVC集成

jqgrid mvc

两年多以前,我写了一篇关于如何在Struts2中实现优雅的CRUD的文章。 实际上,我必须就该主题写两篇文章,因为该主题如此广泛。 今天,我采用了一套更为流行的,完善的框架和库,采用了更为轻量级的现代方法。 也就是说,我们将在后端使用Spring MVC为我们的资源提供REST接口,为jQuery提供出色的jqGrid插件以呈现表格网格(还有更多!),并且我们将使用少量JavaScript和AJAX来连接所有内容。

后端实际上是该展示柜中最不有趣的部分,它可以使用能够处理RESTful请求的任何服务器端技术来实现,现在也许应该将JAX-RS视为该领域的标准。 我没有任何理由就选择了Spring MVC,但这对于这个任务也不是一个坏选择。 我们将通过REST接口公开CRUD操作; 历史上最畅销的书籍清单将是我们的领域模型(您能猜出谁登上领奖台吗?)

@Controller
@RequestMapping(value = "/book")
public class BookController {private final Map<Integer, Book> books = new ConcurrentSkipListMap<Integer, Book>();@RequestMapping(value = "/{id}", method = GET)public @ResponseBody Book read(@PathVariable("id") int id) {return books.get(id);}@RequestMapping(method = GET)public @ResponseBody Page<Book> listBooks(@RequestParam(value = "page", required = false, defaultValue = "1") int page,@RequestParam(value = "max", required = false, defaultValue = "20") int max) {final ArrayList<Book> booksList = new ArrayList<Book>(books.values());final int startIdx = (page - 1) * max;final int endIdx = Math.min(startIdx + max, books.size());return new Page<Book>(booksList.subList(startIdx, endIdx), page, max, books.size());}}

几乎没有什么需要解释的。 首先,出于这个简单展示的目的,我没有使用任何数据库,所有书籍都存储在控制器内部的内存映射中。 原谅我。 第二个问题更加微妙。 由于在如何使用RESTful Web服务处理分页方面似乎尚未达成共识 ,因此我使用了简单的查询参数。 您可能会发现它很丑陋,但是我发现滥用Accept-Ranges和Range标头以及206 HTTP响应代码更加丑陋。

最后一个值得注意的细节是Page wrapper类:

@XmlRootElement
public class Page<T> {private List<T> rows;private int page;private int max;private int total;//...}

我可以返回原始列表(或更确切地说,返回列表的请求部分),但是我还需要一种方法来向视图层提供方便的元数据(例如记录总数),更不用说在编组/解组原始列表时遇到的一些困难。

现在,我们准备开始我们的应用程序并使用curl进行一些测试:

<!-- $ curl -v "http://localhost:8080/books/rest/book?page=1&max=2" --><?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<page><total>43</total><page>1</page><max>3</max><rows xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="book"><author>Charles Dickens</author><available>true</available><cover>PAPERBACK</cover><id>1</id><publishedYear>1859</publishedYear><title>A Tale of Two Cities</title></rows><rows xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="book"><author>J. R. R. Tolkien</author><available>true</available><cover>HARDCOVER</cover><id>2</id><publishedYear>1954</publishedYear><title>The Lord of the Rings</title></rows><rows xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="book"><author>J. R. R. Tolkien</author><available>true</available><cover>PAPERBACK</cover><id>3</id><publishedYear>1937</publishedYear><title>The Hobbit</title></rows>
</page>

如果未指定响应类型,则响应类型默认为XML,但是如果我们将Jackson库添加到CLASSPATH,Spring会选择它并允许我们也使用JSON:

// $ curl -v -H "Accept: application/json" "http://localhost:8080/books/rest/book?page=1&max=3"{"total":43,"max":3,"page":1,"rows":[{"id":1,"available":true,"author":"Charles Dickens","title":"A Tale of Two Cities","publishedYear":1859,"cover":"PAPERBACK","comments":null},{"id":2,"available":true,"author":"J. R. R. Tolkien","title":"The Lord of the Rings","publishedYear":1954,"cover":"HARDCOVER","comments":null},{"id":3,"available":true,"author":"J. R. R. Tolkien","title":"The Hobbit","publishedYear":1937,"cover":"PAPERBACK","comments":null}]
}

很好,现在我们可以在前端工作了,希望不会使手太脏。 关于HTML标记,这就是我们所需要的,认真的是:

<table id="grid"></table>
<div id="pager"></div>

请记住,我们将实现所有CRUD操作,但这仍然是我们所需要的。 没有更多HTML。 多亏了出色的jqGrid库,其余的魔术才得以实现。 这是一个基本设置:

$("#grid").jqGrid({url:'rest/book',colModel:[{name:'id', label: 'ID', formatter:'integer', width: 40},{name:'title', label: 'Title', width: 300},{name:'author', label: 'Author', width: 200},{name:'publishedYear', label: 'Published year', width: 80, align: 'center'},{name:'available', label: 'Available', formatter: 'checkbox', width: 46, align: 'center'}],caption: "Books",pager : '#pager',height: 'auto'}).navGrid('#pager', {edit:false,add:false,del:false, search: false});

从技术上讲,这就是我们所需要的。 用来获取数据的URL,指向我们的控制器(jqGrid将为我们执行所有AJAX魔术)和数据模型(您可能会识别书本字段及其描述)。 但是,由于jqGrid是高度可定制的,因此我进行了一些调整以使网格看起来更好。 另外,我也不喜欢元数据的建议名称,例如,从服务器返回的字段总数应该是页面总数,而不是记录总数,这很违反直觉。 这是我调整过的选项:

$.extend($.jgrid.defaults, {datatype: 'json',jsonReader : {repeatitems:false,total: function(result) {//Total number of pagesreturn Math.ceil(result.total / result.max);},records: function(result) {//Total number of recordsreturn result.total;}},prmNames: {rows: 'max', search: null},height: 'auto',viewrecords: true,rowList: [10, 20, 50, 100],altRows: true,loadError: function(xhr, status, error) {alert(error);}});

渴望看到结果吗? 这是浏览器的屏幕截图:

漂亮的外观,可自定义的分页,轻巧的刷新……而且我们的手还是比较干净的! 但是我答应了CRUD ...如果您小心的话,您可能已经注意到了一些navGrid属性,并且很想打开它:

var URL = 'rest/book';
var options = {url: URL,editurl: URL,colModel:[{name:'id', label: 'ID',formatter:'integer',width: 40,editable: true,editoptions: {disabled: true, size:5}},{name:'title',label: 'Title',width: 300,editable: true,editrules: {required: true}},{name:'author',label: 'Author',width: 200,editable: true,editrules: {required: true}},{name:'cover',label: 'Cover',hidden: true,editable: true,edittype: 'select',editrules: {edithidden:true},editoptions: {value: {'PAPERBACK': 'paperback', 'HARDCOVER': 'hardcover', 'DUST_JACKET': 'dust jacket'}}},{name:'publishedYear',label: 'Published year',width: 80,align: 'center',editable: true,editrules: {required: true, integer: true},editoptions: {size:5, maxlength: 4}},{name:'available',label: 'Available',formatter: 'checkbox',width: 46,align: 'center',editable: true,edittype: 'checkbox',editoptions: {value:"true:false"}},{name:'comments',label: 'Comments',hidden: true,editable: true,edittype: 'textarea',editrules: {edithidden:true}}],caption: "Books",pager : '#pager',height: 'auto'
};
$("#grid").jqGrid(options).navGrid('#pager', {edit:true,add:true,del:true, search: false});

配置变得非常冗长,但是并没有什么复杂的事情–对于每个字段,我们都添加了一些额外的属性来控制在编辑模式下应如何处理该字段。 这包括应该代表哪种类型HTML输入,验证规则,可见性等。但是说实话,我认为这是值得的:

jqGrid根据上面提到的我们的编辑选项(包括验证逻辑)完全生成了一个外观漂亮的编辑窗口。 我们可以使某些字段在网格中可见(在编辑对话框中为隐藏/不活动)(例如id),反之亦然(封面和注释不在网格中,但是您可以对其进行修改)。 还要注意,在网格的左下角可见的新图标很少。 添加和删​​除也是可能的-而且我们还没有编写一行HTML / JSP / JavaScript(jqGrid配置对象除外)。

当然,我们都知道用户界面就是应用程序 ,我们的界面还不错,但是有时候我们真的想要一个漂亮且可以运行的应用程序。 当前,后一个要求是我们的致命弱点。 不是因为后端尚未准备好,而是相当简单的:

@Controller
@RequestMapping(value = "/book")
public class BookController {private final Map<Integer, Book> books = new ConcurrentSkipListMap<Integer, Book>();@RequestMapping(value = "/{id}", method = GET)public @ResponseBody Book read(@PathVariable("id") int id) {//...}@RequestMapping(method = GET)public@ResponseBodyPage<Book> listBooks(@RequestParam(value = "page", required = false, defaultValue = "1") int page,@RequestParam(value = "max", required = false, defaultValue = "20") int max) {//...}@RequestMapping(value = "/{id}", method = PUT)@ResponseStatus(HttpStatus.NO_CONTENT)public void updateBook(@PathVariable("id") int id, @RequestBody Book book) {//...}@RequestMapping(method = POST)public ResponseEntity<String> createBook(HttpServletRequest request, @RequestBody Book book) {//...}@RequestMapping(value = "/{id}", method = DELETE)@ResponseStatus(HttpStatus.NO_CONTENT)public void deleteBook(@PathVariable("id") int id) {//...}}

服务器端已经准备就绪,但是当涉及到客户端的数据操作时,jqGrid揭示了其肮脏的秘密–到服务器的所有流量都使用POST发送,如下所示:

Content-Type: application/x-www-form-urlencoded in the following format:
id=&title=And+Then+There+Were+None&author=Agatha+Christie&cover=PAPERBACK&publishedYear=1939&available=true&comments=&oper=add

最后一个属性(oper = add)是至关重要的。 不是真正的惯用REST,您不觉得吗? 如果我们只能适当地使用POST / PUT / DELETE并使用JSON或XML序列化数据……修改服务器以使其与某些JavaScript库兼容(无论它有多酷),那似乎是不得已的方法。 值得庆幸的是,只需少量的工作就可以自定义所有内容。

$.extend($.jgrid.edit, {ajaxEditOptions: { contentType: "application/json" },mtype: 'PUT',serializeEditData: function(data) {delete data.oper;return JSON.stringify(data);}});
$.extend($.jgrid.del, {mtype: 'DELETE',serializeDelData: function() {return "";}});var URL = 'rest/book';
var options = {url: URL,//...
}var editOptions = {onclickSubmit: function(params, postdata) {params.url = URL + '/' + postdata.id;}
};
var addOptions = {mtype: "POST"};
var delOptions = {onclickSubmit: function(params, postdata) {params.url = URL + '/' + postdata;}
};$("#grid").jqGrid(options).navGrid('#pager',{}, //optionseditOptions,addOptions,delOptions,{} // search options
);

我们为每个操作自定义了HTTP方法,使用JSON处理序列化,最后,用于编辑和删除操作的URL现在带有/ record_id后缀。 现在它不仅看起来,而且可以工作! 查看浏览器与服务器的交互(注意不同的HTTP方法和URL):

这是在浏览器端创建新资源的示例:

为了尽可能严格地遵循REST原则,我返回201 Created响应代码以及Location标头,该标头指向新创建的资源。 如您所见,数据现在以JSON格式发送到服务器。

总而言之,这种方法具有很多优点:

  • GUI非常敏感,页面会立即显示(它可以是CDN提供的静态资源),而数据则是通过AJAX以轻量级JSON格式异步加载的
  • 我们免费获得CRUD操作
  • 其他系统的REST接口也是免费的

将此与任何Web框架进行比较。 我是否在JavaScript结霜方面提到了这个小问题:jqGrid完全符合jQuery UI主题 ,还支持国际化。 这是具有更改的主题和语言的同一应用程序:

完整的源代码可在Tomek的GitHub帐户上获得 。 该应用程序是自包含的,只需构建它并将其部署到某个servlet容器即可。

参考: 穷人的CRUD:jQGrid,REST,AJAX和Spring MVC在我们的JCG合作伙伴 Tomek Nurkiewicz的NoBlogDefFound博客中合而为一 。

相关文章 :
  • Spring 3 RESTful Web服务
  • Tomcat 7上具有RESTeasy JAX-RS的RESTful Web服务– Eclipse和Maven项目
  • Spring MVC3 Hibernate CRUD示例应用程序
  • Spring MVC开发–快速教程
  • 具有Spring和Maven教程的JAX–WS

翻译自: https://www.javacodegeeks.com/2011/07/jqgrid-rest-ajax-spring-mvc-integration.html

jqgrid mvc

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/360045.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ChronicleMap –具有堆外内存的Java体系结构

我的上一篇文章是在几周前写的&#xff0c;在收到一些有效的反馈后&#xff0c;我想澄清几点&#xff0c;作为本文的序言。 “ 使用零垃圾创建数百万个对象 ”的主要收获应该是&#xff0c;使用Chronicle&#xff0c;在编写Java程序时&#xff0c;您不会“局限于”使用jvm分配…

下列不属于html5语义元素,HTML5 新的语义元素

HTML5 提供了新的语义元素来明确一个Web页面的不同部分:HTML5中新的语义元素HTML5 元素标签定义文档中的节(section、区段)。比如章节、页眉、页脚或文档中的其他部分。根据W3C HTML5文档: section 包含了一组内容及其标题。WWFThe World Wide Fund for Nature (WWF) is....HTM…

干加个偏旁可以变成什么字_面试官:“干”字加一笔,变成什么字?回答王和午字不对...

随着大学生的增多&#xff0c;如今的求职者进入职场&#xff0c;想到一份心仪的工作&#xff0c;最让人头疼的就是面试&#xff0c;越来越多的企业都需要全能型的人才&#xff0c;从而在面试的时候不仅要考核专业知识&#xff0c;面试官还要费尽心思出各种各样的题来考验求职者…

Oracle研学-查询

学自B站黑马程序员 1.单表查询 //查询水表编号为 30408 的业主记录 select * from T_OWNERS where watermeter30408 //查询业主名称包含“刘”的业主记录 select * from t_owners where name like %刘% //查询业主名称包含“刘”的并且门牌号包含 5 的业主记录 select * from…

国际站html代码,国际站必须看得懂的HTML代码

国际站必须看得懂的HTML代码國産〇〇柒大家每天都忙着找关键词&#xff0c;忙着写标题&#xff0c;忙着做各种的优化。目的就是想把自己的产品排名到前面&#xff0c;获得更多的曝光&#xff0c;带来更多的询盘。在这个过程中我们是客服同事也是一名搜索优化人员&#xff0c;但…

phoengap–node+websocket在线聊天室

该实验项目基于&#xff1a; phonegapnodewebsocket可以应用于android 和 ios平台。 已经测试通过。以下是测试的图&#xff1a; 首先是用node 架设服务器。 基本上都node 基于websocket的。 主要是对message做处理和判断来进行输出和逻辑处理 而客户都&#xff0c;由于android…

中音萨克斯指法表图_萨克斯的几个特殊指法记忆和几个概念

大家在平常的练习和吹奏的时候&#xff0c;经常会出现找不到相应的指法的情况&#xff0c;有经验的萨友们通过长时间的摸索&#xff0c;会找到其中的一些规律。实际上&#xff0c;能看懂“一图在手&#xff0c;不用再担心找不到指法了”里面的表格&#xff0c;可以起到同样的作…

git配置和使用

1、注册bitbucket用户登录bitbucket站点https://bitbucket.org/注册一个用户&#xff0c;注册后用户名为linjiqin&#xff0c;邮箱为linjiqindkhs.com。 2、Create repository(仓库)登录bitbucket&#xff0c;点击“Create”按钮会出现一个Create a new repository页面&#xf…

操作系统饥饿现象_操作系统心得体会

一、操作系统1.基本概念操作系统简称OS&#xff0c;是配置在计算机硬件上的第一层软件&#xff0c;它能够有效的组织和管理计算机系统中的硬件和软件资源&#xff0c;合理的组织计算机工作流程&#xff0c;控制程序的执行&#xff0c;并向用户提供各种服务功能。OS是现代计算机…

组态王怎么做超级曲线_鸭肉怎么做?大叔教你红烧鸭块,香气扑鼻,简单易做,超级好吃...

晚餐总是要有硬菜上桌的&#xff0c;所谓硬菜无非是鸡鸭鱼肉&#xff0c;买只鸭子吧&#xff0c;倒也是不在乎哪天吃大荤&#xff0c;鸭子算是减肥食谱&#xff0c;对高血压&#xff0c;心脏病有一定的好处&#xff0c;另外&#xff0c;癌症病人不能吃鸡&#xff0c;鸭子却是可…

使用Spring的缓存管理器缓存Web内容

在这篇文章中&#xff0c;我想向您展示如何使用Spring的CacheManager&#xff0c; Cacheable和JMX批注来缓存和管理Web内容的缓存的基础知识。 想象一下一个网上商店&#xff0c;它从远程WCMS&#xff08;Web内容管理系统&#xff09;获取一些内容&#xff0c;例如页眉&#xf…

学水利的想转行计算机,为什么说千万别学水利水电工程?附水利八大院排名2020年(最新)...

选择科目测一测我能上哪些大学选择科目领取你的专属报告>选择省份关闭请选择科目确定v>水利水电工程一直是国家建设中离不开的一个环节&#xff0c;该专业在父母眼中是也很有前途的专业&#xff0c;但近几年&#xff0c;许多人不太看好水利水电工程专业了&#xff0c;甚至…

【WP8】ResourceDictionary

WP8中引用资源字典 当我们定义的样式太多的时候&#xff0c;我们可以把样式分别定义在不同的文件中&#xff0c;然后通过 MergedDictionaries 应用到其他资源字典中&#xff0c;看下面Demo 我们可以把样式定义在多个文件中&#xff0c;然后再App.xaml中引用 我们先定义三个文件…

python夹角余弦雷达图_雷达导论PART-II.1 无线电波与交变电流信号

今天开始进入第二篇-必要的准备知识&#xff0c;全部的篇章结构见我的第一篇文章“雷达导论 引言”。第二篇有3个章节&#xff0c;如下图所示&#xff0c;分别是第4章-无线电波与交变电流信号、第5章-用一种非数学的方法理解雷达、第6章-雷达的数学预备知识。今天先讲第4章&…

Oracle Java Mission Control:终极指南

“我们喜欢关注Mikhail Vorontsov的博客&#xff0c;并获得他对Java Performance相关问题的看法。 我们曾多次被问到Takipi的Java错误分析与Java Mission Control和Java Flight Recorder有何不同。 因此&#xff0c;尽管工具之间的差异很大&#xff08;主要是&#xff0c;JMC主…

用计算机演奏打上花火,米津玄师打上花火歌词中文谐音(最好要简单全面)

满意答案.Ador2020.03.19采纳率&#xff1a;60% 等级&#xff1a;14已帮助&#xff1a;2446人打上花火 - 《升起的烟花&#xff0c;从下面看&#xff1f;还是从侧面看&#xff1f;》主题曲 词&#xff1a;米津玄师 曲&#xff1a;米津玄师xDAOKO有些地方一些音不对请见谅哈 …

两个向量之间的夹角公式_关于平面向量夹角求参数取值范围的两种基本解法介绍...

平面向量的夹角问题是考察高中向量知识掌握程度的常考内容&#xff0c;主要涉及到的知识点是平面向量的数量积公式。在这里介绍一道常见的平面向量题目&#xff0c;通过两种最基本的解法&#xff0c;来帮助同学们理解向量之间的夹角。填空题第15题&#xff1a;设平面向量a(-2&a…

宿迁学院的计算机系怎么样,宿迁学院是几本 学生评价怎么样好不好(10条)

宿迁学院是几本 学生评价怎么样好不好(10条)考生之前的努力奋斗就是为了高考报志愿时有更多的底气和把握。而俗话说&#xff0c;三分考、七分报&#xff0c;有很多考生和家长都还不太了解大学的一本、二本、三本之分&#xff0c;本科高校只有一个层次和等级&#xff0c;就是(本…

Google Guava:您永远不会知道的5件事

每个开发人员都可以使用哪些鲜为人知的Google Guava功能&#xff1f; 它是那里最受欢迎的库之一&#xff0c;它是开源的&#xff0c;您可能已经知道了&#xff0c;它来自人们玩Quidditch作为一项真正的运动的地方&#xff08;至少在The Internship上 &#xff09;。 它不是哈利…

hql中获取前一天的数据_PostgreSql 怎么获取数据库中关键系统信息(一)

如何通过SQL 的方式获得数据库中的一些关键信息&#xff0c;是一个DB最正常的工作&#xff0c;如何通过一些SQL来获得PG的一些关键的参数和信息或者是数据库中的一些信息是需要知道的一件事情。以下是部分 1一般来说每种数据库中都有一个或几个系统的数据库&#xff0c;在PG中s…