2014年6月14日星期六

SpringMVC重定向视图RedirectView小分析 - format丶

本邮件内容由第三方提供,如果您不想继续收到该邮件,可 点此退订
SpringMVC重定向视图RedirectView小分析 - format丶  阅读原文»

目录

前言

SpringMVC是目前主流的Web MVC框架之一。

如果有同学对它不熟悉,那么请参考它的入门blog:http://www.cnblogs.com/fangjian0423/p/springMVC-introduction.html

本文所讲的部分内容跟SpringMVC的视图机制有关,SpringMVC的视图机制请参考楼主的另一篇博客:

http://www.cnblogs.com/fangjian0423/p/springMVC-view-viewResolver.html

RedirectView介绍

RedirectView这个视图是跟重定向相关的,也是重定向问题的核心,我们来看看这个类的源码。

RedirectView属性:

几个重要的构造方法:

RedirectView渲染过程:

重点看来下路径的构造:

路径构造完毕之后使用reponse进行sendRedirect操作。

实例讲解

Controller代码:

@Controller
@RequestMapping(value = "/redirect")
public class TestRedirectController {

@RequestMapping("/test1")
public ModelAndView test1() {
view.setViewName("redirect:index");
return view;
}

@RequestMapping("/test2")
public ModelAndView test2() {
view.setViewName("redirect:login");
return view;
}

@RequestMapping("/test3")
public ModelAndView test3(ModelAndView view) {
view.setViewName("redirect:/index");
return view;
}

@RequestMapping("/test4")
public ModelAndView test4(ModelAndView view) {
view.setView(new RedirectView("/index", false));
return view;
}

@RequestMapping("/test5")
public ModelAndView test5(ModelAndView view) {
view.setView(new RedirectView("index", false));
return view;
}

@RequestMapping("/test6/{id}")
public ModelAndView test6(ModelAndView view, @PathVariable("id") int id) {
view.setViewName("redirect:/index{id}");
    view.addObject("test", "test");
return view;
}

@RequestMapping("/test7/{id}")
public ModelAndView test7(ModelAndView view, @PathVariable("id") int id) {
RedirectView redirectView = new RedirectView("/index{id}");
redirectView.setExpandUriTemplateVariables(false);
redirectView.setExposeModelAttributes(false);
view.setView(redirectView);
view.addObject("test", "test");
return view;
}

}

先看test1方法,返回值 "redirect:index" , 那么会使用重定向。

SpringMVC找视图名"redirect:index"的时候,本文使用的ViewResolver是FreeMarkerViewResolver。

FreeMarkerViewResolver解析视图名的话,最调用父类之一的UrlBasedViewResolver中的createView方法。

通过构造方法发现,这个RedirectView使用相对路径,兼容Http1.0,不暴露路径变量。

test1方法,进入的路径: /SpringMVCDemo/redirect/test1。 RedirectView使用相对路径,那么重定向的路径: /SpringMVCDemo/redirect/index

我们通过firebug看下路径:

nice,验证了我们的想法。

test2方法同理:进入的路径: /SpringMVCDemo/redirect/test2。 重定向的路径: /SpringMVCDemo/redirect/login。

test3方法:以 "/" 开头并且使用相对路径,那么会默认加上contextPath。 进入的路径: /SpringMVCDemo/redirect/test3。 重定向的路径: /SpringMVCDemo/index。

test4方法:不使用默认路径,createTargetUrl方法中直接append "/index"。进入的路径: /SpringMVCDemo/redirect/test4。 重定向的路径: /index。

test5方法:不使用默认路径,createTargetUrl方法中直接append "index"。进入的路径: /SpringMVCDemo/redirect/test5。 重定向的路径: /SpringMVCDemo/redirect/index。

其实这里有点意外,刚开始看的时候以为不使用绝对路径,以后路径会是/SpringMVCDemo/index或/index。 结果居然不是这样,感觉SpringMVC这个取名有点尴尬,有点蛋疼。 其实RedirectView中的createTargetUrl方法就明白了,源码是最好的文档 0 0.

test6方法:使用默认路径,该方法还使用了路径变量。本文之前分析的时候说了RedirectView中构造重定向路径的时候会对路径变量进行替代,还会暴露model中的属性,且这2个暴露分别受属性expandUriTemplateVariables、exposeModelAttributes影响,这2个属性默认都是true。进入的路径: /SpringMVCDemo/redirect/test6/1。 重定向的路径: /SpringMVCDemo/index1?test=test。

test7方法:跟test6方法一样,只不过我们不暴露model属性,不替代路径变量了。进入的路径: /SpringMVCDemo/redirect/test7/1。 重定向的路径: /SpringMVCDemo/index{id}。

总结

简单了分析了RedirectView视图,并分析了该视图的渲染源码,并分析了重定向中的路径问题,参数问题,路径变量问题等常用的问题。

源码真是最好的文档,了解了视图机制之后,再回过头来看看RedirectView视图,So easy。

最后感觉RedirectView的相对路径属性怪怪的,不使用相对路径,"/" 开头的直接就是服务器根路径, 不带 "/" 开头的,又是相对路径, 有点蛋疼。

希望本文能够帮助读者了解SpringMVC的重定向相关问题。

文中难免有错误,希望读者能够指明出来。


本文链接:SpringMVC重定向视图RedirectView小分析,转载请注明。

query多选下拉框插件 jquery-multiselect(修改) - dz45693  阅读原文»

其实网上关于该控件的使用教程已经很多了,其中

query多选下拉框插件 jquery-multiselect

Jquery多选下拉列表插件jquery multiselect功能介绍及使用

这2个的介绍已经比较详细了,尤其是第二个有扩展MyValues函数,只是扩展有些bug,这里我在提出一些我的扩展,我们应该把multiValues属性定义在options里面,让每个multiselect控件都有自己的multiValues属性。我这里还需要一个获取text的方法。有关Myvalues和Mytexts的函数如下:

MyValues: function () {
return this.options.multiValues;
},
MyTexts: function () {
return this.buttonlabel.html();
},

默认的mytexts会有html编码效果,比如我的text是111&AAAA,我希望返回的呈现的text就是真是的值而不是111&AAA;要实现这个功能需要需要修改_setButtonValue函数

_setButtonValue: function (value) {
// this.buttonlabel.text(value);
this.buttonlabel.html(value);
},

在多选框弹出层关闭的时候我们要实现一些自己ajax请求,于是乎我们需要一个close函数,函数定义在options属性里面 WinClose: null,实现在close方法里面

if (this.options.WinClose) {
this.options.WinClose(this);
}

客户端的控件效果默认是没有固定高度,这里我们需要加一个固定高度给button

<button type="button" style=" height: 24px; overflow: hidden" >

最后的调用代码是:

$("select").multiselect({
noneSelectedText: "==请选择==",
checkAllText: "全选",
uncheckAllText: '全不选',
selectedList: 5,
WinClose: function (val) {
alert("Values:" + val.MyValues() + " Texts:" + val.MyTexts());

}
});

实现的效果如下:

当我们关闭弹出层时会调用我们的Winclose函数

修改后的整个js如下:

/* jshint forin:true, noarg:true, noempty:true, eqeqeq:true, boss:true, undef:true, curly:true, browser:true, jquery:true */
/*
* jQuery MultiSelect UI Widget 1.14pre
* Copyright (c) 2012 Eric Hynds
*
*
http://www.erichynds.com/jquery/jquery-ui-multiselect-widget/
*
* Depends:
* - jQuery 1.4.2+
* - jQuery UI 1.8 widget factory
*
* Optional:
* - jQuery UI effects
* - jQuery UI position utility
*
* Dual licensed under the MIT and GPL licenses:
*
http://www.opensource.org/licenses/mit-license.php
*
http://www.gnu.org/licenses/gpl.html
*
*/
(function ($, undefined) {

var multiselectID = 0;
var $doc = $(document);
$.widget(
"ech.multiselect", {

// default options
options: {
multiValues:
"",
header:
true,
height:
175,
minWidth:
225,
classes:
'',
checkAllText:
'Check all',
uncheckAllText:
'Uncheck all',
noneSelectedText:
'Select options',
selectedText:
'# selected',
selectedList:
0,
show:
null,
hide:
null,
autoOpen:
false,
multiple:
true,
position: {},
WinClose:
null,
appendTo:
"body"
},

_create: function () {
var el = this.element.hide();
var o = this.options;

this.speed = $.fx.speeds._default; // default speed for effects
this._isOpen = false; // assume no

// create a unique namespace for events that the widget
// factory cannot unbind automatically. Use eventNamespace if on
// jQuery UI 1.9+, and otherwise fallback to a custom string.
this._namespaceID = this.eventNamespace || ('multiselect' + multiselectID);

var button = (this.button = $('<button type="button" style=" height: 24px; overflow: hidden" ><span class="ui-icon ui-icon-triangle-1-s"></span></button>'))
.addClass(
'ui-multiselect ui-widget ui-state-default ui-corner-all')
.addClass(o.classes)
.attr({
'title': el.attr('title'), 'aria-haspopup': true, 'tabIndex': el.attr('tabIndex') })
.insertAfter(el),

buttonlabel
= (this.buttonlabel = $(

没有评论:

发表评论