").append(b.parseHTML(e)).find(i):e)}).complete(r&&function(e,t){s.each(r,o||[e.responseText,t,e])}),this},b.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){b.fn[t]=function(e){return this.on(t,e)}}),b.each(["get","post"],function(e,n){b[n]=function(e,r,i,o){return b.isFunction(r)&&(o=o||i,i=r,r=t),b.ajax({url:e,type:n,dataType:o,data:r,success:i})}}),b.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:yn,type:"GET",isLocal:Nn.test(mn[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Dn,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":e.String,"text html":!0,"text json":b.parseJSON,"text xml":b.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?Mn(Mn(e,b.ajaxSettings),t):Mn(b.ajaxSettings,e)},ajaxPrefilter:Hn(An),ajaxTransport:Hn(jn),ajax:function(e,n){"object"==typeof e&&(n=e,e=t),n=n||{};var r,i,o,a,s,u,l,c,p=b.ajaxSetup({},n),f=p.context||p,d=p.context&&(f.nodeType||f.jquery)?b(f):b.event,h=b.Deferred(),g=b.Callbacks("once memory"),m=p.statusCode||{},y={},v={},x=0,T="canceled",N={readyState:0,getResponseHeader:function(e){var t;if(2===x){if(!c){c={};while(t=Tn.exec(a))c[t[1].toLowerCase()]=t[2]}t=c[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return 2===x?a:null},setRequestHeader:function(e,t){var n=e.toLowerCase();return x||(e=v[n]=v[n]||e,y[e]=t),this},overrideMimeType:function(e){return x||(p.mimeType=e),this},statusCode:function(e){var t;if(e)if(2>x)for(t in e)m[t]=[m[t],e[t]];else N.always(e[N.status]);return this},abort:function(e){var t=e||T;return l&&l.abort(t),k(0,t),this}};if(h.promise(N).complete=g.add,N.success=N.done,N.error=N.fail,p.url=((e||p.url||yn)+"").replace(xn,"").replace(kn,mn[1]+"//"),p.type=n.method||n.type||p.method||p.type,p.dataTypes=b.trim(p.dataType||"*").toLowerCase().match(w)||[""],null==p.crossDomain&&(r=En.exec(p.url.toLowerCase()),p.crossDomain=!(!r||r[1]===mn[1]&&r[2]===mn[2]&&(r[3]||("http:"===r[1]?80:443))==(mn[3]||("http:"===mn[1]?80:443)))),p.data&&p.processData&&"string"!=typeof p.data&&(p.data=b.param(p.data,p.traditional)),qn(An,p,n,N),2===x)return N;u=p.global,u&&0===b.active++&&b.event.trigger("ajaxStart"),p.type=p.type.toUpperCase(),p.hasContent=!Cn.test(p.type),o=p.url,p.hasContent||(p.data&&(o=p.url+=(bn.test(o)?"&":"?")+p.data,delete p.data),p.cache===!1&&(p.url=wn.test(o)?o.replace(wn,"$1_="+vn++):o+(bn.test(o)?"&":"?")+"_="+vn++)),p.ifModified&&(b.lastModified[o]&&N.setRequestHeader("If-Modified-Since",b.lastModified[o]),b.etag[o]&&N.setRequestHeader("If-None-Match",b.etag[o])),(p.data&&p.hasContent&&p.contentType!==!1||n.contentType)&&N.setRequestHeader("Content-Type",p.contentType),N.setRequestHeader("Accept",p.dataTypes[0]&&p.accepts[p.dataTypes[0]]?p.accepts[p.dataTypes[0]]+("*"!==p.dataTypes[0]?", "+Dn+"; q=0.01":""):p.accepts["*"]);for(i in p.headers)N.setRequestHeader(i,p.headers[i]);if(p.beforeSend&&(p.beforeSend.call(f,N,p)===!1||2===x))return N.abort();T="abort";for(i in{success:1,error:1,complete:1})N[i](p[i]);if(l=qn(jn,p,n,N)){N.readyState=1,u&&d.trigger("ajaxSend",[N,p]),p.async&&p.timeout>0&&(s=setTimeout(function(){N.abort("timeout")},p.timeout));try{x=1,l.send(y,k)}catch(C){if(!(2>x))throw C;k(-1,C)}}else k(-1,"No Transport");function k(e,n,r,i){var c,y,v,w,T,C=n;2!==x&&(x=2,s&&clearTimeout(s),l=t,a=i||"",N.readyState=e>0?4:0,r&&(w=_n(p,N,r)),e>=200&&300>e||304===e?(p.ifModified&&(T=N.getResponseHeader("Last-Modified"),T&&(b.lastModified[o]=T),T=N.getResponseHeader("etag"),T&&(b.etag[o]=T)),204===e?(c=!0,C="nocontent"):304===e?(c=!0,C="notmodified"):(c=Fn(p,w),C=c.state,y=c.data,v=c.error,c=!v)):(v=C,(e||!C)&&(C="error",0>e&&(e=0))),N.status=e,N.statusText=(n||C)+"",c?h.resolveWith(f,[y,C,N]):h.rejectWith(f,[N,C,v]),N.statusCode(m),m=t,u&&d.trigger(c?"ajaxSuccess":"ajaxError",[N,p,c?y:v]),g.fireWith(f,[N,C]),u&&(d.trigger("ajaxComplete",[N,p]),--b.active||b.event.trigger("ajaxStop")))}return N},getScript:function(e,n){return b.get(e,t,n,"script")},getJSON:function(e,t,n){return b.get(e,t,n,"json")}});function _n(e,n,r){var i,o,a,s,u=e.contents,l=e.dataTypes,c=e.responseFields;for(s in c)s in r&&(n[c[s]]=r[s]);while("*"===l[0])l.shift(),o===t&&(o=e.mimeType||n.getResponseHeader("Content-Type"));if(o)for(s in u)if(u[s]&&u[s].test(o)){l.unshift(s);break}if(l[0]in r)a=l[0];else{for(s in r){if(!l[0]||e.converters[s+" "+l[0]]){a=s;break}i||(i=s)}a=a||i}return a?(a!==l[0]&&l.unshift(a),r[a]):t}function Fn(e,t){var n,r,i,o,a={},s=0,u=e.dataTypes.slice(),l=u[0];if(e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u[1])for(i in e.converters)a[i.toLowerCase()]=e.converters[i];for(;r=u[++s];)if("*"!==r){if("*"!==l&&l!==r){if(i=a[l+" "+r]||a["* "+r],!i)for(n in a)if(o=n.split(" "),o[1]===r&&(i=a[l+" "+o[0]]||a["* "+o[0]])){i===!0?i=a[n]:a[n]!==!0&&(r=o[0],u.splice(s--,0,r));break}if(i!==!0)if(i&&e["throws"])t=i(t);else try{t=i(t)}catch(c){return{state:"parsererror",error:i?c:"No conversion from "+l+" to "+r}}}l=r}return{state:"success",data:t}}b.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(e){return b.globalEval(e),e}}}),b.ajaxPrefilter("script",function(e){e.cache===t&&(e.cache=!1),e.crossDomain&&(e.type="GET",e.global=!1)}),b.ajaxTransport("script",function(e){if(e.crossDomain){var n,r=o.head||b("head")[0]||o.documentElement;return{send:function(t,i){n=o.createElement("script"),n.async=!0,e.scriptCharset&&(n.charset=e.scriptCharset),n.src=e.url,n.onload=n.onreadystatechange=function(e,t){(t||!n.readyState||/loaded|complete/.test(n.readyState))&&(n.onload=n.onreadystatechange=null,n.parentNode&&n.parentNode.removeChild(n),n=null,t||i(200,"success"))},r.insertBefore(n,r.firstChild)},abort:function(){n&&n.onload(t,!0)}}}});var On=[],Bn=/(=)\?(?=&|$)|\?\?/;b.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=On.pop()||b.expando+"_"+vn++;return this[e]=!0,e}}),b.ajaxPrefilter("json jsonp",function(n,r,i){var o,a,s,u=n.jsonp!==!1&&(Bn.test(n.url)?"url":"string"==typeof n.data&&!(n.contentType||"").indexOf("application/x-www-form-urlencoded")&&Bn.test(n.data)&&"data");return u||"jsonp"===n.dataTypes[0]?(o=n.jsonpCallback=b.isFunction(n.jsonpCallback)?n.jsonpCallback():n.jsonpCallback,u?n[u]=n[u].replace(Bn,"$1"+o):n.jsonp!==!1&&(n.url+=(bn.test(n.url)?"&":"?")+n.jsonp+"="+o),n.converters["script json"]=function(){return s||b.error(o+" was not called"),s[0]},n.dataTypes[0]="json",a=e[o],e[o]=function(){s=arguments},i.always(function(){e[o]=a,n[o]&&(n.jsonpCallback=r.jsonpCallback,On.push(o)),s&&b.isFunction(a)&&a(s[0]),s=a=t}),"script"):t});var Pn,Rn,Wn=0,$n=e.ActiveXObject&&function(){var e;for(e in Pn)Pn[e](t,!0)};function In(){try{return new e.XMLHttpRequest}catch(t){}}function zn(){try{return new e.ActiveXObject("Microsoft.XMLHTTP")}catch(t){}}b.ajaxSettings.xhr=e.ActiveXObject?function(){return!this.isLocal&&In()||zn()}:In,Rn=b.ajaxSettings.xhr(),b.support.cors=!!Rn&&"withCredentials"in Rn,Rn=b.support.ajax=!!Rn,Rn&&b.ajaxTransport(function(n){if(!n.crossDomain||b.support.cors){var r;return{send:function(i,o){var a,s,u=n.xhr();if(n.username?u.open(n.type,n.url,n.async,n.username,n.password):u.open(n.type,n.url,n.async),n.xhrFields)for(s in n.xhrFields)u[s]=n.xhrFields[s];n.mimeType&&u.overrideMimeType&&u.overrideMimeType(n.mimeType),n.crossDomain||i["X-Requested-With"]||(i["X-Requested-With"]="XMLHttpRequest");try{for(s in i)u.setRequestHeader(s,i[s])}catch(l){}u.send(n.hasContent&&n.data||null),r=function(e,i){var s,l,c,p;try{if(r&&(i||4===u.readyState))if(r=t,a&&(u.onreadystatechange=b.noop,$n&&delete Pn[a]),i)4!==u.readyState&&u.abort();else{p={},s=u.status,l=u.getAllResponseHeaders(),"string"==typeof u.responseText&&(p.text=u.responseText);try{c=u.statusText}catch(f){c=""}s||!n.isLocal||n.crossDomain?1223===s&&(s=204):s=p.text?200:404}}catch(d){i||o(-1,d)}p&&o(s,c,p,l)},n.async?4===u.readyState?setTimeout(r):(a=++Wn,$n&&(Pn||(Pn={},b(e).unload($n)),Pn[a]=r),u.onreadystatechange=r):r()},abort:function(){r&&r(t,!0)}}}});var Xn,Un,Vn=/^(?:toggle|show|hide)$/,Yn=RegExp("^(?:([+-])=|)("+x+")([a-z%]*)$","i"),Jn=/queueHooks$/,Gn=[nr],Qn={"*":[function(e,t){var n,r,i=this.createTween(e,t),o=Yn.exec(t),a=i.cur(),s=+a||0,u=1,l=20;if(o){if(n=+o[2],r=o[3]||(b.cssNumber[e]?"":"px"),"px"!==r&&s){s=b.css(i.elem,e,!0)||n||1;do u=u||".5",s/=u,b.style(i.elem,e,s+r);while(u!==(u=i.cur()/a)&&1!==u&&--l)}i.unit=r,i.start=s,i.end=o[1]?s+(o[1]+1)*n:n}return i}]};function Kn(){return setTimeout(function(){Xn=t}),Xn=b.now()}function Zn(e,t){b.each(t,function(t,n){var r=(Qn[t]||[]).concat(Qn["*"]),i=0,o=r.length;for(;o>i;i++)if(r[i].call(e,t,n))return})}function er(e,t,n){var r,i,o=0,a=Gn.length,s=b.Deferred().always(function(){delete u.elem}),u=function(){if(i)return!1;var t=Xn||Kn(),n=Math.max(0,l.startTime+l.duration-t),r=n/l.duration||0,o=1-r,a=0,u=l.tweens.length;for(;u>a;a++)l.tweens[a].run(o);return s.notifyWith(e,[l,o,n]),1>o&&u?n:(s.resolveWith(e,[l]),!1)},l=s.promise({elem:e,props:b.extend({},t),opts:b.extend(!0,{specialEasing:{}},n),originalProperties:t,originalOptions:n,startTime:Xn||Kn(),duration:n.duration,tweens:[],createTween:function(t,n){var r=b.Tween(e,l.opts,t,n,l.opts.specialEasing[t]||l.opts.easing);return l.tweens.push(r),r},stop:function(t){var n=0,r=t?l.tweens.length:0;if(i)return this;for(i=!0;r>n;n++)l.tweens[n].run(1);return t?s.resolveWith(e,[l,t]):s.rejectWith(e,[l,t]),this}}),c=l.props;for(tr(c,l.opts.specialEasing);a>o;o++)if(r=Gn[o].call(l,e,c,l.opts))return r;return Zn(l,c),b.isFunction(l.opts.start)&&l.opts.start.call(e,l),b.fx.timer(b.extend(u,{elem:e,anim:l,queue:l.opts.queue})),l.progress(l.opts.progress).done(l.opts.done,l.opts.complete).fail(l.opts.fail).always(l.opts.always)}function tr(e,t){var n,r,i,o,a;for(i in e)if(r=b.camelCase(i),o=t[r],n=e[i],b.isArray(n)&&(o=n[1],n=e[i]=n[0]),i!==r&&(e[r]=n,delete e[i]),a=b.cssHooks[r],a&&"expand"in a){n=a.expand(n),delete e[r];for(i in n)i in e||(e[i]=n[i],t[i]=o)}else t[r]=o}b.Animation=b.extend(er,{tweener:function(e,t){b.isFunction(e)?(t=e,e=["*"]):e=e.split(" ");var n,r=0,i=e.length;for(;i>r;r++)n=e[r],Qn[n]=Qn[n]||[],Qn[n].unshift(t)},prefilter:function(e,t){t?Gn.unshift(e):Gn.push(e)}});function nr(e,t,n){var r,i,o,a,s,u,l,c,p,f=this,d=e.style,h={},g=[],m=e.nodeType&&nn(e);n.queue||(c=b._queueHooks(e,"fx"),null==c.unqueued&&(c.unqueued=0,p=c.empty.fire,c.empty.fire=function(){c.unqueued||p()}),c.unqueued++,f.always(function(){f.always(function(){c.unqueued--,b.queue(e,"fx").length||c.empty.fire()})})),1===e.nodeType&&("height"in t||"width"in t)&&(n.overflow=[d.overflow,d.overflowX,d.overflowY],"inline"===b.css(e,"display")&&"none"===b.css(e,"float")&&(b.support.inlineBlockNeedsLayout&&"inline"!==un(e.nodeName)?d.zoom=1:d.display="inline-block")),n.overflow&&(d.overflow="hidden",b.support.shrinkWrapBlocks||f.always(function(){d.overflow=n.overflow[0],d.overflowX=n.overflow[1],d.overflowY=n.overflow[2]}));for(i in t)if(a=t[i],Vn.exec(a)){if(delete t[i],u=u||"toggle"===a,a===(m?"hide":"show"))continue;g.push(i)}if(o=g.length){s=b._data(e,"fxshow")||b._data(e,"fxshow",{}),"hidden"in s&&(m=s.hidden),u&&(s.hidden=!m),m?b(e).show():f.done(function(){b(e).hide()}),f.done(function(){var t;b._removeData(e,"fxshow");for(t in h)b.style(e,t,h[t])});for(i=0;o>i;i++)r=g[i],l=f.createTween(r,m?s[r]:0),h[r]=s[r]||b.style(e,r),r in s||(s[r]=l.start,m&&(l.end=l.start,l.start="width"===r||"height"===r?1:0))}}function rr(e,t,n,r,i){return new rr.prototype.init(e,t,n,r,i)}b.Tween=rr,rr.prototype={constructor:rr,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||"swing",this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(b.cssNumber[n]?"":"px")},cur:function(){var e=rr.propHooks[this.prop];return e&&e.get?e.get(this):rr.propHooks._default.get(this)},run:function(e){var t,n=rr.propHooks[this.prop];return this.pos=t=this.options.duration?b.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):rr.propHooks._default.set(this),this}},rr.prototype.init.prototype=rr.prototype,rr.propHooks={_default:{get:function(e){var t;return null==e.elem[e.prop]||e.elem.style&&null!=e.elem.style[e.prop]?(t=b.css(e.elem,e.prop,""),t&&"auto"!==t?t:0):e.elem[e.prop]},set:function(e){b.fx.step[e.prop]?b.fx.step[e.prop](e):e.elem.style&&(null!=e.elem.style[b.cssProps[e.prop]]||b.cssHooks[e.prop])?b.style(e.elem,e.prop,e.now+e.unit):e.elem[e.prop]=e.now}}},rr.propHooks.scrollTop=rr.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},b.each(["toggle","show","hide"],function(e,t){var n=b.fn[t];b.fn[t]=function(e,r,i){return null==e||"boolean"==typeof e?n.apply(this,arguments):this.animate(ir(t,!0),e,r,i)}}),b.fn.extend({fadeTo:function(e,t,n,r){return this.filter(nn).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(e,t,n,r){var i=b.isEmptyObject(e),o=b.speed(t,n,r),a=function(){var t=er(this,b.extend({},e),o);a.finish=function(){t.stop(!0)},(i||b._data(this,"finish"))&&t.stop(!0)};return a.finish=a,i||o.queue===!1?this.each(a):this.queue(o.queue,a)},stop:function(e,n,r){var i=function(e){var t=e.stop;delete e.stop,t(r)};return"string"!=typeof e&&(r=n,n=e,e=t),n&&e!==!1&&this.queue(e||"fx",[]),this.each(function(){var t=!0,n=null!=e&&e+"queueHooks",o=b.timers,a=b._data(this);if(n)a[n]&&a[n].stop&&i(a[n]);else for(n in a)a[n]&&a[n].stop&&Jn.test(n)&&i(a[n]);for(n=o.length;n--;)o[n].elem!==this||null!=e&&o[n].queue!==e||(o[n].anim.stop(r),t=!1,o.splice(n,1));(t||!r)&&b.dequeue(this,e)})},finish:function(e){return e!==!1&&(e=e||"fx"),this.each(function(){var t,n=b._data(this),r=n[e+"queue"],i=n[e+"queueHooks"],o=b.timers,a=r?r.length:0;for(n.finish=!0,b.queue(this,e,[]),i&&i.cur&&i.cur.finish&&i.cur.finish.call(this),t=o.length;t--;)o[t].elem===this&&o[t].queue===e&&(o[t].anim.stop(!0),o.splice(t,1));for(t=0;a>t;t++)r[t]&&r[t].finish&&r[t].finish.call(this);delete n.finish})}});function ir(e,t){var n,r={height:e},i=0;for(t=t?1:0;4>i;i+=2-t)n=Zt[i],r["margin"+n]=r["padding"+n]=e;return t&&(r.opacity=r.width=e),r}b.each({slideDown:ir("show"),slideUp:ir("hide"),slideToggle:ir("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,t){b.fn[e]=function(e,n,r){return this.animate(t,e,n,r)}}),b.speed=function(e,t,n){var r=e&&"object"==typeof e?b.extend({},e):{complete:n||!n&&t||b.isFunction(e)&&e,duration:e,easing:n&&t||t&&!b.isFunction(t)&&t};return r.duration=b.fx.off?0:"number"==typeof r.duration?r.duration:r.duration in b.fx.speeds?b.fx.speeds[r.duration]:b.fx.speeds._default,(null==r.queue||r.queue===!0)&&(r.queue="fx"),r.old=r.complete,r.complete=function(){b.isFunction(r.old)&&r.old.call(this),r.queue&&b.dequeue(this,r.queue)},r},b.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2}},b.timers=[],b.fx=rr.prototype.init,b.fx.tick=function(){var e,n=b.timers,r=0;for(Xn=b.now();n.length>r;r++)e=n[r],e()||n[r]!==e||n.splice(r--,1);n.length||b.fx.stop(),Xn=t},b.fx.timer=function(e){e()&&b.timers.push(e)&&b.fx.start()},b.fx.interval=13,b.fx.start=function(){Un||(Un=setInterval(b.fx.tick,b.fx.interval))},b.fx.stop=function(){clearInterval(Un),Un=null},b.fx.speeds={slow:600,fast:200,_default:400},b.fx.step={},b.expr&&b.expr.filters&&(b.expr.filters.animated=function(e){return b.grep(b.timers,function(t){return e===t.elem}).length}),b.fn.offset=function(e){if(arguments.length)return e===t?this:this.each(function(t){b.offset.setOffset(this,e,t)});var n,r,o={top:0,left:0},a=this[0],s=a&&a.ownerDocument;if(s)return n=s.documentElement,b.contains(n,a)?(typeof a.getBoundingClientRect!==i&&(o=a.getBoundingClientRect()),r=or(s),{top:o.top+(r.pageYOffset||n.scrollTop)-(n.clientTop||0),left:o.left+(r.pageXOffset||n.scrollLeft)-(n.clientLeft||0)}):o},b.offset={setOffset:function(e,t,n){var r=b.css(e,"position");"static"===r&&(e.style.position="relative");var i=b(e),o=i.offset(),a=b.css(e,"top"),s=b.css(e,"left"),u=("absolute"===r||"fixed"===r)&&b.inArray("auto",[a,s])>-1,l={},c={},p,f;u?(c=i.position(),p=c.top,f=c.left):(p=parseFloat(a)||0,f=parseFloat(s)||0),b.isFunction(t)&&(t=t.call(e,n,o)),null!=t.top&&(l.top=t.top-o.top+p),null!=t.left&&(l.left=t.left-o.left+f),"using"in t?t.using.call(e,l):i.css(l)}},b.fn.extend({position:function(){if(this[0]){var e,t,n={top:0,left:0},r=this[0];return"fixed"===b.css(r,"position")?t=r.getBoundingClientRect():(e=this.offsetParent(),t=this.offset(),b.nodeName(e[0],"html")||(n=e.offset()),n.top+=b.css(e[0],"borderTopWidth",!0),n.left+=b.css(e[0],"borderLeftWidth",!0)),{top:t.top-n.top-b.css(r,"marginTop",!0),left:t.left-n.left-b.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||o.documentElement;while(e&&!b.nodeName(e,"html")&&"static"===b.css(e,"position"))e=e.offsetParent;return e||o.documentElement})}}),b.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(e,n){var r=/Y/.test(n);b.fn[e]=function(i){return b.access(this,function(e,i,o){var a=or(e);return o===t?a?n in a?a[n]:a.document.documentElement[i]:e[i]:(a?a.scrollTo(r?b(a).scrollLeft():o,r?o:b(a).scrollTop()):e[i]=o,t)},e,i,arguments.length,null)}});function or(e){return b.isWindow(e)?e:9===e.nodeType?e.defaultView||e.parentWindow:!1}b.each({Height:"height",Width:"width"},function(e,n){b.each({padding:"inner"+e,content:n,"":"outer"+e},function(r,i){b.fn[i]=function(i,o){var a=arguments.length&&(r||"boolean"!=typeof i),s=r||(i===!0||o===!0?"margin":"border");return b.access(this,function(n,r,i){var o;return b.isWindow(n)?n.document.documentElement["client"+e]:9===n.nodeType?(o=n.documentElement,Math.max(n.body["scroll"+e],o["scroll"+e],n.body["offset"+e],o["offset"+e],o["client"+e])):i===t?b.css(n,r,s):b.style(n,r,i,s)},n,a?i:t,a,null)}})}),e.jQuery=e.$=b,"function"==typeof define&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return b})})(window);
\ No newline at end of file
diff --git a/examples/quickstart/src/main/webapp/static/styles/default.css b/examples/quickstart/src/main/webapp/static/styles/default.css
deleted file mode 100644
index d0e66f7d2..000000000
--- a/examples/quickstart/src/main/webapp/static/styles/default.css
+++ /dev/null
@@ -1,20 +0,0 @@
-/* header */
-#header {margin-bottom:15px;}
-
-#header h1 a {
- color: #658A16;
- text-decoration: none
-}
-
-#header h1 small {color: #BACE87;}
-
-/* footer */
-#footer {
- margin-top: 15px;
- padding: 15px 0px 0px 0px;
- font-size: 95%;
- text-align: center;
- border-top: 2px solid #658A16;
-}
-
-#footer a {color: #999;}
\ No newline at end of file
diff --git a/examples/quickstart/src/test/functional/org/springside/examples/quickstart/functional/BaseFunctionalTestCase.java b/examples/quickstart/src/test/functional/org/springside/examples/quickstart/functional/BaseFunctionalTestCase.java
deleted file mode 100644
index 36d044fd5..000000000
--- a/examples/quickstart/src/test/functional/org/springside/examples/quickstart/functional/BaseFunctionalTestCase.java
+++ /dev/null
@@ -1,93 +0,0 @@
-package org.springside.examples.quickstart.functional;
-
-import java.net.URL;
-import java.sql.Driver;
-
-import org.eclipse.jetty.server.Server;
-import org.junit.BeforeClass;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.jdbc.datasource.SimpleDriverDataSource;
-import org.springside.examples.quickstart.QuickStartServer;
-import org.springside.modules.test.data.DataFixtures;
-import org.springside.modules.test.jetty.JettyFactory;
-import org.springside.modules.test.spring.Profiles;
-import org.springside.modules.utils.PropertiesLoader;
-
-/**
- * 功能测试基类.
- *
- * 在整个测试期间启动一次Jetty Server和 Selenium,在JVM退出时关闭两者。
- * 在每个TestCase Class执行前重新载入默认数据.
- *
- * @author calvin
- */
-public class BaseFunctionalTestCase {
-
- protected static String baseUrl;
-
- protected static Server jettyServer;
-
- protected static SimpleDriverDataSource dataSource;
-
- protected static PropertiesLoader propertiesLoader = new PropertiesLoader("classpath:/application.properties",
- "classpath:/application.functional.properties", "classpath:/application.functional-local.properties");
-
- private static Logger logger = LoggerFactory.getLogger(BaseFunctionalTestCase.class);
-
- @BeforeClass
- public static void initFunctionalTestEnv() throws Exception {
- baseUrl = propertiesLoader.getProperty("baseUrl");
-
- // 如果是目标地址是localhost,则启动嵌入式jetty。如果指向远程地址,则不需要启动Jetty.
- boolean isEmbedded = new URL(baseUrl).getHost().equals("localhost")
- && propertiesLoader.getBoolean("embeddedForLocal");
-
- if (isEmbedded) {
- startJettyOnce();
- }
-
- buildDataSourceOnce();
- reloadSampleData();
- }
-
- /**
- * 启动Jetty服务器, 仅启动一次.
- */
- protected static void startJettyOnce() throws Exception {
- if (jettyServer == null) {
- // 设定Spring的profile
- Profiles.setProfileAsSystemProperty(Profiles.FUNCTIONAL_TEST);
-
- jettyServer = JettyFactory.createServerInSource(new URL(baseUrl).getPort(), QuickStartServer.CONTEXT);
- JettyFactory.setTldJarNames(jettyServer, QuickStartServer.TLD_JAR_NAMES);
- jettyServer.start();
-
- logger.info("Jetty Server started at {}", baseUrl);
- }
- }
-
- /**
- * 构造数据源,仅构造一次.
- * 连接参数从配置文件中读取,可指向本地的开发环境,也可以指向远程的测试服务器。
- */
- protected static void buildDataSourceOnce() throws ClassNotFoundException {
- if (dataSource == null) {
- dataSource = new SimpleDriverDataSource();
- dataSource.setDriverClass((Class extends Driver>) Class.forName(propertiesLoader
- .getProperty("jdbc.driver")));
- dataSource.setUrl(propertiesLoader.getProperty("jdbc.url"));
- dataSource.setUsername(propertiesLoader.getProperty("jdbc.username"));
- dataSource.setPassword(propertiesLoader.getProperty("jdbc.password"));
- }
- }
-
- /**
- * 载入测试数据.
- */
- protected static void reloadSampleData() throws Exception {
- String dbType = propertiesLoader.getProperty("db.type", "h2");
- DataFixtures.executeScript(dataSource, "classpath:data/" + dbType + "/cleanup-data.sql", "classpath:data/"
- + dbType + "/import-data.sql");
- }
-}
\ No newline at end of file
diff --git a/examples/quickstart/src/test/functional/org/springside/examples/quickstart/functional/BaseSeleniumTestCase.java b/examples/quickstart/src/test/functional/org/springside/examples/quickstart/functional/BaseSeleniumTestCase.java
deleted file mode 100644
index 25294d44d..000000000
--- a/examples/quickstart/src/test/functional/org/springside/examples/quickstart/functional/BaseSeleniumTestCase.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package org.springside.examples.quickstart.functional;
-
-import org.junit.BeforeClass;
-import org.junit.Rule;
-import org.junit.rules.TestRule;
-import org.openqa.selenium.By;
-import org.openqa.selenium.WebDriver;
-import org.springside.modules.test.selenium.Selenium2;
-import org.springside.modules.test.selenium.SeleniumSnapshotRule;
-import org.springside.modules.test.selenium.WebDriverFactory;
-
-/**
- * 使用Selenium的功能测试基类.
- *
- * 在BaseFunctionalTestCase的基础上,在整个测试期间仅启动一次Selenium.
- *
- * @author calvin
- */
-public class BaseSeleniumTestCase extends BaseFunctionalTestCase {
-
- protected static Selenium2 s;
-
- // 出错时截屏的规则
- @Rule
- public TestRule snapshotRule = new SeleniumSnapshotRule(s);
-
- @BeforeClass
- public static void initSelenium() throws Exception {
- createSeleniumOnce();
- loginAsUserIfNecessary();
- }
-
- /**
- * 创建Selenium,仅创建一次.
- */
- protected static void createSeleniumOnce() throws Exception {
- if (s == null) {
- // 根据配置创建Selenium driver.
- String driverName = propertiesLoader.getProperty("selenium.driver");
-
- WebDriver driver = WebDriverFactory.createDriver(driverName);
-
- s = new Selenium2(driver, baseUrl);
- s.setStopAtShutdown();
- }
- }
-
- /**
- * 登录管理员, 如果用户还没有登录.
- */
- protected static void loginAsUserIfNecessary() {
- s.open("/task");
-
- if ("QuickStart示例:登录页".equals(s.getTitle())) {
- s.type(By.name("username"), "user");
- s.type(By.name("password"), "user");
- s.check(By.name("rememberMe"));
- s.click(By.id("submit_btn"));
- s.waitForTitleContains("任务管理");
- }
- }
-}
diff --git a/examples/quickstart/src/test/functional/org/springside/examples/quickstart/functional/gui/ProfileFT.java b/examples/quickstart/src/test/functional/org/springside/examples/quickstart/functional/gui/ProfileFT.java
deleted file mode 100644
index aa8439dec..000000000
--- a/examples/quickstart/src/test/functional/org/springside/examples/quickstart/functional/gui/ProfileFT.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package org.springside.examples.quickstart.functional.gui;
-
-import static org.junit.Assert.*;
-
-import org.junit.Test;
-import org.openqa.selenium.By;
-import org.springside.examples.quickstart.functional.BaseSeleniumTestCase;
-
-public class ProfileFT extends BaseSeleniumTestCase {
-
- /**
- * 修改用户资料.
- */
- @Test
- public void editProfile() {
- s.open("/profile");
- s.type(By.id("name"), "Kevin");
- s.click(By.id("submit_btn"));
-
- assertTrue("没有成功消息", s.isTextPresent("Kevin"));
- }
-}
diff --git a/examples/quickstart/src/test/functional/org/springside/examples/quickstart/functional/gui/RegisterFT.java b/examples/quickstart/src/test/functional/org/springside/examples/quickstart/functional/gui/RegisterFT.java
deleted file mode 100644
index 6c6fd9201..000000000
--- a/examples/quickstart/src/test/functional/org/springside/examples/quickstart/functional/gui/RegisterFT.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package org.springside.examples.quickstart.functional.gui;
-
-import static org.junit.Assert.*;
-
-import org.junit.Test;
-import org.openqa.selenium.By;
-import org.springside.examples.quickstart.functional.BaseSeleniumTestCase;
-
-public class RegisterFT extends BaseSeleniumTestCase {
-
- @Test
- public void register() {
- //注册用户
- s.open("/logout");
- s.click(By.linkText("注册"));
-
- s.type(By.id("loginName"), "user2");
- s.type(By.id("name"), "Kevin");
- s.type(By.id("plainPassword"), "user2");
- s.type(By.id("confirmPassword"), "user2");
-
- s.click(By.id("submit_btn"));
-
- //跳转到登录页
- s.waitForTitleContains("登录页");
- assertEquals("user2", s.getValue(By.name("username")));
-
- s.type(By.name("password"), "user2");
- s.click(By.id("submit_btn"));
-
- //登陆成功
- s.waitForTitleContains("任务管理");
-
- //退出用户
- s.open("/logout");
- }
-
- @Test
- public void inputInValidateValue() {
- s.open("/register");
- s.click(By.id("submit_btn"));
-
- assertEquals("必选字段", s.getText(By.xpath("//fieldset/div/div/span")));
- }
-
-}
diff --git a/examples/quickstart/src/test/functional/org/springside/examples/quickstart/functional/gui/SecurityFT.java b/examples/quickstart/src/test/functional/org/springside/examples/quickstart/functional/gui/SecurityFT.java
deleted file mode 100644
index 57ac1655a..000000000
--- a/examples/quickstart/src/test/functional/org/springside/examples/quickstart/functional/gui/SecurityFT.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package org.springside.examples.quickstart.functional.gui;
-
-import static org.junit.Assert.*;
-
-import org.junit.Test;
-import org.openqa.selenium.By;
-import org.springside.examples.quickstart.functional.BaseSeleniumTestCase;
-
-/**
- * 系统安全控制的功能测试, 测试主要用户故事.
- *
- * @author calvin
- */
-public class SecurityFT extends BaseSeleniumTestCase {
-
- /**
- * 测试匿名用户访问系统时的行为.
- */
- @Test
- public void anonymousUserAccessSystem() {
- //访问退出登录页面,退出之前的登录
- s.open("/logout");
- s.waitForTitleContains("登录页");
-
- //访问任意页面会跳转到登录界面
- s.open("/task");
- s.waitForTitleContains("登录页");
- }
-
- /**
- * 测试普通用户访问管理员的用户管理功能时代行为。
- */
- @Test
- public void userTryToManageUsers() {
- loginAsUserIfNecessary();
- s.open("/admin/user");
- assertEquals("Error 401 Unauthorized", s.getTitle());
- }
-
- /**
- * 登录错误的用户名密码.
- */
- @Test
- public void loginWithWrongPassword() {
- s.open("/logout");
- s.type(By.name("username"), "wrongUser");
- s.type(By.name("password"), "WrongPassword");
- s.check(By.name("rememberMe"));
- s.click(By.id("submit_btn"));
-
- s.waitForTitleContains("登录页");
- assertTrue(s.isTextPresent("登录失败,请重试."));
- }
-}
diff --git a/examples/quickstart/src/test/functional/org/springside/examples/quickstart/functional/gui/TaskGuiFT.java b/examples/quickstart/src/test/functional/org/springside/examples/quickstart/functional/gui/TaskGuiFT.java
deleted file mode 100644
index 115383d22..000000000
--- a/examples/quickstart/src/test/functional/org/springside/examples/quickstart/functional/gui/TaskGuiFT.java
+++ /dev/null
@@ -1,76 +0,0 @@
-package org.springside.examples.quickstart.functional.gui;
-
-import static org.junit.Assert.*;
-
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-import org.openqa.selenium.By;
-import org.openqa.selenium.WebElement;
-import org.springside.examples.quickstart.data.TaskData;
-import org.springside.examples.quickstart.entity.Task;
-import org.springside.examples.quickstart.functional.BaseSeleniumTestCase;
-import org.springside.modules.test.category.Smoke;
-
-/**
- * 任务管理的功能测试, 测试页面JavaScript及主要用户故事流程.
- *
- * @author calvin
- */
-public class TaskGuiFT extends BaseSeleniumTestCase {
-
- /**
- * 浏览任务列表.
- */
- @Test
- @Category(Smoke.class)
- public void viewTaskList() {
- s.open("/task/");
- WebElement table = s.findElement(By.id("contentTable"));
- assertEquals("Release SpringSide 4.0", s.getTable(table, 0, 0));
- }
-
- /**
- * 创建/更新/搜索/删除任务.
- */
- @Test
- @Category(Smoke.class)
- public void crudTask() {
- s.open("/task/");
-
- // create
- s.click(By.linkText("创建任务"));
-
- Task task = TaskData.randomTask();
- s.type(By.id("task_title"), task.getTitle());
- s.click(By.id("submit_btn"));
-
- assertTrue(s.isTextPresent("创建任务成功"));
-
- // update
- s.click(By.linkText(task.getTitle()));
- assertEquals(task.getTitle(), s.getValue(By.id("task_title")));
-
- String newTitle = TaskData.randomTitle();
- s.type(By.id("task_title"), newTitle);
- s.click(By.id("submit_btn"));
- assertTrue(s.isTextPresent("更新任务成功"));
-
- // search
- s.type(By.name("search_LIKE_title"), newTitle);
- s.click(By.id("search_btn"));
- assertEquals(newTitle, s.getTable(By.id("contentTable"), 0, 0));
-
- // delete
- s.click(By.linkText("删除"));
- assertTrue("没有成功消息", s.isTextPresent("删除任务成功"));
- }
-
- @Test
- public void inputInValidateValue() {
- s.open("/task/");
- s.click(By.linkText("创建任务"));
- s.click(By.id("submit_btn"));
-
- assertEquals("必选字段", s.getText(By.xpath("//fieldset/div/div/span")));
- }
-}
diff --git a/examples/quickstart/src/test/functional/org/springside/examples/quickstart/functional/gui/UserAdminFT.java b/examples/quickstart/src/test/functional/org/springside/examples/quickstart/functional/gui/UserAdminFT.java
deleted file mode 100644
index a92f7c4ec..000000000
--- a/examples/quickstart/src/test/functional/org/springside/examples/quickstart/functional/gui/UserAdminFT.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package org.springside.examples.quickstart.functional.gui;
-
-import static org.junit.Assert.*;
-
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-import org.openqa.selenium.By;
-import org.openqa.selenium.WebElement;
-import org.springside.examples.quickstart.functional.BaseSeleniumTestCase;
-import org.springside.modules.test.category.Smoke;
-
-public class UserAdminFT extends BaseSeleniumTestCase {
-
- @BeforeClass
- public static void loginAsAdmin() {
- s.open("/logout");
- s.type(By.name("username"), "admin");
- s.type(By.name("password"), "admin");
- s.click(By.id("submit_btn"));
- }
-
- @AfterClass
- public static void logout() {
- s.open("/logout");
- }
-
- /**
- * 浏览用户列表.
- */
- @Test
- @Category(Smoke.class)
- public void viewUserList() {
- s.open("/admin/user");
- WebElement table = s.findElement(By.id("contentTable"));
- assertEquals("admin", s.getTable(table, 0, 0));
- assertEquals("user", s.getTable(table, 1, 0));
- }
-
- @Test
- public void editUser() {
- s.open("/admin/user/update/2");
- s.type(By.id("name"), "Kevin");
- s.type(By.id("plainPassword"), "user2");
- s.type(By.id("confirmPassword"), "user2");
- s.click(By.id("submit_btn"));
-
- assertTrue("没有成功消息", s.isTextPresent("更新用户user成功"));
- WebElement table = s.findElement(By.id("contentTable"));
- assertEquals("Kevin", s.getTable(table, 1, 1));
- }
-
- @Test
- public void deleteUser() {
- s.open("/admin/user/delete/2");
- assertTrue("没有成功消息", s.isTextPresent("删除用户user成功"));
- }
-}
diff --git a/examples/quickstart/src/test/functional/org/springside/examples/quickstart/functional/rest/TaskRestFT.java b/examples/quickstart/src/test/functional/org/springside/examples/quickstart/functional/rest/TaskRestFT.java
deleted file mode 100644
index 59644f256..000000000
--- a/examples/quickstart/src/test/functional/org/springside/examples/quickstart/functional/rest/TaskRestFT.java
+++ /dev/null
@@ -1,127 +0,0 @@
-package org.springside.examples.quickstart.functional.rest;
-
-import static org.junit.Assert.*;
-
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.Map;
-
-import org.apache.commons.lang3.StringUtils;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-import org.springframework.http.HttpStatus;
-import org.springframework.web.client.HttpStatusCodeException;
-import org.springframework.web.client.RestTemplate;
-import org.springside.examples.quickstart.data.TaskData;
-import org.springside.examples.quickstart.entity.Task;
-import org.springside.examples.quickstart.functional.BaseFunctionalTestCase;
-import org.springside.modules.mapper.JsonMapper;
-import org.springside.modules.test.category.Smoke;
-
-/**
- * 任务管理的功能测试, 测试页面JavaScript及主要用户故事流程.
- *
- * @author calvin
- */
-public class TaskRestFT extends BaseFunctionalTestCase {
-
- private final RestTemplate restTemplate = new RestTemplate();
-
- private final JsonMapper jsonMapper = new JsonMapper();
-
- private static class TaskList extends ArrayList
{
- }
-
- private static String resoureUrl;
-
- @BeforeClass
- public static void initUrl() {
- resoureUrl = baseUrl + "/api/v1/task";
- }
-
- /**
- * 查看任务列表.
- */
- @Test
- @Category(Smoke.class)
- public void listTasks() {
- TaskList tasks = restTemplate.getForObject(resoureUrl, TaskList.class);
- assertEquals(5, tasks.size());
- assertEquals("Study PlayFramework 2.0", tasks.get(0).getTitle());
- }
-
- /**
- * 获取任务.
- */
- @Test
- @Category(Smoke.class)
- public void getTask() {
- Task task = restTemplate.getForObject(resoureUrl + "/{id}", Task.class, 1L);
- assertEquals("Study PlayFramework 2.0", task.getTitle());
- }
-
- /**
- * 创建/更新/删除任务.
- */
- @Test
- @Category(Smoke.class)
- public void createUpdateAndDeleteTask() {
-
- // create
- Task task = TaskData.randomTask();
-
- URI taskUri = restTemplate.postForLocation(resoureUrl, task);
- System.out.println(taskUri.toString());
- Task createdTask = restTemplate.getForObject(taskUri, Task.class);
- assertEquals(task.getTitle(), createdTask.getTitle());
-
- // update
- String id = StringUtils.substringAfterLast(taskUri.toString(), "/");
- task.setId(new Long(id));
- task.setTitle(TaskData.randomTitle());
-
- restTemplate.put(taskUri, task);
-
- Task updatedTask = restTemplate.getForObject(taskUri, Task.class);
- assertEquals(task.getTitle(), updatedTask.getTitle());
-
- // delete
- restTemplate.delete(taskUri);
-
- try {
- restTemplate.getForObject(taskUri, Task.class);
- fail("Get should fail while feth a deleted task");
- } catch (HttpStatusCodeException e) {
- assertEquals(HttpStatus.NOT_FOUND, e.getStatusCode());
- }
- }
-
- @Test
- public void invalidInput() {
-
- // create
- Task titleBlankTask = new Task();
- try {
- restTemplate.postForLocation(resoureUrl, titleBlankTask);
- fail("Create should fail while title is blank");
- } catch (HttpStatusCodeException e) {
- assertEquals(HttpStatus.BAD_REQUEST, e.getStatusCode());
- Map messages = jsonMapper.fromJson(e.getResponseBodyAsString(), Map.class);
- assertEquals(1, messages.size());
- assertTrue(messages.get("title").equals("may not be empty") || messages.get("title").equals("不能为空"));
- }
-
- // update
- titleBlankTask.setId(1L);
- try {
- restTemplate.put(resoureUrl + "/1", titleBlankTask);
- fail("Update should fail while title is blank");
- } catch (HttpStatusCodeException e) {
- assertEquals(HttpStatus.BAD_REQUEST, e.getStatusCode());
- Map messages = jsonMapper.fromJson(e.getResponseBodyAsString(), Map.class);
- assertEquals(1, messages.size());
- assertTrue(messages.get("title").equals("may not be empty") || messages.get("title").equals("不能为空"));
- }
- }
-}
diff --git a/examples/quickstart/src/test/java/org/springside/examples/quickstart/QuickStartServer.java b/examples/quickstart/src/test/java/org/springside/examples/quickstart/QuickStartServer.java
deleted file mode 100644
index 1c90d05a2..000000000
--- a/examples/quickstart/src/test/java/org/springside/examples/quickstart/QuickStartServer.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package org.springside.examples.quickstart;
-
-import org.eclipse.jetty.server.Server;
-import org.springside.modules.test.jetty.JettyFactory;
-import org.springside.modules.test.spring.Profiles;
-
-/**
- * 使用Jetty运行调试Web应用, 在Console输入回车快速重新加载应用.
- *
- * @author calvin
- */
-public class QuickStartServer {
-
- public static final int PORT = 8080;
- public static final String CONTEXT = "/quickstart";
- public static final String[] TLD_JAR_NAMES = new String[] { "sitemesh", "spring-webmvc", "shiro-web",
- "springside-core" };
-
- public static void main(String[] args) throws Exception {
- // 设定Spring的profile
- Profiles.setProfileAsSystemProperty(Profiles.DEVELOPMENT);
-
- // 启动Jetty
- Server server = JettyFactory.createServerInSource(PORT, CONTEXT);
- JettyFactory.setTldJarNames(server, TLD_JAR_NAMES);
-
- try {
- server.start();
-
- System.out.println("[INFO] Server running at http://localhost:" + PORT + CONTEXT);
- System.out.println("[HINT] Hit Enter to reload the application quickly");
-
- // 等待用户输入回车重载应用.
- while (true) {
- char c = (char) System.in.read();
- if (c == '\n') {
- JettyFactory.reloadContext(server);
- }
- }
- } catch (Exception e) {
- e.printStackTrace();
- System.exit(-1);
- }
- }
-}
diff --git a/examples/quickstart/src/test/java/org/springside/examples/quickstart/data/TaskData.java b/examples/quickstart/src/test/java/org/springside/examples/quickstart/data/TaskData.java
deleted file mode 100644
index ba9798baa..000000000
--- a/examples/quickstart/src/test/java/org/springside/examples/quickstart/data/TaskData.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package org.springside.examples.quickstart.data;
-
-import org.springside.examples.quickstart.entity.Task;
-import org.springside.examples.quickstart.entity.User;
-import org.springside.modules.test.data.RandomData;
-
-/**
- * Task相关实体测试数据生成.
- *
- * @author calvin
- */
-public class TaskData {
-
- public static Task randomTask() {
- Task task = new Task();
- task.setTitle(randomTitle());
- User user = new User(1L);
- task.setUser(user);
- return task;
- }
-
- public static String randomTitle() {
- return RandomData.randomName("Task");
- }
-}
diff --git a/examples/quickstart/src/test/java/org/springside/examples/quickstart/data/UserData.java b/examples/quickstart/src/test/java/org/springside/examples/quickstart/data/UserData.java
deleted file mode 100644
index 7abcc5c48..000000000
--- a/examples/quickstart/src/test/java/org/springside/examples/quickstart/data/UserData.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package org.springside.examples.quickstart.data;
-
-import org.springside.examples.quickstart.entity.User;
-import org.springside.modules.test.data.RandomData;
-
-public class UserData {
-
- public static User randomNewUser() {
- User user = new User();
- user.setLoginName(RandomData.randomName("user"));
- user.setName(RandomData.randomName("User"));
- user.setPlainPassword(RandomData.randomName("password"));
-
- return user;
- }
-}
diff --git a/examples/quickstart/src/test/java/org/springside/examples/quickstart/repository/JpaMappingTest.java b/examples/quickstart/src/test/java/org/springside/examples/quickstart/repository/JpaMappingTest.java
deleted file mode 100644
index 6ed14fa61..000000000
--- a/examples/quickstart/src/test/java/org/springside/examples/quickstart/repository/JpaMappingTest.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package org.springside.examples.quickstart.repository;
-
-import static org.junit.Assert.*;
-
-import javax.persistence.EntityManager;
-import javax.persistence.PersistenceContext;
-import javax.persistence.metamodel.EntityType;
-import javax.persistence.metamodel.Metamodel;
-
-import org.junit.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.test.context.ContextConfiguration;
-import org.springside.modules.test.spring.SpringTransactionalTestCase;
-
-@ContextConfiguration(locations = { "/applicationContext.xml" })
-public class JpaMappingTest extends SpringTransactionalTestCase {
-
- private static Logger logger = LoggerFactory.getLogger(JpaMappingTest.class);
-
- @PersistenceContext
- private EntityManager em;
-
- @Test
- public void allClassMapping() throws Exception {
- Metamodel model = em.getEntityManagerFactory().getMetamodel();
-
- assertTrue("No entity mapping found", model.getEntities().size() > 0);
-
- for (EntityType entityType : model.getEntities()) {
- String entityName = entityType.getName();
- em.createQuery("select o from " + entityName + " o").getResultList();
- logger.info("ok: " + entityName);
-
- }
- }
-}
diff --git a/examples/quickstart/src/test/java/org/springside/examples/quickstart/repository/TaskDaoTest.java b/examples/quickstart/src/test/java/org/springside/examples/quickstart/repository/TaskDaoTest.java
deleted file mode 100644
index 1f74c9b8f..000000000
--- a/examples/quickstart/src/test/java/org/springside/examples/quickstart/repository/TaskDaoTest.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package org.springside.examples.quickstart.repository;
-
-import static org.junit.Assert.*;
-
-import org.junit.Test;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.domain.Page;
-import org.springframework.data.domain.PageRequest;
-import org.springframework.data.domain.Sort.Direction;
-import org.springframework.test.context.ContextConfiguration;
-import org.springside.examples.quickstart.entity.Task;
-import org.springside.modules.test.spring.SpringTransactionalTestCase;
-
-@ContextConfiguration(locations = { "/applicationContext.xml" })
-public class TaskDaoTest extends SpringTransactionalTestCase {
-
- @Autowired
- private TaskDao taskDao;
-
- @Test
- public void findTasksByUserId() throws Exception {
- Page tasks = taskDao.findByUserId(2L, new PageRequest(0, 100, Direction.ASC, "id"));
- assertEquals(5, tasks.getContent().size());
- assertEquals(new Long(1), tasks.getContent().get(0).getId());
-
- tasks = taskDao.findByUserId(99999L, new PageRequest(0, 100, Direction.ASC, "id"));
- assertEquals(0, tasks.getContent().size());
- }
-}
diff --git a/examples/quickstart/src/test/java/org/springside/examples/quickstart/service/account/AccountServiceTest.java b/examples/quickstart/src/test/java/org/springside/examples/quickstart/service/account/AccountServiceTest.java
deleted file mode 100644
index e0f1f30b0..000000000
--- a/examples/quickstart/src/test/java/org/springside/examples/quickstart/service/account/AccountServiceTest.java
+++ /dev/null
@@ -1,89 +0,0 @@
-package org.springside.examples.quickstart.service.account;
-
-import static org.junit.Assert.*;
-
-import java.util.Date;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-import org.springside.examples.quickstart.data.UserData;
-import org.springside.examples.quickstart.entity.User;
-import org.springside.examples.quickstart.repository.TaskDao;
-import org.springside.examples.quickstart.repository.UserDao;
-import org.springside.examples.quickstart.service.ServiceException;
-import org.springside.examples.quickstart.service.account.ShiroDbRealm.ShiroUser;
-import org.springside.modules.test.security.shiro.ShiroTestUtils;
-import org.springside.modules.utils.Clock.MockClock;
-
-/**
- * AccountService的测试用例, 测试Service层的业务逻辑.
- *
- * @author calvin
- */
-public class AccountServiceTest {
-
- @InjectMocks
- private AccountService accountService;
-
- @Mock
- private UserDao mockUserDao;
-
- @Mock
- private TaskDao mockTaskDao;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- ShiroTestUtils.mockSubject(new ShiroUser(3L, "foo", "Foo"));
- }
-
- @Test
- public void registerUser() {
- User user = UserData.randomNewUser();
- Date currentTime = new Date();
- accountService.setClock(new MockClock(currentTime));
-
- accountService.registerUser(user);
-
- // 验证user的角色,注册日期和加密后的密码都被自动更新了。
- assertEquals("user", user.getRoles());
- assertEquals(currentTime, user.getRegisterDate());
- assertNotNull(user.getPassword());
- assertNotNull(user.getSalt());
- }
-
- @Test
- public void updateUser() {
- // 如果明文密码不为空,加密密码会被更新.
- User user = UserData.randomNewUser();
- accountService.updateUser(user);
- assertNotNull(user.getSalt());
-
- // 如果明文密码为空,加密密码无变化。
- User user2 = UserData.randomNewUser();
- user2.setPlainPassword(null);
- accountService.updateUser(user2);
- assertNull(user2.getSalt());
- }
-
- @Test
- public void deleteUser() {
- // 正常删除用户.
- accountService.deleteUser(2L);
- Mockito.verify(mockUserDao).delete(2L);
-
- // 删除超级管理用户抛出异常, userDao没有被执行
- try {
- accountService.deleteUser(1L);
- fail("expected ServicExcepton not be thrown");
- } catch (ServiceException e) {
- // expected exception
- }
- Mockito.verify(mockUserDao, Mockito.never()).delete(1L);
- }
-
-}
diff --git a/examples/quickstart/src/test/resources/application.development.properties b/examples/quickstart/src/test/resources/application.development.properties
deleted file mode 100644
index 9dafabc3f..000000000
--- a/examples/quickstart/src/test/resources/application.development.properties
+++ /dev/null
@@ -1,5 +0,0 @@
-#(optional)override jdbc url for local development
-
-#log4jdbc driver
-#jdbc.driver=net.sf.log4jdbc.DriverSpy
-#jdbc.url=jdbc:log4jdbc:h2:file:~/.h2/quickstart;AUTO_SERVER=TRUE;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
\ No newline at end of file
diff --git a/examples/quickstart/src/test/resources/application.functional.properties b/examples/quickstart/src/test/resources/application.functional.properties
deleted file mode 100644
index 5f934c5a1..000000000
--- a/examples/quickstart/src/test/resources/application.functional.properties
+++ /dev/null
@@ -1,15 +0,0 @@
-baseUrl=http://localhost:8082/quickstart
-embeddedForLocal=true
-
-#selenium settings, options include firefox,ie,chrome,remote:localhost:4444:firefox
-selenium.driver=firefox
-
-#(optional)override jdbc url for functional test
-db.type=h2
-jdbc.driver=org.h2.Driver
-jdbc.url=jdbc:h2:file:~/.h2/quickstart-test;AUTO_SERVER=TRUE;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
-jdbc.username=sa
-jdbc.password=
-
-#log4jdbc driver
-#jdbc.url=jdbc:log4jdbc:h2:file:~/.h2/quickstart-test;AUTO_SERVER=TRUE;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
diff --git a/examples/quickstart/src/test/resources/application.test.properties b/examples/quickstart/src/test/resources/application.test.properties
deleted file mode 100644
index 963b13e07..000000000
--- a/examples/quickstart/src/test/resources/application.test.properties
+++ /dev/null
@@ -1,8 +0,0 @@
-#(optional)override jdbc url as in-memory db for unit test
-jdbc.driver=org.h2.Driver
-jdbc.url=jdbc:h2:mem:quickstart;DB_CLOSE_DELAY=-1
-jdbc.username=sa
-jdbc.password=
-
-#log4jdbc driver
-#jdbc.url=jdbc:log4jdbc:h2:mem:quickstart;DB_CLOSE_DELAY=-1
\ No newline at end of file
diff --git a/examples/quickstart/src/test/resources/data/h2/cleanup-data.sql b/examples/quickstart/src/test/resources/data/h2/cleanup-data.sql
deleted file mode 100644
index 46312bc26..000000000
--- a/examples/quickstart/src/test/resources/data/h2/cleanup-data.sql
+++ /dev/null
@@ -1,2 +0,0 @@
-delete from ss_task;
-delete from ss_user;
\ No newline at end of file
diff --git a/examples/quickstart/src/test/resources/data/h2/import-data.sql b/examples/quickstart/src/test/resources/data/h2/import-data.sql
deleted file mode 100644
index 8466e90c3..000000000
--- a/examples/quickstart/src/test/resources/data/h2/import-data.sql
+++ /dev/null
@@ -1,8 +0,0 @@
-insert into ss_task (id, title, description, user_id) values(1, 'Study PlayFramework 2.0','http://www.playframework.org/', 2);
-insert into ss_task (id, title, description, user_id) values(2, 'Study Grails 2.0','http://www.grails.org/', 2);
-insert into ss_task (id, title, description, user_id) values(3, 'Try SpringFuse','http://www.springfuse.com/', 2);
-insert into ss_task (id, title, description, user_id) values(4, 'Try Spring Roo','http://www.springsource.org/spring-roo', 2);
-insert into ss_task (id, title, description, user_id) values(5, 'Release SpringSide 4.0','As soon as posibble.', 2);
-
-insert into ss_user (id, login_name, name, password, salt, roles, register_date) values(1,'admin','Admin','691b14d79bf0fa2215f155235df5e670b64394cc','7efbd59d9741d34f','admin','2012-06-04 01:00:00');
-insert into ss_user (id, login_name, name, password, salt, roles, register_date) values(2,'user','Calvin','2488aa0c31c624687bd9928e0a5d29e7d1ed520b','6d65d24122c30500','user','2012-06-04 02:00:00');
\ No newline at end of file
diff --git a/examples/showcase/assembly-standalone.xml b/examples/showcase/assembly-standalone.xml
deleted file mode 100644
index e24d26da7..000000000
--- a/examples/showcase/assembly-standalone.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-
-
- standalone
-
- war
-
- false
-
-
-
- /
-
- org.eclipse.jetty*:*
-
- provided
- true
-
-
- META-INF/*
-
-
-
-
-
-
-
- ${project.basedir}/target/${project.build.finalName}
- /
-
- META-INF/**/*
-
-
-
- ${project.basedir}/target/classes
- /
-
- **/*/Main.class
-
-
-
-
diff --git a/examples/showcase/bin/executable-war.bat b/examples/showcase/bin/executable-war.bat
deleted file mode 100644
index 47eaaaacb..000000000
--- a/examples/showcase/bin/executable-war.bat
+++ /dev/null
@@ -1,14 +0,0 @@
-@echo off
-echo [INFO] Packaging a executable war.
-
-cd %~dp0
-cd ..
-
-set MAVEN_OPTS=%MAVEN_OPTS%
-call mvn clean package -Pstandalone
-
-echo [INFO] Executable war had been packaged as target/showcase-4.x.x.standalone.war
-
-
-cd bin
-pause
\ No newline at end of file
diff --git a/examples/showcase/bin/jetty-large.bat b/examples/showcase/bin/jetty-large.bat
deleted file mode 100644
index 3abdef464..000000000
--- a/examples/showcase/bin/jetty-large.bat
+++ /dev/null
@@ -1,11 +0,0 @@
-@echo off
-echo [INFO] Use maven jetty-plugin run the project.
-
-cd %~dp0
-cd ..
-
-set MAVEN_OPTS=%MAVEN_OPTS% -XX:MaxPermSize=128m -Xms1024m -Xmx1024m -XX:NewSize=512m -server
-call mvn jetty:run -Djetty.port=8080
-
-cd bin
-pause
\ No newline at end of file
diff --git a/examples/showcase/bin/jetty.bat b/examples/showcase/bin/jetty.bat
deleted file mode 100644
index 4027d0287..000000000
--- a/examples/showcase/bin/jetty.bat
+++ /dev/null
@@ -1,11 +0,0 @@
-@echo off
-echo [INFO] Use maven jetty-plugin run the project.
-
-cd %~dp0
-cd ..
-
-set MAVEN_OPTS=%MAVEN_OPTS% -XX:MaxPermSize=128m
-call mvn jetty:run -Djetty.port=8080
-
-cd bin
-pause
\ No newline at end of file
diff --git a/examples/showcase/bin/package.bat b/examples/showcase/bin/package.bat
deleted file mode 100644
index a9b5ddbae..000000000
--- a/examples/showcase/bin/package.bat
+++ /dev/null
@@ -1,8 +0,0 @@
-@echo off
-echo [INFO] Package the war in target dir.
-
-cd %~dp0
-cd ..
-call mvn clean package -Dmaven.test.skip=true
-cd bin
-pause
\ No newline at end of file
diff --git a/examples/showcase/bin/refresh-db.bat b/examples/showcase/bin/refresh-db.bat
deleted file mode 100644
index 6a63ae5de..000000000
--- a/examples/showcase/bin/refresh-db.bat
+++ /dev/null
@@ -1,10 +0,0 @@
-@echo off
-echo [INFO] Re-create the schema and provision the sample data.
-
-cd %~dp0
-cd ..
-
-call mvn antrun:run -Prefresh-db
-
-cd bin
-pause
\ No newline at end of file
diff --git a/examples/showcase/bin/smoke-test.bat b/examples/showcase/bin/smoke-test.bat
deleted file mode 100644
index 6b3ea76b8..000000000
--- a/examples/showcase/bin/smoke-test.bat
+++ /dev/null
@@ -1,11 +0,0 @@
-@echo off
-echo [INFO] run smoking functional test.
-
-cd %~dp0
-cd ..
-
-set MAVEN_OPTS=%MAVEN_OPTS% -XX:MaxPermSize=128m
-call mvn clean test -Pfunctional-test,run-smoke
-
-cd bin
-pause
\ No newline at end of file
diff --git a/examples/showcase/bin/tomcat.bat b/examples/showcase/bin/tomcat.bat
deleted file mode 100644
index 2794b5530..000000000
--- a/examples/showcase/bin/tomcat.bat
+++ /dev/null
@@ -1,11 +0,0 @@
-@echo off
-echo [INFO] Use maven tomcat7-plugin run the project.
-
-cd %~dp0
-cd ..
-
-set MAVEN_OPTS=%MAVEN_OPTS% -XX:MaxPermSize=128m
-call mvn tomcat7:run
-
-cd bin
-pause
\ No newline at end of file
diff --git a/examples/showcase/bin/wsdl2java.bat b/examples/showcase/bin/wsdl2java.bat
deleted file mode 100644
index 07bc578e0..000000000
--- a/examples/showcase/bin/wsdl2java.bat
+++ /dev/null
@@ -1,13 +0,0 @@
-@echo off
-echo Before run this script, please save
-echo http://localhost:8080/showcase/soap/accountservice?wsdl to target/wsdl/accountservice.wsdl
-
-cd %~dp0/../
-call mvn cxf-codegen:wsdl2java
-if errorlevel 1 goto end
-
-echo [INFO] Code had generated to
-pause
-
-:end
-pause
\ No newline at end of file
diff --git a/examples/showcase/bin/yuicompressor.bat b/examples/showcase/bin/yuicompressor.bat
deleted file mode 100644
index 9eb26085d..000000000
--- a/examples/showcase/bin/yuicompressor.bat
+++ /dev/null
@@ -1,7 +0,0 @@
-@echo off
-echo [PreRequirment] Download yuicompressor-2.4.7.jar from http://yuilibrary.com/downloads/yuicompressor and put it here.
-
-cd %~dp0
-java -jar yuicompressor-2.4.7.jar -o ..\src\main\webapp\static\styles\default.min.css ..\src\main\webapp\static\styles\default.css
-
-pause
\ No newline at end of file
diff --git a/examples/showcase/pom.xml b/examples/showcase/pom.xml
deleted file mode 100644
index 32ddaf9ea..000000000
--- a/examples/showcase/pom.xml
+++ /dev/null
@@ -1,629 +0,0 @@
-
-
- 4.0.0
-
- org.springside
- springside-parent
- 4.1.1-SNAPSHOT
- ../../modules/parent/
-
- org.springside.examples
- showcase
- war
- Springside :: Example :: Showcase
-
-
-
- com.h2database
- h2
- ${h2.version}
-
-
-
-
-
-
- org.springside
- springside-core
-
-
- org.springside
- springside-extension
-
-
- org.springside
- springside-metrics
-
-
-
-
-
-
- org.springframework
- spring-context-support
-
-
-
-
-
-
- org.aspectj
- aspectjrt
-
-
- org.aspectj
- aspectjweaver
-
-
-
-
-
-
- org.hibernate
- hibernate-entitymanager
-
-
- org.hibernate
- hibernate-ehcache
-
-
-
-
- org.mybatis
- mybatis
-
-
- org.mybatis
- mybatis-spring
-
-
-
-
- org.springframework.data
- spring-data-jpa
-
-
- org.springframework
- spring-orm
-
-
-
-
- org.apache.tomcat
- tomcat-jdbc
-
-
-
-
- ${jdbc.driver.groupId}
- ${jdbc.driver.artifactId}
- ${jdbc.driver.version}
- runtime
-
-
-
-
-
- org.springframework
- spring-webmvc
-
-
-
- opensymphony
- sitemesh
-
-
-
- javax.servlet
- jstl
-
-
- javax.servlet
- servlet-api
-
-
-
-
-
- org.apache.shiro
- shiro-spring
-
-
- org.apache.shiro
- shiro-ehcache
-
-
-
-
-
- org.apache.cxf
- cxf-rt-frontend-jaxws
-
-
- org.apache.cxf
- cxf-rt-transports-http
-
-
-
-
-
- org.apache.cxf
- cxf-rt-frontend-jaxrs
-
-
- com.fasterxml.jackson.jaxrs
- jackson-jaxrs-json-provider
-
-
-
-
-
- org.springframework
- spring-jms
-
-
-
- org.apache.activemq
- activemq-core
-
-
-
-
-
- org.quartz-scheduler
- quartz
-
-
-
-
- redis.clients
- jedis
-
-
-
-
- net.spy
- spymemcached
-
-
-
- com.thimbleware.jmemcached
- jmemcached-core
-
- runtime
-
-
-
- net.sf.ehcache
- ehcache-core
-
-
-
-
-
- org.jolokia
- jolokia-core
-
-
-
-
- com.netflix.hystrix
- hystrix-core
-
-
-
-
-
- org.javasimon
- javasimon-spring
-
-
- org.javasimon
- javasimon-jdbc4
-
-
- org.javasimon
- javasimon-console-embed
-
-
-
-
-
- org.hibernate
- hibernate-validator
-
-
-
-
- com.fasterxml.jackson.core
- jackson-databind
-
-
- com.fasterxml.jackson.module
- jackson-module-jaxb-annotations
-
-
- com.fasterxml.jackson.datatype
- jackson-datatype-joda
-
-
-
-
- dom4j
- dom4j
-
-
-
- jaxen
- jaxen
-
-
-
-
-
- org.slf4j
- slf4j-api
-
-
-
- ch.qos.logback
- logback-classic
-
-
-
- org.slf4j
- log4j-over-slf4j
-
-
- org.slf4j
- jcl-over-slf4j
-
-
- org.slf4j
- jul-to-slf4j
-
-
-
- com.googlecode.log4jdbc
- log4jdbc
-
-
-
-
-
- org.apache.commons
- commons-lang3
-
-
- commons-io
- commons-io
-
-
- commons-codec
- commons-codec
-
-
- com.google.guava
- guava
-
-
-
- joda-time
- joda-time
-
-
-
-
-
- org.freemarker
- freemarker
-
-
-
- org.apache.httpcomponents
- httpclient
-
-
-
- net.sf.dozer
- dozer
-
-
-
-
- javax.mail
- mail
-
-
- javax.activation
- activation
-
-
-
-
-
- junit
- junit
-
- compile
-
-
-
- org.mockito
- mockito-core
-
-
-
- org.powermock
- powermock-module-junit4
-
-
- org.powermock
- powermock-api-mockito
-
-
-
- org.springside
- springside-test
-
- compile
-
-
-
- org.springframework
- spring-test
-
- compile
-
-
-
-
- org.seleniumhq.selenium
- selenium-java
-
-
- org.seleniumhq.selenium
- selenium-remote-driver
-
-
-
-
- org.eclipse.jetty.aggregate
- jetty-webapp
- provided
-
-
- org.eclipse.jetty
- jetty-jsp
- provided
-
-
-
-
-
-
- com.icegreen
- greenmail
-
-
-
-
-
-
-
-
- org.codehaus.mojo
- build-helper-maven-plugin
-
-
- add-functional-source
- generate-sources
-
- add-test-source
-
-
-
-
-
-
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-surefire-plugin
-
- -Xmx256M
-
-
-
-
-
- org.codehaus.mojo
- cobertura-maven-plugin
-
-
-
- **/entity/*.class
- **/dto/*.class
- **/*Controller.class
- **/*Demo.class
-
-
-
-
-
-
-
- org.mortbay.jetty
- jetty-maven-plugin
-
-
-
- spring.profiles.active
- development
-
-
- true
-
- /${project.artifactId}
-
-
-
-
-
-
- org.apache.tomcat.maven
- tomcat7-maven-plugin
- 2.1
-
-
- development
-
- true
-
-
-
-
-
- org.apache.maven.plugins
- maven-enforcer-plugin
-
-
-
-
- org.apache.cxf
- cxf-codegen-plugin
- ${cxf.version}
-
- ${basedir}/target/generated-sources/cxf
-
-
- ${basedir}/target/wsdl/accountservice.wsdl
-
-
-
-
-
-
-
-
-
-
- functional-test
-
-
-
- org.apache.maven.plugins
- maven-surefire-plugin
-
- -Xmx256M -XX:MaxPermSize=128m
-
- **/*FT.java
-
-
- false
-
-
- ${selenium.driver}
-
-
-
-
-
-
-
-
-
- refresh-db
-
-
-
- org.apache.maven.plugins
- maven-antrun-plugin
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- standalone
-
-
-
- org.apache.maven.plugins
- maven-assembly-plugin
-
-
- package
-
- single
-
-
-
- assembly-standalone.xml
-
-
-
- org.springside.examples.showcase.Main
-
-
-
-
-
-
-
-
-
-
-
-
- standalone-tomcat
-
-
-
- org.apache.tomcat.maven
- tomcat7-maven-plugin
- 2.1
-
-
- tomcat-run
-
- exec-war-only
-
- package
-
- standalone-tomcat
-
-
-
-
-
-
-
-
-
diff --git a/examples/showcase/src/main/java/org/springside/examples/showcase/Main.java b/examples/showcase/src/main/java/org/springside/examples/showcase/Main.java
deleted file mode 100644
index 3fdf2c43a..000000000
--- a/examples/showcase/src/main/java/org/springside/examples/showcase/Main.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package org.springside.examples.showcase;
-
-import java.io.File;
-import java.net.URL;
-import java.security.ProtectionDomain;
-
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.webapp.WebAppContext;
-
-/**
- * Main Class for standalone running.
- *
- * @author calvin
- */
-public class Main {
-
- public static void main(String[] args) throws Exception {
-
- String contextPath = "/showcase";
- int port = Integer.getInteger("port", 8080);
-
- Server server = createServer(contextPath, port);
-
- try {
- server.start();
- server.join();
- } catch (Exception e) {
- e.printStackTrace();
- System.exit(100);
- }
- }
-
- private static Server createServer(String contextPath, int port) {
- // use Eclipse JDT compiler
- System.setProperty("org.apache.jasper.compiler.disablejsr199", "true");
-
- Server server = new Server(port);
- server.setStopAtShutdown(true);
-
- ProtectionDomain protectionDomain = Main.class.getProtectionDomain();
- URL location = protectionDomain.getCodeSource().getLocation();
- String warFile = location.toExternalForm();
-
- WebAppContext context = new WebAppContext(warFile, contextPath);
- context.setServer(server);
-
- // 设置work dir,war包将解压到该目录,jsp编译后的文件也将放入其中。
- String currentDir = new File(location.getPath()).getParent();
- File workDir = new File(currentDir, "work");
- context.setTempDirectory(workDir);
-
- server.setHandler(context);
- return server;
- }
-
-}
diff --git a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/cache/ehcache/EhcacheDemo.java b/examples/showcase/src/main/java/org/springside/examples/showcase/demos/cache/ehcache/EhcacheDemo.java
deleted file mode 100644
index 59be088bc..000000000
--- a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/cache/ehcache/EhcacheDemo.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package org.springside.examples.showcase.demos.cache.ehcache;
-
-import static org.junit.Assert.*;
-import net.sf.ehcache.Cache;
-import net.sf.ehcache.CacheManager;
-import net.sf.ehcache.Element;
-
-import org.junit.Test;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.test.context.ContextConfiguration;
-import org.springside.modules.test.spring.SpringContextTestCase;
-
-/**
- * 演示Ehcache的配置.
- *
- * 配置见applicationContext-ehcache.xml与ehcache.xml
- *
- * @author calvin
- */
-@ContextConfiguration(locations = { "/cache/applicationContext-ehcache.xml" })
-public class EhcacheDemo extends SpringContextTestCase {
-
- private static final String CACHE_NAME = "demoCache";
-
- @Autowired
- private CacheManager ehcacheManager;
-
- private Cache cache;
-
- @Test
- public void demo() {
-
- cache = ehcacheManager.getCache(CACHE_NAME);
-
- String key = "foo";
- String value = "boo";
-
- put(key, value);
- Object result = get(key);
-
- assertEquals(value, result);
- }
-
- public Object get(String key) {
- Element element = cache.get(key);
- return element.getObjectValue();
- }
-
- public void put(String key, Object value) {
- Element element = new Element(key, value);
- cache.put(element);
- }
-}
diff --git a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/cache/guava/GuavaCacheDemo.java b/examples/showcase/src/main/java/org/springside/examples/showcase/demos/cache/guava/GuavaCacheDemo.java
deleted file mode 100644
index df641cf69..000000000
--- a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/cache/guava/GuavaCacheDemo.java
+++ /dev/null
@@ -1,70 +0,0 @@
-package org.springside.examples.showcase.demos.cache.guava;
-
-import static org.junit.Assert.*;
-
-import java.util.concurrent.TimeUnit;
-
-import org.junit.Test;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.test.context.ContextConfiguration;
-import org.springside.examples.showcase.entity.User;
-import org.springside.examples.showcase.service.AccountService;
-import org.springside.modules.test.data.DataFixtures;
-import org.springside.modules.test.log.LogbackListAppender;
-import org.springside.modules.test.spring.SpringTransactionalTestCase;
-import org.springside.modules.utils.Threads;
-
-import com.google.common.cache.CacheBuilder;
-import com.google.common.cache.CacheLoader;
-import com.google.common.cache.LoadingCache;
-
-/**
- * 本地缓存演示,使用GuavaCache.
- *
- * @author calvin
- */
-@ContextConfiguration(locations = { "/applicationContext.xml" })
-public class GuavaCacheDemo extends SpringTransactionalTestCase {
-
- @Autowired
- private AccountService accountService;
-
- @Test
- public void demo() throws Exception {
- // 设置缓存最大个数为100,缓存过期时间为5秒
- LoadingCache cache = CacheBuilder.newBuilder().maximumSize(100)
- .expireAfterAccess(5, TimeUnit.SECONDS).build(new CacheLoader() {
- @Override
- public User load(Long key) throws Exception {
- logger.info("fetch from database");
- return accountService.getUser(key);
- }
-
- });
-
- // 初始化数据
- DataFixtures.executeScript(dataSource, "classpath:data/h2/cleanup-data.sql",
- "classpath:data/h2/import-data.sql");
-
- // 插入appender用于assert。
- LogbackListAppender appender = new LogbackListAppender();
- appender.addToLogger(GuavaCacheDemo.class);
-
- // 第一次加载会查数据库
- User user = cache.get(1L);
- assertEquals("admin", user.getLoginName());
- assertFalse(appender.isEmpty());
- appender.clearLogs();
-
- // 第二次加载时直接从缓存里取
- User user2 = cache.get(1L);
- assertEquals("admin", user2.getLoginName());
- assertTrue(appender.isEmpty());
-
- // 第三次加载时,因为缓存已经过期所以会查数据库
- Threads.sleep(10, TimeUnit.SECONDS);
- User user3 = cache.get(1L);
- assertEquals("admin", user3.getLoginName());
- assertFalse(appender.isEmpty());
- }
-}
diff --git a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/cache/memcached/MemcachedDemo.java b/examples/showcase/src/main/java/org/springside/examples/showcase/demos/cache/memcached/MemcachedDemo.java
deleted file mode 100644
index 9e4483cc2..000000000
--- a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/cache/memcached/MemcachedDemo.java
+++ /dev/null
@@ -1,88 +0,0 @@
-package org.springside.examples.showcase.demos.cache.memcached;
-
-import static org.junit.Assert.*;
-
-import java.util.Map;
-
-import org.junit.Test;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.test.context.ContextConfiguration;
-import org.springside.modules.cache.memcached.SpyMemcachedClient;
-import org.springside.modules.test.spring.SpringContextTestCase;
-
-import com.google.common.collect.Lists;
-
-@ContextConfiguration(locations = { "/cache/applicationContext-memcached.xml", "/applicationContext.xml" })
-public class MemcachedDemo extends SpringContextTestCase {
-
- @Autowired
- private SpyMemcachedClient spyMemcachedClient;
-
- @Test
- public void normal() {
-
- String key = "consumer:1";
- String value = "admin";
-
- spyMemcachedClient.set(key, 60 * 60 * 1, value);
-
- String result = spyMemcachedClient.get(key);
- assertEquals(value, result);
-
- spyMemcachedClient.delete(key);
- result = spyMemcachedClient.get(key);
- assertNull(result);
- }
-
- @Test
- public void safeDelete() {
- String key = "consumer:1";
- spyMemcachedClient.set(key, 60, "admin");
- boolean result = spyMemcachedClient.safeDelete(key);
- assertTrue(result);
-
- result = spyMemcachedClient.safeDelete("consumer:1");
- assertFalse(result);
- }
-
- @Test
- public void getBulk() {
-
- String key1 = "consumer:1";
- String value1 = "admin";
-
- String key2 = "consumer:2";
- String value2 = "calvin";
-
- String key3 = "invalidKey";
-
- spyMemcachedClient.set(key1, 60 * 60 * 1, value1);
- spyMemcachedClient.set(key2, 60 * 60 * 1, value2);
-
- Map result = spyMemcachedClient.getBulk(Lists.newArrayList(key1, key2));
- assertEquals(value1, result.get(key1));
- assertEquals(value2, result.get(key2));
- assertNull(result.get(key3));
- }
-
- @Test
- public void incr() {
- String key = "incr_key";
-
- // 注意,incr返回的数值使用long表达
- long result = spyMemcachedClient.incr(key, 2, 1);
- assertEquals(1, result);
- // 注意,get返回的数值使用字符串表达
- assertEquals("1", spyMemcachedClient.get(key));
-
- result = spyMemcachedClient.incr(key, 2, 1);
- assertEquals(3, result);
- assertEquals("3", spyMemcachedClient.get(key));
-
- key = "set_and_incr_key";
- // 注意,set中的数值必须使用字符串,后面的incr操作结果才会正确.
- spyMemcachedClient.set(key, 60 * 60 * 1, "1");
- result = spyMemcachedClient.incr(key, 2, 1);
- assertEquals(3, result);
- }
-}
diff --git a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/cache/memcached/MemcachedObjectType.java b/examples/showcase/src/main/java/org/springside/examples/showcase/demos/cache/memcached/MemcachedObjectType.java
deleted file mode 100644
index 0bec2c293..000000000
--- a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/cache/memcached/MemcachedObjectType.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package org.springside.examples.showcase.demos.cache.memcached;
-
-/**
- * 统一定义Memcached中存储的各种对象的Key前缀和超时时间.
- *
- * @see org.springside.examples.showcase.service.AccountService#getInitializedUser(String)
- *
- * @author calvin
- */
-public enum MemcachedObjectType {
- USER("user:", 60 * 60 * 1);
-
- private String prefix;
- private int expiredTime;
-
- MemcachedObjectType(String prefix, int expiredTime) {
- this.prefix = prefix;
- this.expiredTime = expiredTime;
- }
-
- public String getPrefix() {
- return prefix;
- }
-
- public int getExpiredTime() {
- return expiredTime;
- }
-
-}
diff --git a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/hystrix/dependency/DependencyResourceController.java b/examples/showcase/src/main/java/org/springside/examples/showcase/demos/hystrix/dependency/DependencyResourceController.java
deleted file mode 100644
index 80f6fceff..000000000
--- a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/hystrix/dependency/DependencyResourceController.java
+++ /dev/null
@@ -1,66 +0,0 @@
-package org.springside.examples.showcase.demos.hystrix.dependency;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.HttpStatus;
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.ResponseBody;
-import org.springside.examples.showcase.entity.User;
-import org.springside.examples.showcase.service.AccountEffectiveService;
-import org.springside.examples.showcase.webservice.rest.RestException;
-import org.springside.examples.showcase.webservice.rest.UserDTO;
-import org.springside.modules.mapper.BeanMapper;
-import org.springside.modules.utils.Threads;
-
-/**
- * 模拟被Service所依赖的Resource.
- */
-@Controller
-public class DependencyResourceController {
- public static final int TIMEOUT = 30000;
-
- public static String status = "normal";
-
- @Autowired
- private AccountEffectiveService accountService;
-
- /**
- * 根据控制器中的状态而演示不同的行为,如正常返回,30秒后返回或直接报错
- */
- @RequestMapping(value = "/hystrix/resource/{id}", method = RequestMethod.GET)
- @ResponseBody
- public UserDTO getUser(@PathVariable("id") Long id) {
- // 正常返回.
- if ("normal".equals(status)) {
- return handleRequest(id);
- }
-
- // 演示超时,30秒后返回.
- if ("timeout".equals(status)) {
- Threads.sleep(TIMEOUT);
- return handleRequest(id);
- }
-
- // 演示服务端出错情况.
- if ("server-error".equals(status)) {
- throw new RestException(HttpStatus.INTERNAL_SERVER_ERROR, "Server Exception");
- }
-
- // 演示客户端请求出错。
- if ("bad-request".equals(status)) {
- throw new RestException(HttpStatus.BAD_REQUEST, "Client send a bad request");
- }
-
- return null;
- }
-
- private UserDTO handleRequest(Long id) {
- User user = accountService.getUser(id);
- UserDTO dto = BeanMapper.map(user, UserDTO.class);
- dto.setTeamId(user.getTeam().getId());
- return dto;
- }
-
-}
diff --git a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/hystrix/service/GetUserCommand.java b/examples/showcase/src/main/java/org/springside/examples/showcase/demos/hystrix/service/GetUserCommand.java
deleted file mode 100644
index 4fafbb982..000000000
--- a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/hystrix/service/GetUserCommand.java
+++ /dev/null
@@ -1,58 +0,0 @@
-package org.springside.examples.showcase.demos.hystrix.service;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.http.HttpStatus;
-import org.springframework.web.client.HttpStatusCodeException;
-import org.springframework.web.client.RestTemplate;
-import org.springside.examples.showcase.webservice.rest.UserDTO;
-
-import com.netflix.hystrix.HystrixCommand;
-import com.netflix.hystrix.exception.HystrixBadRequestException;
-
-/**
- * HystrixCommand的实现类, 将访问远程资源的逻辑封装在T run()函数内.
- * 如需对异常, 超时, 短路等进行自行处理,返回默认值则实现T getFallback()函数.
- *
- * @author calvin
- */
-public class GetUserCommand extends HystrixCommand {
-
- private static Logger logger = LoggerFactory.getLogger(GetUserCommand.class);
-
- private RestTemplate restTemplate;
- private Long id;
-
- /**
- * 构造函数,注入配置、用到的资源访问类和命令参数.
- */
- protected GetUserCommand(Setter commandConfig, RestTemplate restTemplate, Long id) {
- super(commandConfig);
- this.restTemplate = restTemplate;
- this.id = id;
- }
-
- /**
- * 访问依赖资源的函数的实现。
- */
- @Override
- protected UserDTO run() throws Exception {
- try {
- logger.info("Access restful resource");
- return restTemplate.getForObject("http://localhost:8080/showcase/hystrix/resource/{id}", UserDTO.class, id);
- } catch (HttpStatusCodeException e) {
- throw handleException(e);
- }
- }
-
- /**
- * 处理异常,对于客户端自己的异常,抛出HystrixBadRequestException,不算入短路统计内。
- */
- protected Exception handleException(HttpStatusCodeException e) {
- HttpStatus status = e.getStatusCode();
- if (status.equals(HttpStatus.BAD_REQUEST)) {
- throw new HystrixBadRequestException(e.getResponseBodyAsString(), e);
- }
- throw e;
- }
-}
diff --git a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/hystrix/service/UserService.java b/examples/showcase/src/main/java/org/springside/examples/showcase/demos/hystrix/service/UserService.java
deleted file mode 100644
index c3b43cb17..000000000
--- a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/hystrix/service/UserService.java
+++ /dev/null
@@ -1,130 +0,0 @@
-package org.springside.examples.showcase.demos.hystrix.service;
-
-import java.util.HashMap;
-
-import javax.annotation.PostConstruct;
-
-import org.springframework.http.client.SimpleClientHttpRequestFactory;
-import org.springframework.stereotype.Service;
-import org.springframework.web.client.RestTemplate;
-import org.springside.examples.showcase.webservice.rest.UserDTO;
-
-import com.netflix.hystrix.HystrixCircuitBreaker;
-import com.netflix.hystrix.HystrixCommand.Setter;
-import com.netflix.hystrix.HystrixCommandGroupKey;
-import com.netflix.hystrix.HystrixCommandKey;
-import com.netflix.hystrix.HystrixCommandMetrics;
-import com.netflix.hystrix.HystrixCommandMetrics.HealthCounts;
-import com.netflix.hystrix.HystrixCommandProperties;
-import com.netflix.hystrix.HystrixCommandProperties.ExecutionIsolationStrategy;
-import com.netflix.hystrix.HystrixThreadPoolProperties;
-import com.netflix.hystrix.util.HystrixRollingNumberEvent;
-
-/**
- * 使用Hystrix 封装的Service。原来直接调用restTemplate改为调用Hystrix Command的封装.
- *
- * @author calvin
- */
-@Service
-public class UserService {
-
- private boolean isolateThreadPool = true;
- private Setter commandConfig;
- private RestTemplate restTemplate;
-
- /**
- * 创建并调用command, 不处理Hystrix Error,直接透传到Web层.
- */
- public UserDTO getUser(Long id) throws Exception {
- GetUserCommand command = new GetUserCommand(commandConfig, restTemplate, id);
- return command.execute();
- }
-
- /**
- * 演示获取Hystrix的Metrics.
- */
- public MetricsMap getHystrixMetrics() {
- MetricsMap metricsMap = new MetricsMap();
- HystrixCommandKey key = HystrixCommandKey.Factory.asKey("GetUserCommand");
- HystrixCommandMetrics metrics = HystrixCommandMetrics.getInstance(key);
-
- if (metrics != null) {
- HealthCounts counts = metrics.getHealthCounts();
- HystrixCircuitBreaker circuitBreaker = HystrixCircuitBreaker.Factory.getInstance(key);
-
- metricsMap.put("circuitOpen", circuitBreaker.isOpen());
- metricsMap.put("totalRequest", counts.getTotalRequests());
- metricsMap.put("errorPercentage", counts.getErrorPercentage());
- metricsMap.put("success", metrics.getRollingCount(HystrixRollingNumberEvent.SUCCESS));
- metricsMap.put("timeout", metrics.getRollingCount(HystrixRollingNumberEvent.TIMEOUT));
- metricsMap.put("failure", metrics.getRollingCount(HystrixRollingNumberEvent.FAILURE));
- metricsMap.put("shortCircuited", metrics.getRollingCount(HystrixRollingNumberEvent.SHORT_CIRCUITED));
- metricsMap.put("threadPoolRejected",
- metrics.getRollingCount(HystrixRollingNumberEvent.THREAD_POOL_REJECTED));
- metricsMap.put("semaphoreRejected", metrics.getRollingCount(HystrixRollingNumberEvent.SEMAPHORE_REJECTED));
- metricsMap.put("latency50", metrics.getTotalTimePercentile(50));
- metricsMap.put("latency90", metrics.getTotalTimePercentile(90));
- metricsMap.put("latency100", metrics.getTotalTimePercentile(100));
- }
-
- return metricsMap;
- }
-
- /**
- * 演示Hystrix Command的各种配置项, 并构造Thread-Safed的RestTemplate.
- */
- @PostConstruct
- public void init() {
- // 初始化RestTemplate
- restTemplate = new RestTemplate();
-
- // 设置Command名称 //
- commandConfig = Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("ExampleGroup")).andCommandKey(
- HystrixCommandKey.Factory.asKey("GetUserCommand"));
-
- HystrixCommandProperties.Setter commandProperties = HystrixCommandProperties.Setter();
- commandConfig.andCommandPropertiesDefaults(commandProperties);
-
- // 设置短路规则 //
- // 设置短路后的保护时间 ,默认为5秒,改为20秒方便演示
- commandProperties.withCircuitBreakerSleepWindowInMilliseconds(20000)
- // 多少百分比的失败在rolling windows内发生,计算为短路。默认为50%,无改变.
- .withCircuitBreakerErrorThresholdPercentage(50)
- // 至少多少请求在rolling window内发生,才开始触发短路的计算,默认为20, 设为3方便演示.
- .withCircuitBreakerRequestVolumeThreshold(3)
- // rolling windows 长度,默认为20秒,改为120秒方便演示。同时相应改变桶的数量.
- .withMetricsRollingStatisticalWindowInMilliseconds(120000)
- .withMetricsRollingStatisticalWindowBuckets(120);
-
- // 设置超时与并发控制 //
- if (isolateThreadPool) { // 使用隔离的Hystrix线程池
- // 线程超时,默认为1秒,设为3秒方便演示.
- commandProperties.withExecutionIsolationThreadTimeoutInMilliseconds(3000);
- // 线程池属性, 线程池大小,默认为10,无改变。待执行队列的大小,默认为5,无改变.
- commandConfig.andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter().withCoreSize(10)
- .withQueueSizeRejectionThreshold(5));
- } else { // 使用原有的调用者线程
- // 依靠RestTemplate本身的超时机制,设为10秒。
- ((SimpleClientHttpRequestFactory) restTemplate.getRequestFactory()).setReadTimeout(10000);
-
- // 设置使用原有的调用者线程,设置并发,默认为10,无改变.
- commandProperties.withExecutionIsolationStrategy(ExecutionIsolationStrategy.SEMAPHORE)
- .withExecutionIsolationSemaphoreMaxConcurrentRequests(10);
- }
- }
-
- public void setIsolateThreadPool(boolean isolateThreadPool) {
- this.isolateThreadPool = isolateThreadPool;
- }
-
- /**
- * 简易Map,对不存在的统计项返回0.
- */
- public static class MetricsMap extends HashMap {
- @Override
- public Object get(Object key) {
- Object result = super.get(key);
- return result != null ? result : "0";
- }
- }
-}
diff --git a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/hystrix/web/HystrixDemoController.java b/examples/showcase/src/main/java/org/springside/examples/showcase/demos/hystrix/web/HystrixDemoController.java
deleted file mode 100644
index afddb8cdd..000000000
--- a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/hystrix/web/HystrixDemoController.java
+++ /dev/null
@@ -1,88 +0,0 @@
-package org.springside.examples.showcase.demos.hystrix.web;
-
-import java.util.Map;
-
-import javax.annotation.PostConstruct;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Controller;
-import org.springframework.ui.Model;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.ResponseBody;
-import org.springside.examples.showcase.demos.hystrix.dependency.DependencyResourceController;
-import org.springside.examples.showcase.demos.hystrix.service.UserService;
-import org.springside.examples.showcase.webservice.rest.UserDTO;
-import org.springside.modules.web.MediaTypes;
-
-import com.google.common.collect.Maps;
-
-@Controller
-public class HystrixDemoController {
- private Map allStatus = Maps.newLinkedHashMap();
-
- @Autowired
- private UserService userService;
-
- @RequestMapping(value = "/hystrix", method = RequestMethod.GET)
- public String index(Model model) {
- model.addAttribute("allStatus", allStatus);
- model.addAttribute("statusHolder", new StatusHolder(DependencyResourceController.status));
- model.addAttribute("metrics", userService.getHystrixMetrics());
- return "hystrix/hystrix";
- }
-
- /**
- * 调用Hystrix保护的UserService从远端资源获取用户信息, 异常由HystrixExceptionHandler统一处理.
- */
- @RequestMapping(value = "/hystrix/user/{id}", method = RequestMethod.GET, produces = MediaTypes.JSON_UTF_8)
- @ResponseBody
- public UserDTO getUser(@PathVariable("id") Long id) throws Exception {
- return userService.getUser(id);
- }
-
- /**
- * 设定资源的状态.
- */
- @RequestMapping(value = "/hystrix/status")
- public String updateStatus(@RequestParam("value") String newStatus) {
- DependencyResourceController.status = newStatus;
- return "redirect:/hystrix";
- }
-
- /**
- * 从默认的Hystrix线程池模式切换为使用原调用者线程的模式.
- */
- @RequestMapping(value = "/hystrix/disableIsolateThreadPool")
- public String disableIsolateThreadPool() {
- userService.setIsolateThreadPool(false);
- userService.init();
- return "redirect:/hystrix";
-
- }
-
- @PostConstruct
- public void init() {
- allStatus.put("normal", "正常");
- allStatus.put("timeout", "超时");
- allStatus.put("server-error", "服务器错误");
- allStatus.put("bad-request", "请求错误");
- }
-
- /**
- * 给Spring Form Tag使用的类.
- */
- public static class StatusHolder {
- private String value;
-
- public StatusHolder(String value) {
- this.value = value;
- }
-
- public String getValue() {
- return value;
- }
- }
-}
diff --git a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/hystrix/web/HystrixExceptionHandler.java b/examples/showcase/src/main/java/org/springside/examples/showcase/demos/hystrix/web/HystrixExceptionHandler.java
deleted file mode 100644
index 26c8c2fd5..000000000
--- a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/hystrix/web/HystrixExceptionHandler.java
+++ /dev/null
@@ -1,61 +0,0 @@
-package org.springside.examples.showcase.demos.hystrix.web;
-
-import org.springframework.http.HttpHeaders;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.MediaType;
-import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.ControllerAdvice;
-import org.springframework.web.bind.annotation.ExceptionHandler;
-import org.springframework.web.context.request.WebRequest;
-import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
-import org.springside.modules.utils.Exceptions;
-import org.springside.modules.web.MediaTypes;
-
-import com.netflix.hystrix.exception.HystrixBadRequestException;
-import com.netflix.hystrix.exception.HystrixRuntimeException;
-import com.netflix.hystrix.exception.HystrixRuntimeException.FailureType;
-
-/**
- * 自定义ExceptionHandler,专门处理Hystrix异常.
- *
- * @author calvin
- */
-@ControllerAdvice
-public class HystrixExceptionHandler extends ResponseEntityExceptionHandler {
-
- /**
- * 处理Hystrix Runtime异常, 异常分为两类,一类是Command内部抛出异常,一类是Hystrix自身的保护机制
- */
- @ExceptionHandler(value = { HystrixRuntimeException.class })
- public final ResponseEntity> handleException(HystrixRuntimeException e, WebRequest request) {
- HttpStatus status = HttpStatus.SERVICE_UNAVAILABLE;
- String message = e.getMessage();
-
- FailureType type = e.getFailureType();
-
- // 对命令抛出的异常进行特殊处理
- if (type.equals(FailureType.COMMAND_EXCEPTION)) {
- status = HttpStatus.INTERNAL_SERVER_ERROR;
- message = Exceptions.getErrorMessageWithNestedException(e);
- }
-
- logger.error(message, e);
-
- HttpHeaders headers = new HttpHeaders();
- headers.setContentType(MediaType.parseMediaType(MediaTypes.TEXT_PLAIN_UTF_8));
- return handleExceptionInternal(e, message, headers, status, request);
- }
-
- /**
- * 处理Hystrix ClientException异常.
- */
- @ExceptionHandler(value = { HystrixBadRequestException.class })
- public final ResponseEntity> handleException(HystrixBadRequestException e, WebRequest request) {
- String message = Exceptions.getErrorMessageWithNestedException(e);
- logger.error(message, e);
-
- HttpHeaders headers = new HttpHeaders();
- headers.setContentType(MediaType.parseMediaType(MediaTypes.TEXT_PLAIN_UTF_8));
- return handleExceptionInternal(e, message, headers, HttpStatus.BAD_REQUEST, request);
- }
-}
diff --git a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/jms/advanced/AdvancedNotifyMessageListener.java b/examples/showcase/src/main/java/org/springside/examples/showcase/demos/jms/advanced/AdvancedNotifyMessageListener.java
deleted file mode 100644
index e20bd16e7..000000000
--- a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/jms/advanced/AdvancedNotifyMessageListener.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package org.springside.examples.showcase.demos.jms.advanced;
-
-import javax.jms.MapMessage;
-import javax.jms.Message;
-import javax.jms.MessageListener;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * 消息的异步被动接收者.
- *
- * 使用Spring的MessageListenerContainer侦听消息并调用本Listener进行处理.
- *
- * @author calvin
- */
-public class AdvancedNotifyMessageListener implements MessageListener {
-
- private static Logger logger = LoggerFactory.getLogger(AdvancedNotifyMessageListener.class);
-
- /**
- * MessageListener回调函数.
- */
- @Override
- public void onMessage(Message message) {
- try {
- MapMessage mapMessage = (MapMessage) message;
-
- // 打印消息详情
- logger.info("UserName:{}, Email:{}, ObjectType:{}", mapMessage.getString("userName"),
- mapMessage.getString("email"), mapMessage.getStringProperty("objectType"));
- } catch (Exception e) {
- logger.error("处理消息时发生异常.", e);
- }
- }
-}
diff --git a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/jms/advanced/AdvancedNotifyMessageProducer.java b/examples/showcase/src/main/java/org/springside/examples/showcase/demos/jms/advanced/AdvancedNotifyMessageProducer.java
deleted file mode 100644
index 8ee0a46cc..000000000
--- a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/jms/advanced/AdvancedNotifyMessageProducer.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package org.springside.examples.showcase.demos.jms.advanced;
-
-import javax.jms.Destination;
-import javax.jms.JMSException;
-import javax.jms.MapMessage;
-import javax.jms.Message;
-import javax.jms.Session;
-
-import org.springframework.jms.core.JmsTemplate;
-import org.springframework.jms.core.MessageCreator;
-import org.springside.examples.showcase.entity.User;
-
-/**
- * JMS用户变更消息生产者.
- *
- * 使用jmsTemplate将用户变更消息分别发送到queue与topic.
- *
- * @author calvin
- */
-public class AdvancedNotifyMessageProducer {
-
- private JmsTemplate jmsTemplate;
- private Destination notifyQueue;
- private Destination notifyTopic;
-
- public void sendQueue(final User user) {
- sendMessage(user, notifyQueue);
- }
-
- public void sendTopic(final User user) {
- sendMessage(user, notifyTopic);
- }
-
- /**
- * 使用jmsTemplate的send/MessageCreator()发送Map类型的消息并在Message中附加属性用于消息过滤.
- */
- private void sendMessage(final User user, Destination destination) {
- jmsTemplate.send(destination, new MessageCreator() {
- @Override
- public Message createMessage(Session session) throws JMSException {
-
- MapMessage message = session.createMapMessage();
- message.setString("userName", user.getName());
- message.setString("email", user.getEmail());
-
- message.setStringProperty("objectType", "user");
-
- return message;
- }
- });
- }
-
- public void setJmsTemplate(JmsTemplate jmsTemplate) {
- this.jmsTemplate = jmsTemplate;
- }
-
- public void setNotifyQueue(Destination notifyQueue) {
- this.notifyQueue = notifyQueue;
- }
-
- public void setNotifyTopic(Destination nodifyTopic) {
- this.notifyTopic = nodifyTopic;
- }
-}
diff --git a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/jms/simple/NotifyMessageListener.java b/examples/showcase/src/main/java/org/springside/examples/showcase/demos/jms/simple/NotifyMessageListener.java
deleted file mode 100644
index 0b2f1c11c..000000000
--- a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/jms/simple/NotifyMessageListener.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package org.springside.examples.showcase.demos.jms.simple;
-
-import javax.jms.MapMessage;
-import javax.jms.Message;
-import javax.jms.MessageListener;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springside.examples.showcase.demos.utilities.email.SimpleMailService;
-
-/**
- * 消息的异步被动接收者.
- *
- * 使用Spring的MessageListenerContainer侦听消息并调用本Listener进行处理.
- *
- * @author calvin
- */
-public class NotifyMessageListener implements MessageListener {
-
- private static Logger logger = LoggerFactory.getLogger(NotifyMessageListener.class);
-
- @Autowired(required = false)
- private SimpleMailService simpleMailService;
-
- /**
- * MessageListener回调函数.
- */
- @Override
- public void onMessage(Message message) {
- try {
- MapMessage mapMessage = (MapMessage) message;
- // 打印消息详情
- logger.info("UserName:{}, Email:{}", mapMessage.getString("userName"), mapMessage.getString("email"));
-
- // 发送邮件
- if (simpleMailService != null) {
- simpleMailService.sendNotificationMail(mapMessage.getString("userName"));
- }
- } catch (Exception e) {
- logger.error("处理消息时发生异常.", e);
- }
- }
-}
diff --git a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/jms/simple/NotifyMessageProducer.java b/examples/showcase/src/main/java/org/springside/examples/showcase/demos/jms/simple/NotifyMessageProducer.java
deleted file mode 100644
index ac6172d0c..000000000
--- a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/jms/simple/NotifyMessageProducer.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package org.springside.examples.showcase.demos.jms.simple;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.jms.Destination;
-
-import org.springframework.jms.core.JmsTemplate;
-import org.springside.examples.showcase.entity.User;
-
-/**
- * JMS用户变更消息生产者.
- *
- * 使用jmsTemplate将用户变更消息分别发送到queue与topic.
- *
- * @author calvin
- */
-
-public class NotifyMessageProducer {
-
- private JmsTemplate jmsTemplate;
- private Destination notifyQueue;
- private Destination notifyTopic;
-
- public void sendQueue(final User user) {
- sendMessage(user, notifyQueue);
- }
-
- public void sendTopic(final User user) {
- sendMessage(user, notifyTopic);
- }
-
- /**
- * 使用jmsTemplate最简便的封装convertAndSend()发送Map类型的消息.
- */
- private void sendMessage(User user, Destination destination) {
- Map map = new HashMap();
- map.put("userName", user.getName());
- map.put("email", user.getEmail());
-
- jmsTemplate.convertAndSend(destination, map);
- }
-
- public void setJmsTemplate(JmsTemplate jmsTemplate) {
- this.jmsTemplate = jmsTemplate;
- }
-
- public void setNotifyQueue(Destination notifyQueue) {
- this.notifyQueue = notifyQueue;
- }
-
- public void setNotifyTopic(Destination nodifyTopic) {
- this.notifyTopic = nodifyTopic;
- }
-}
diff --git a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/jmx/ApplicationStatistics.java b/examples/showcase/src/main/java/org/springside/examples/showcase/demos/jmx/ApplicationStatistics.java
deleted file mode 100644
index 8aa76337b..000000000
--- a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/jmx/ApplicationStatistics.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package org.springside.examples.showcase.demos.jmx;
-
-import java.util.concurrent.atomic.AtomicInteger;
-
-import org.springframework.jmx.export.annotation.ManagedAttribute;
-import org.springframework.jmx.export.annotation.ManagedOperation;
-import org.springframework.jmx.export.annotation.ManagedResource;
-
-/**
- * 应用的运行情况统计bean, 通过JMX可被外部监控系统获取数据.
- *
- * @author calvin
- */
-@ManagedResource(objectName = ApplicationStatistics.MBEAN_NAME, description = "Application Statistics Management Bean")
-public class ApplicationStatistics {
-
- public static final String MBEAN_NAME = "showcase:name=ApplicationStatistics";
-
- private final AtomicInteger listUserTimes = new AtomicInteger();
- private final AtomicInteger updateUserTimes = new AtomicInteger();
-
- public void incrListUserTimes() {
- listUserTimes.incrementAndGet();
- }
-
- public void incrUpdateUserTimes() {
- updateUserTimes.incrementAndGet();
- }
-
- @ManagedAttribute(description = "Times of users be listed")
- public int getListUserTimes() {
- return listUserTimes.get();
- }
-
- @ManagedAttribute(description = "Times of users be updated")
- public int getUpdateUserTimes() {
- return updateUserTimes.get();
- }
-
- @ManagedOperation(description = "Reset all statistics")
- public void resetStatistics() {
- listUserTimes.set(0);
- updateUserTimes.set(0);
- }
-}
diff --git a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/metrics/MetricsManager.java b/examples/showcase/src/main/java/org/springside/examples/showcase/demos/metrics/MetricsManager.java
deleted file mode 100644
index 16d0b4188..000000000
--- a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/metrics/MetricsManager.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package org.springside.examples.showcase.demos.metrics;
-
-import java.net.InetSocketAddress;
-import java.util.concurrent.TimeUnit;
-
-import javax.annotation.PostConstruct;
-import javax.annotation.PreDestroy;
-
-import org.springside.modules.metrics.MetricRegistry;
-import org.springside.modules.metrics.report.ConsoleReporter;
-import org.springside.modules.metrics.report.GraphiteReporter;
-import org.springside.modules.metrics.report.ReportScheduler;
-
-public class MetricsManager {
-
- private ReportScheduler scheduler;
-
- @PostConstruct
- public void start() {
- GraphiteReporter graphiteReporter = new GraphiteReporter(new InetSocketAddress("localhost", 2003));
- ConsoleReporter consoleReporter = new ConsoleReporter();
- scheduler = new ReportScheduler(MetricRegistry.INSTANCE, consoleReporter, graphiteReporter);
- scheduler.start(10, TimeUnit.SECONDS);
- }
-
- @PreDestroy
- public void stop() {
- scheduler.stop();
- }
-}
diff --git a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/redis/JedisPoolFactory.java b/examples/showcase/src/main/java/org/springside/examples/showcase/demos/redis/JedisPoolFactory.java
deleted file mode 100644
index e5f935d74..000000000
--- a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/redis/JedisPoolFactory.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package org.springside.examples.showcase.demos.redis;
-
-import org.springside.modules.nosql.redis.JedisUtils;
-
-import redis.clients.jedis.JedisPool;
-import redis.clients.jedis.JedisPoolConfig;
-
-public class JedisPoolFactory {
-
- public static JedisPool createJedisPool(String defaultHost, int defaultPort, int defaultTimeout, int threadCount) {
- // 合并命令行传入的系统变量与默认值
- String host = System.getProperty("benchmark.host", defaultHost);
- String port = System.getProperty("benchmark.port", String.valueOf(defaultPort));
- String timeout = System.getProperty("benchmark.timeout", String.valueOf(defaultTimeout));
-
- // 设置Pool大小,设为与线程数等大,并屏蔽掉idle checking
- JedisPoolConfig poolConfig = JedisUtils.createPoolConfig(threadCount, threadCount);
-
- // create jedis pool
- return new JedisPool(poolConfig, host, Integer.valueOf(port), Integer.valueOf(timeout));
- }
-}
diff --git a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/redis/RedisCounterBenchmark.java b/examples/showcase/src/main/java/org/springside/examples/showcase/demos/redis/RedisCounterBenchmark.java
deleted file mode 100644
index be124dbec..000000000
--- a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/redis/RedisCounterBenchmark.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package org.springside.examples.showcase.demos.redis;
-
-import org.springside.modules.nosql.redis.JedisTemplate;
-import org.springside.modules.nosql.redis.JedisUtils;
-import org.springside.modules.test.benchmark.BenchmarkTask;
-import org.springside.modules.test.benchmark.ConcurrentBenchmark;
-
-import redis.clients.jedis.JedisPool;
-
-/**
- * 测试Redis用于计数器时incr()方法的性能.
- *
- * 可用-Dbenchmark.thread.count, -Dbenchmark.loop.count 重置测试规模
- * 可用-Dbenchmark.host,-Dbenchmark.port,-Dbenchmark.timeout 重置连接参数
- *
- * @author calvin
- */
-public class RedisCounterBenchmark extends ConcurrentBenchmark {
- private static final int DEFAULT_THREAD_COUNT = 50;
- private static final long DEFAULT_LOOP_COUNT = 20000;
-
- private String counterKey = "ss.counter";
- private JedisPool pool;
- private JedisTemplate jedisTemplate;
-
- public static void main(String[] args) throws Exception {
- RedisCounterBenchmark benchmark = new RedisCounterBenchmark();
- benchmark.execute();
- }
-
- public RedisCounterBenchmark() {
- super(DEFAULT_THREAD_COUNT, DEFAULT_LOOP_COUNT);
- }
-
- @Override
- protected void setUp() {
- pool = JedisPoolFactory.createJedisPool(JedisUtils.DEFAULT_HOST, JedisUtils.DEFAULT_PORT,
- JedisUtils.DEFAULT_TIMEOUT, threadCount);
- jedisTemplate = new JedisTemplate(pool);
-
- // 重置Counter
- jedisTemplate.set(counterKey, "0");
- }
-
- @Override
- protected void tearDown() {
- pool.destroy();
- }
-
- @Override
- protected BenchmarkTask createTask() {
- return new CounterTask();
- }
-
- public class CounterTask extends BenchmarkTask {
-
- @Override
- protected void execute(int requestSequence) {
- jedisTemplate.incr(counterKey);
- }
- }
-}
diff --git a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/redis/RedisSessionBenchmark.java b/examples/showcase/src/main/java/org/springside/examples/showcase/demos/redis/RedisSessionBenchmark.java
deleted file mode 100644
index e6e796d6e..000000000
--- a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/redis/RedisSessionBenchmark.java
+++ /dev/null
@@ -1,90 +0,0 @@
-package org.springside.examples.showcase.demos.redis;
-
-import java.security.SecureRandom;
-
-import org.springside.modules.mapper.JsonMapper;
-import org.springside.modules.nosql.redis.JedisTemplate;
-import org.springside.modules.nosql.redis.JedisTemplate.JedisActionNoResult;
-import org.springside.modules.nosql.redis.JedisUtils;
-import org.springside.modules.test.benchmark.BenchmarkTask;
-import org.springside.modules.test.benchmark.ConcurrentBenchmark;
-
-import redis.clients.jedis.Jedis;
-import redis.clients.jedis.JedisPool;
-
-/**
- * 测试Redis用于Session管理的setEx()与get()方法性能, 使用JSON格式存储数据.
- *
- * 可用系统参数重置相关变量,@see RedisCounterBenchmark
- *
- * @author calvin
- */
-public class RedisSessionBenchmark extends ConcurrentBenchmark {
- private static final int DEFAULT_THREAD_COUNT = 50;
- private static final long DEFAULT_LOOP_COUNT = 20000;
-
- private String keyPrefix = "ss.session:";
- private JsonMapper jsonMapper = new JsonMapper();
- private JedisPool pool;
- private JedisTemplate jedisTemplate;
-
- public static void main(String[] args) throws Exception {
- RedisSessionBenchmark benchmark = new RedisSessionBenchmark();
- benchmark.execute();
- }
-
- public RedisSessionBenchmark() {
- super(DEFAULT_THREAD_COUNT, DEFAULT_LOOP_COUNT);
- }
-
- @Override
- protected void setUp() {
- pool = JedisPoolFactory.createJedisPool(JedisUtils.DEFAULT_HOST, JedisUtils.DEFAULT_PORT,
- JedisUtils.DEFAULT_TIMEOUT, threadCount);
- jedisTemplate = new JedisTemplate(pool);
-
- // 清空数据库
- jedisTemplate.flushDB();
- }
-
- @Override
- protected void tearDown() {
- pool.destroy();
- }
-
- @Override
- protected BenchmarkTask createTask() {
- return new SessionTask();
- }
-
- public class SessionTask extends BenchmarkTask {
- private SecureRandom random = new SecureRandom();
-
- @Override
- protected void execute(final int requestSequnce) {
-
- int randomIndex = random.nextInt((int) loopCount);
- final String key = new StringBuilder().append(keyPrefix).append(taskSequence).append(":")
- .append(randomIndex).toString();
-
- jedisTemplate.execute(new JedisActionNoResult() {
- @Override
- public void action(Jedis jedis) {
- Session session = new Session(key);
- session.setAttrbute("name", key);
- session.setAttrbute("seq", requestSequnce);
- session.setAttrbute("address", "address:" + requestSequnce);
- session.setAttrbute("tel", "tel:" + requestSequnce);
-
- // 设置session,超时时间为300秒
- jedis.setex(session.getId(), 300, jsonMapper.toJson(session));
-
- // 再重新从Redis中取出并反序列化
- String sessionBackString = jedis.get(key);
- Session sessionBack = jsonMapper.fromJson(sessionBackString, Session.class);
- }
- });
- }
-
- }
-}
diff --git a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/redis/Session.java b/examples/showcase/src/main/java/org/springside/examples/showcase/demos/redis/Session.java
deleted file mode 100644
index bfa27bb9c..000000000
--- a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/redis/Session.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package org.springside.examples.showcase.demos.redis;
-
-import java.util.Map;
-
-import com.google.common.collect.Maps;
-
-public class Session {
-
- private String id;
-
- private Map attributes = Maps.newHashMap();
-
- public Session() {
- }
-
- public Session(String id) {
- this.id = id;
- }
-
- public String getId() {
- return id;
- }
-
- public void setId(String id) {
- this.id = id;
- }
-
- public Map getAttributes() {
- return attributes;
- }
-
- public void setAttributes(Map attributes) {
- this.attributes = attributes;
- }
-
- public Session setAttrbute(String key, Object value) {
- attributes.put(key, value);
- return this;
- }
-
- public Session removeAttrbute(String key) {
- attributes.remove(key);
- return this;
- }
-}
diff --git a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/redis/elector/MasterElectorDemo.java b/examples/showcase/src/main/java/org/springside/examples/showcase/demos/redis/elector/MasterElectorDemo.java
deleted file mode 100644
index 9dc2ecf42..000000000
--- a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/redis/elector/MasterElectorDemo.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package org.springside.examples.showcase.demos.redis.elector;
-
-import org.springside.examples.showcase.demos.redis.JedisPoolFactory;
-import org.springside.modules.nosql.redis.JedisUtils;
-import org.springside.modules.nosql.redis.elector.MasterElector;
-
-import redis.clients.jedis.JedisPool;
-
-public class MasterElectorDemo {
-
- public static void main(String[] args) throws Exception {
-
- JedisPool pool = JedisPoolFactory.createJedisPool(JedisUtils.DEFAULT_HOST, JedisUtils.DEFAULT_PORT,
- JedisUtils.DEFAULT_TIMEOUT, 1);
- try {
- MasterElector masterElector = new MasterElector(pool, 5);
-
- masterElector.start();
-
- System.out.println("Hit enter to stop.");
- while (true) {
- char c = (char) System.in.read();
- if (c == '\n') {
- System.out.println("Shuting down");
- masterElector.stop();
- return;
- }
- }
- } finally {
- pool.destroy();
- }
- }
-
-}
diff --git a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/redis/job/consumer/AdvancedJobConsumerBatchPopDemo.java b/examples/showcase/src/main/java/org/springside/examples/showcase/demos/redis/job/consumer/AdvancedJobConsumerBatchPopDemo.java
deleted file mode 100644
index 3b40f5c42..000000000
--- a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/redis/job/consumer/AdvancedJobConsumerBatchPopDemo.java
+++ /dev/null
@@ -1,102 +0,0 @@
-package org.springside.examples.showcase.demos.redis.job.consumer;
-
-import java.util.List;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.TimeUnit;
-
-import org.springside.examples.showcase.demos.redis.JedisPoolFactory;
-import org.springside.modules.nosql.redis.JedisUtils;
-import org.springside.modules.nosql.redis.scheduler.AdvancedConsumer;
-import org.springside.modules.nosql.redis.scheduler.SimpleJobConsumer;
-import org.springside.modules.test.benchmark.ConcurrentBenchmark;
-import org.springside.modules.utils.Threads;
-
-/**
- * 多线程运行BatchJobConsumer,从"ss.job:ready" list中popup job进行处理。
- *
- * 可用系统参数benchmark.thread.count 改变线程数,用reliable改变是否高可靠,用batchsize改变批处理数量.
- *
- * @author calvin
- */
-public class AdvancedJobConsumerBatchPopDemo extends SimpleJobConsumerDemo {
-
- private AdvancedConsumer consumer;
-
- private static boolean reliable;
- private static int batchSize;
-
- public static void main(String[] args) throws Exception {
-
- threadCount = Integer.parseInt(System.getProperty(ConcurrentBenchmark.THREAD_COUNT_NAME,
- String.valueOf(THREAD_COUNT)));
-
- reliable = Boolean.parseBoolean(System.getProperty("reliable",
- String.valueOf(AdvancedConsumer.DEFAULT_RELIABLE)));
- batchSize = Integer.parseInt(System.getProperty("batchsize",
- String.valueOf(AdvancedConsumer.DEFAULT_BATCH_SIZE)));
-
- pool = JedisPoolFactory.createJedisPool(JedisUtils.DEFAULT_HOST, JedisUtils.DEFAULT_PORT,
- JedisUtils.DEFAULT_TIMEOUT, threadCount);
-
- ExecutorService threadPool = Executors.newFixedThreadPool(threadCount);
- for (int i = 0; i < threadCount; i++) {
- SimpleJobConsumerDemo demo = new SimpleJobConsumerDemo();
- threadPool.execute(demo);
- }
-
- System.out.println("Hit enter to stop");
- try {
- while (true) {
- char c = (char) System.in.read();
- if (c == '\n') {
- System.out.println("Shutting down");
- threadPool.shutdownNow();
- boolean shutdownSucess = threadPool.awaitTermination(
- SimpleJobConsumer.DEFAULT_POPUP_TIMEOUT_SECONDS + 1, TimeUnit.SECONDS);
-
- if (!shutdownSucess) {
- System.out.println("Forcing exiting.");
- System.exit(-1);
- }
-
- return;
- }
- }
- } finally {
- pool.destroy();
- }
- }
-
- public AdvancedJobConsumerBatchPopDemo() {
- consumer = new AdvancedConsumer("ss", pool);
- consumer.setReliable(reliable);
- consumer.setBatchSize(batchSize);
- }
-
- @Override
- public void run() {
- while (!Thread.currentThread().isInterrupted()) {
- try {
- List jobs = consumer.popupJobs();
- if ((jobs != null) && !jobs.isEmpty()) {
- for (String job : jobs) {
- handleJob(job);
- }
- } else {
- Threads.sleep(100);
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
-
- @Override
- public void handleJob(String job) {
- super.handleJob(job);
- if (reliable) {
- consumer.ackJob(job);
- }
- }
-}
diff --git a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/redis/job/consumer/AdvancedJobConsumerSinglePopDemo.java b/examples/showcase/src/main/java/org/springside/examples/showcase/demos/redis/job/consumer/AdvancedJobConsumerSinglePopDemo.java
deleted file mode 100644
index 5b3533e20..000000000
--- a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/redis/job/consumer/AdvancedJobConsumerSinglePopDemo.java
+++ /dev/null
@@ -1,88 +0,0 @@
-package org.springside.examples.showcase.demos.redis.job.consumer;
-
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.TimeUnit;
-
-import org.springside.examples.showcase.demos.redis.JedisPoolFactory;
-import org.springside.modules.nosql.redis.JedisUtils;
-import org.springside.modules.nosql.redis.scheduler.AdvancedConsumer;
-import org.springside.modules.nosql.redis.scheduler.SimpleJobConsumer;
-import org.springside.modules.test.benchmark.ConcurrentBenchmark;
-import org.springside.modules.utils.Threads;
-
-/**
- * 多线程运行ReliableJobConsumer,从"ss.job:ready" list中popup job进行处理。
- *
- * 可用系统参数benchmark.thread.count 改变线程数.
- *
- * @author calvin
- */
-public class AdvancedJobConsumerSinglePopDemo extends SimpleJobConsumerDemo {
-
- private AdvancedConsumer consumer;
-
- public static void main(String[] args) throws Exception {
-
- threadCount = Integer.parseInt(System.getProperty(ConcurrentBenchmark.THREAD_COUNT_NAME,
- String.valueOf(THREAD_COUNT)));
-
- pool = JedisPoolFactory.createJedisPool(JedisUtils.DEFAULT_HOST, JedisUtils.DEFAULT_PORT,
- JedisUtils.DEFAULT_TIMEOUT, threadCount);
-
- ExecutorService threadPool = Executors.newFixedThreadPool(threadCount);
- for (int i = 0; i < threadCount; i++) {
- SimpleJobConsumerDemo demo = new SimpleJobConsumerDemo();
- threadPool.execute(demo);
- }
-
- System.out.println("Hit enter to stop");
- try {
- while (true) {
- char c = (char) System.in.read();
- if (c == '\n') {
- System.out.println("Shutting down");
- threadPool.shutdownNow();
- boolean shutdownSucess = threadPool.awaitTermination(
- SimpleJobConsumer.DEFAULT_POPUP_TIMEOUT_SECONDS + 1, TimeUnit.SECONDS);
-
- if (!shutdownSucess) {
- System.out.println("Forcing exiting.");
- System.exit(-1);
- }
-
- return;
- }
- }
- } finally {
- pool.destroy();
- }
- }
-
- public AdvancedJobConsumerSinglePopDemo() {
- consumer = new AdvancedConsumer("ss", pool);
- consumer.setReliable(true);
- }
-
- @Override
- public void run() {
- while (!Thread.currentThread().isInterrupted()) {
- try {
- String job = consumer.popupJob();
- if (job != null) {
- handleJob(job);
- } else {
- Threads.sleep(100);
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
-
- @Override
- public void handleJob(String job) {
- super.handleJob(job);
- consumer.ackJob(job);
- }
-}
diff --git a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/redis/job/consumer/SimpleJobConsumerDemo.java b/examples/showcase/src/main/java/org/springside/examples/showcase/demos/redis/job/consumer/SimpleJobConsumerDemo.java
deleted file mode 100644
index 4568cd1ad..000000000
--- a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/redis/job/consumer/SimpleJobConsumerDemo.java
+++ /dev/null
@@ -1,119 +0,0 @@
-package org.springside.examples.showcase.demos.redis.job.consumer;
-
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicLong;
-
-import org.springside.examples.showcase.demos.redis.JedisPoolFactory;
-import org.springside.modules.nosql.redis.JedisUtils;
-import org.springside.modules.nosql.redis.scheduler.SimpleJobConsumer;
-import org.springside.modules.test.benchmark.ConcurrentBenchmark;
-
-import redis.clients.jedis.JedisPool;
-
-import com.google.common.util.concurrent.RateLimiter;
-
-/**
- * 多线程运行JobConsumer,从"ss.job:ready" list中popup job进行处理。
- *
- * 可用系统参数重置变量改变线程数,@see RedisCounterBenchmark
- *
- * @author calvin
- */
-public class SimpleJobConsumerDemo implements Runnable {
-
- protected static final int THREAD_COUNT = 10;
- protected static final int PRINT_BETWEEN_SECONDS = 10;
-
- protected static JedisPool pool;
- protected static int threadCount;
-
- protected static AtomicLong golbalCounter = new AtomicLong(0);
- protected static AtomicLong golbalPreviousCount = new AtomicLong(0);
- protected static RateLimiter golbalPrintRate = RateLimiter.create(1d / PRINT_BETWEEN_SECONDS);
-
- private SimpleJobConsumer consumer;
-
- protected long localCounter = 0L;
- protected long localPreviousCount = 0L;
- protected RateLimiter localPrintRate = RateLimiter.create(1d / PRINT_BETWEEN_SECONDS);
-
- public static void main(String[] args) throws Exception {
-
- threadCount = Integer.parseInt(System.getProperty(ConcurrentBenchmark.THREAD_COUNT_NAME,
- String.valueOf(THREAD_COUNT)));
-
- pool = JedisPoolFactory.createJedisPool(JedisUtils.DEFAULT_HOST, JedisUtils.DEFAULT_PORT,
- JedisUtils.DEFAULT_TIMEOUT, threadCount);
-
- ExecutorService threadPool = Executors.newFixedThreadPool(threadCount);
- for (int i = 0; i < threadCount; i++) {
- SimpleJobConsumerDemo demo = new SimpleJobConsumerDemo();
- threadPool.execute(demo);
- }
-
- System.out.println("Hit enter to stop");
- try {
- while (true) {
- char c = (char) System.in.read();
- if (c == '\n') {
- System.out.println("Shutting down");
- threadPool.shutdownNow();
- boolean shutdownSucess = threadPool.awaitTermination(
- SimpleJobConsumer.DEFAULT_POPUP_TIMEOUT_SECONDS + 1, TimeUnit.SECONDS);
-
- if (!shutdownSucess) {
- System.out.println("Forcing exiting.");
- System.exit(-1);
- }
-
- return;
- }
- }
- } finally {
- pool.destroy();
- }
- }
-
- public SimpleJobConsumerDemo() {
- consumer = new SimpleJobConsumer("ss", pool);
- }
-
- @Override
- public void run() {
- while (!Thread.currentThread().isInterrupted()) {
- try {
- String job = consumer.popupJob();
- if (job != null) {
- handleJob(job);
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
-
- /**
- * 处理Job的回调函数.
- */
- public void handleJob(String job) {
-
- long globalCount = golbalCounter.incrementAndGet();
- localCounter++;
-
- // print global progress, 所有線程裡只有一個会在10秒內打印一次。
- if (golbalPrintRate.tryAcquire()) {
- System.out.printf("Total pop %,d jobs, tps is %,d\n", globalCount,
- (globalCount - golbalPreviousCount.get()) / PRINT_BETWEEN_SECONDS);
- golbalPreviousCount.set(globalCount);
- }
-
- // print current thread progress,10秒內打印一次。
- if (localPrintRate.tryAcquire()) {
- System.out.printf("Local thread pop %,d jobs, tps is %,d\n", localCounter,
- (localCounter - localPreviousCount) / PRINT_BETWEEN_SECONDS);
- localPreviousCount = localCounter;
- }
- }
-}
diff --git a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/redis/job/dispatcher/ReliableJobDispatcherDemo.java b/examples/showcase/src/main/java/org/springside/examples/showcase/demos/redis/job/dispatcher/ReliableJobDispatcherDemo.java
deleted file mode 100644
index 38b5bdc4e..000000000
--- a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/redis/job/dispatcher/ReliableJobDispatcherDemo.java
+++ /dev/null
@@ -1,73 +0,0 @@
-package org.springside.examples.showcase.demos.redis.job.dispatcher;
-
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.ScheduledFuture;
-import java.util.concurrent.TimeUnit;
-
-import org.springside.examples.showcase.demos.redis.JedisPoolFactory;
-import org.springside.modules.nosql.redis.JedisUtils;
-import org.springside.modules.nosql.redis.scheduler.JobDispatcher;
-import org.springside.modules.nosql.redis.scheduler.JobStatistics;
-
-import redis.clients.jedis.JedisPool;
-
-/**
- * 运行JobDispatcher,每秒将Job从"job:ss:scheduled" sorted set 发布到"job:ss:ready" list.
- * 如果有任务已被领取而长期没有被执行,会从"job:ss:locked" sorted set取回并重新发布到"job:ss:ready" list.
- *
- * 可用系统参数重置相关变量,@see RedisCounterBenchmark
- *
- * @author calvin
- */
-public class ReliableJobDispatcherDemo {
- public static final int EXPECT_TPS = 5000;
- public static final int DELAY_SECONDS = 10;
-
- private static ScheduledFuture statisticsTask;
-
- public static void main(String[] args) throws Exception {
-
- JedisPool pool = JedisPoolFactory.createJedisPool(JedisUtils.DEFAULT_HOST, JedisUtils.DEFAULT_PORT,
- JedisUtils.DEFAULT_TIMEOUT, 1);
- try {
- JobDispatcher dispatcher = new JobDispatcher("ss", pool);
- dispatcher.setReliable(true);
-
- JobStatistics statistics = new JobStatistics("ss", pool);
-
- startPrintStatistics(statistics);
- dispatcher.start();
-
- System.out.println("Hit enter to stop.");
- while (true) {
- char c = (char) System.in.read();
- if (c == '\n') {
- System.out.println("Shuting down");
- dispatcher.stop();
- stopPrintStatistics();
- return;
- }
- }
- } finally {
- pool.destroy();
- }
- }
-
- public static void startPrintStatistics(final JobStatistics statistics) {
- ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
- statisticsTask = scheduler.scheduleAtFixedRate(new Runnable() {
- @Override
- public void run() {
- System.out.printf(
- "Scheduled job %d, Ready Job %d, Lock Job %d, Dispatch Counter %d, Retry Counter %d \n",
- statistics.getScheduledJobNumber(), statistics.getReadyJobNumber(),
- statistics.getLockJobNumber(), statistics.getDispatchCounter(), statistics.getRetryCounter());
- }
- }, 0, 10, TimeUnit.SECONDS);
- }
-
- public static void stopPrintStatistics() {
- statisticsTask.cancel(true);
- }
-}
diff --git a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/redis/job/dispatcher/SimpleJobDispatcherDemo.java b/examples/showcase/src/main/java/org/springside/examples/showcase/demos/redis/job/dispatcher/SimpleJobDispatcherDemo.java
deleted file mode 100644
index 4c2ddb751..000000000
--- a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/redis/job/dispatcher/SimpleJobDispatcherDemo.java
+++ /dev/null
@@ -1,70 +0,0 @@
-package org.springside.examples.showcase.demos.redis.job.dispatcher;
-
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.ScheduledFuture;
-import java.util.concurrent.TimeUnit;
-
-import org.springside.examples.showcase.demos.redis.JedisPoolFactory;
-import org.springside.modules.nosql.redis.JedisUtils;
-import org.springside.modules.nosql.redis.scheduler.JobDispatcher;
-import org.springside.modules.nosql.redis.scheduler.JobStatistics;
-
-import redis.clients.jedis.JedisPool;
-
-/**
- * 运行JobDispatcher,每秒将Job从"job:ss:scheduled" sorted set 发布到"job:ss:ready" list.
- *
- * 可用系统参数重置相关变量,@see RedisCounterBenchmark
- *
- * @author calvin
- */
-public class SimpleJobDispatcherDemo {
-
- public static final int EXPECT_TPS = 5000;
- public static final int DELAY_SECONDS = 10;
-
- private static ScheduledFuture statisticsTask;
-
- public static void main(String[] args) throws Exception {
-
- JedisPool pool = JedisPoolFactory.createJedisPool(JedisUtils.DEFAULT_HOST, JedisUtils.DEFAULT_PORT,
- JedisUtils.DEFAULT_TIMEOUT, 1);
- try {
- JobDispatcher dispatcher = new JobDispatcher("ss", pool);
- JobStatistics statistics = new JobStatistics("ss", pool);
-
- startPrintStatistics(statistics);
- dispatcher.start();
-
- System.out.println("Hit enter to stop.");
- while (true) {
- char c = (char) System.in.read();
- if (c == '\n') {
- System.out.println("Shuting down");
- dispatcher.stop();
- stopPrintStatistics();
- return;
- }
- }
- } finally {
- pool.destroy();
- }
- }
-
- private static void startPrintStatistics(final JobStatistics statistics) {
- ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
- statisticsTask = scheduler.scheduleAtFixedRate(new Runnable() {
- @Override
- public void run() {
- System.out.printf("Scheduled job %d, Ready Job %d, Dispatch Counter %d \n",
- statistics.getScheduledJobNumber(), statistics.getReadyJobNumber(),
- statistics.getDispatchCounter());
- }
- }, 0, 10, TimeUnit.SECONDS);
- }
-
- private static void stopPrintStatistics() {
- statisticsTask.cancel(true);
- }
-}
diff --git a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/redis/job/producer/JobProducerDemo.java b/examples/showcase/src/main/java/org/springside/examples/showcase/demos/redis/job/producer/JobProducerDemo.java
deleted file mode 100644
index c7b2053df..000000000
--- a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/redis/job/producer/JobProducerDemo.java
+++ /dev/null
@@ -1,75 +0,0 @@
-package org.springside.examples.showcase.demos.redis.job.producer;
-
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicLong;
-
-import org.springside.examples.showcase.demos.redis.JedisPoolFactory;
-import org.springside.examples.showcase.demos.redis.job.dispatcher.SimpleJobDispatcherDemo;
-import org.springside.modules.nosql.redis.JedisUtils;
-import org.springside.modules.nosql.redis.scheduler.JobProducer;
-import org.springside.modules.test.benchmark.BenchmarkTask;
-import org.springside.modules.test.benchmark.ConcurrentBenchmark;
-
-import redis.clients.jedis.JedisPool;
-
-/**
- * 运行JobManager产生新的Job。
- *
- * 可用系统参数重置相关变量,@see RedisCounterBenchmark
- *
- * @author calvin
- */
-public class JobProducerDemo extends ConcurrentBenchmark {
- private static final int DEFAULT_THREAD_COUNT = 5;
- private static final long DEFAULT_LOOP_COUNT = 100000;
-
- private static AtomicLong expiredMills = new AtomicLong(System.currentTimeMillis()
- + (SimpleJobDispatcherDemo.DELAY_SECONDS * 1000));
- private static AtomicLong idGenerator = new AtomicLong(0);
-
- private long expectTps;
- private JedisPool pool;
- private JobProducer jobProducer;
-
- public static void main(String[] args) throws Exception {
- JobProducerDemo benchmark = new JobProducerDemo();
- benchmark.execute();
- }
-
- public JobProducerDemo() {
- super(DEFAULT_THREAD_COUNT, DEFAULT_LOOP_COUNT);
- this.expectTps = Long.parseLong(System.getProperty("benchmark.tps",
- String.valueOf(SimpleJobDispatcherDemo.EXPECT_TPS)));
- }
-
- @Override
- protected void setUp() {
- pool = JedisPoolFactory.createJedisPool(JedisUtils.DEFAULT_HOST, JedisUtils.DEFAULT_PORT,
- JedisUtils.DEFAULT_TIMEOUT, threadCount);
- jobProducer = new JobProducer("ss", pool);
- }
-
- @Override
- protected void tearDown() {
- pool.destroy();
- }
-
- @Override
- protected BenchmarkTask createTask() {
- return new JobProducerTask();
- }
-
- public class JobProducerTask extends BenchmarkTask {
- @Override
- public void execute(final int requestSequence) {
- long jobId = idGenerator.getAndIncrement();
- jobProducer.schedule("job:" + jobId, expiredMills.get() - System.currentTimeMillis(),
- TimeUnit.MILLISECONDS);
-
- // 达到期望的每秒的TPS后,expireTime往后滚动一秒
- if ((jobId % (expectTps)) == 0) {
- expiredMills.addAndGet(1000);
- }
- }
- }
-}
diff --git a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/schedule/JdkTimerJob.java b/examples/showcase/src/main/java/org/springside/examples/showcase/demos/schedule/JdkTimerJob.java
deleted file mode 100644
index 2f0deb37b..000000000
--- a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/schedule/JdkTimerJob.java
+++ /dev/null
@@ -1,85 +0,0 @@
-package org.springside.examples.showcase.demos.schedule;
-
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-
-import javax.annotation.PostConstruct;
-import javax.annotation.PreDestroy;
-
-import org.apache.commons.lang3.Validate;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.scheduling.support.TaskUtils;
-import org.springside.modules.utils.Threads;
-
-import com.google.common.util.concurrent.ThreadFactoryBuilder;
-
-/**
- * 用JDKScheduledThreadPoolExecutor定时执行的任务。
- * 相比Spring的Task NameSpace配置方, 不需要反射調用,并强化了退出超时控制.
- *
- * @author calvin
- */
-public class JdkTimerJob implements Runnable {
-
- private int initialDelay = 0;
-
- private int period = 0;
-
- private int shutdownTimeout = Integer.MAX_VALUE;
-
- private ScheduledExecutorService scheduledExecutorService;
-
- @Autowired
- private UserCountScanner userCountScanner;
-
- @PostConstruct
- public void start() throws Exception {
- Validate.isTrue(period > 0);
-
- // 任何异常不会中断schedule执行, 由Spring TaskUtils的LOG_AND_SUPPRESS_ERROR_HANDLER進行处理
- Runnable task = TaskUtils.decorateTaskWithErrorHandler(this, null, true);
-
- // 创建单线程的SechdulerExecutor,并用guava的ThreadFactoryBuilder设定生成线程的名称
- scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(new ThreadFactoryBuilder().setNameFormat(
- "JdkTimerJob-%1$d").build());
-
- // scheduleAtFixedRatefixRate() 固定任务两次启动之间的时间间隔.
- // scheduleAtFixedDelay() 固定任务结束后到下一次启动间的时间间隔.
- scheduledExecutorService.scheduleAtFixedRate(task, initialDelay, period, TimeUnit.SECONDS);
- }
-
- @PreDestroy
- public void stop() {
- Threads.normalShutdown(scheduledExecutorService, shutdownTimeout, TimeUnit.SECONDS);
- }
-
- /**
- * 定时打印当前用户数到日志.
- */
- @Override
- public void run() {
- userCountScanner.executeByJdk();
- }
-
- /**
- * 设置任务初始启动延时时间.
- */
- public void setInitialDelay(int initialDelay) {
- this.initialDelay = initialDelay;
- }
-
- /**
- * 设置任务间隔时间,单位秒.
- */
- public void setPeriod(int period) {
- this.period = period;
- }
-
- /**
- * 设置normalShutdown的等待时间, 单位秒.
- */
- public void setShutdownTimeout(int shutdownTimeout) {
- this.shutdownTimeout = shutdownTimeout;
- }
-}
diff --git a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/schedule/QuartzClusterableJob.java b/examples/showcase/src/main/java/org/springside/examples/showcase/demos/schedule/QuartzClusterableJob.java
deleted file mode 100644
index c34e5e7bb..000000000
--- a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/schedule/QuartzClusterableJob.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package org.springside.examples.showcase.demos.schedule;
-
-import java.util.Map;
-
-import org.quartz.JobExecutionContext;
-import org.quartz.JobExecutionException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.context.ApplicationContext;
-import org.springframework.scheduling.quartz.QuartzJobBean;
-import org.springside.examples.showcase.service.AccountService;
-
-/**
- * 被Spring的Quartz JobDetailBean定时执行的Job类, 支持持久化到数据库实现Quartz集群.
- *
- * 因为需要被持久化, 不能有用XXService等不能被持久化的成员变量,
- * 只能在每次调度时从QuartzJobBean注入的applicationContext中动态取出.
- *
- * @author calvin
- */
-public class QuartzClusterableJob extends QuartzJobBean {
-
- private static Logger logger = LoggerFactory.getLogger(QuartzClusterableJob.class);
-
- private ApplicationContext applicationContext;
-
- /**
- * 从SchedulerFactoryBean注入的applicationContext.
- */
- public void setApplicationContext(ApplicationContext applicationContext) {
- this.applicationContext = applicationContext;
- }
-
- /**
- * 定时打印当前用户数到日志.
- */
- @Override
- protected void executeInternal(JobExecutionContext ctx) throws JobExecutionException {
- AccountService accountService = applicationContext.getBean(AccountService.class);
- Map config = (Map) applicationContext.getBean("timerJobConfig");
-
- long userCount = accountService.getUserCount();
- String nodeName = (String) config.get("nodeName");
-
- logger.info("There are {} user in database, printed by quartz cluster job on node {}.", userCount, nodeName);
- }
-}
diff --git a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/schedule/SpringCronJob.java b/examples/showcase/src/main/java/org/springside/examples/showcase/demos/schedule/SpringCronJob.java
deleted file mode 100644
index ac4c8227d..000000000
--- a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/schedule/SpringCronJob.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package org.springside.examples.showcase.demos.schedule;
-
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-
-import javax.annotation.PostConstruct;
-import javax.annotation.PreDestroy;
-
-import org.apache.commons.lang3.Validate;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
-import org.springframework.scheduling.support.CronTrigger;
-import org.springside.modules.utils.Threads;
-
-/**
- * 使用Spring的ThreadPoolTaskScheduler执行Cron式任务的类.
- * 相比Spring的Task NameSpace配置方式, 不需要反射調用,并强化了退出超时控制.
- *
- * @author calvin
- */
-public class SpringCronJob implements Runnable {
-
- private String cronExpression;
-
- private int shutdownTimeout = Integer.MAX_VALUE;
-
- private ThreadPoolTaskScheduler threadPoolTaskScheduler;
-
- @Autowired
- private UserCountScanner userCountScanner;
-
- @PostConstruct
- public void start() {
- Validate.notBlank(cronExpression);
-
- threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
- threadPoolTaskScheduler.setThreadNamePrefix("SpringCronJob");
- threadPoolTaskScheduler.initialize();
-
- threadPoolTaskScheduler.schedule(this, new CronTrigger(cronExpression));
- }
-
- @PreDestroy
- public void stop() {
- ScheduledExecutorService scheduledExecutorService = threadPoolTaskScheduler.getScheduledExecutor();
- Threads.normalShutdown(scheduledExecutorService, shutdownTimeout, TimeUnit.SECONDS);
- }
-
- /**
- * 定时打印当前用户数到日志.
- */
- @Override
- public void run() {
- userCountScanner.executeBySpringCronByJava();
- }
-
- public void setCronExpression(String cronExpression) {
- this.cronExpression = cronExpression;
- }
-
- /**
- * 设置normalShutdown的等待时间,单位秒.
- */
- public void setShutdownTimeout(int shutdownTimeout) {
- this.shutdownTimeout = shutdownTimeout;
- }
-}
diff --git a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/schedule/UserCountScanner.java b/examples/showcase/src/main/java/org/springside/examples/showcase/demos/schedule/UserCountScanner.java
deleted file mode 100644
index a7f375c32..000000000
--- a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/schedule/UserCountScanner.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package org.springside.examples.showcase.demos.schedule;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-import org.springside.examples.showcase.service.AccountService;
-
-/**
- * 被Spring各种Scheduler反射调用的Service POJO.
- *
- * @author Calvin
- */
-@Component
-public class UserCountScanner {
-
- private static Logger logger = LoggerFactory.getLogger(UserCountScanner.class);
-
- @Autowired
- private AccountService accountService;
-
- public void executeByJdk() {
- execute("jdk timer job");
- }
-
- public void executeBySpringCronByJava() {
- execute("spring cron job by java");
- }
-
- // 被Spring的Quartz MethodInvokingJobDetailFactoryBean反射执行
- public void executeByQuartzLocalJob() {
- execute("quartz local job");
- }
-
- // 被Spring的Scheduler namespace 反射构造成ScheduledMethodRunnable
- public void executeBySpringCronByXml() {
- execute("spring cron job by xml");
- }
-
- // 被Spring的Scheduler namespace 反射构造成ScheduledMethodRunnable
- public void executeBySpringTimerByXml() {
- execute("spring timer job by xml");
- }
-
- /**
- * 定时打印当前用户数到日志.
- */
- private void execute(String by) {
- long userCount = accountService.getUserCount();
- logger.info("There are {} user in database, printed by {}.", userCount, by);
- }
-}
diff --git a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/utilities/collection/AdvancedMapDemo.java b/examples/showcase/src/main/java/org/springside/examples/showcase/demos/utilities/collection/AdvancedMapDemo.java
deleted file mode 100644
index 6a153a5a2..000000000
--- a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/utilities/collection/AdvancedMapDemo.java
+++ /dev/null
@@ -1,72 +0,0 @@
-package org.springside.examples.showcase.demos.utilities.collection;
-
-import static org.junit.Assert.*;
-
-import java.util.Collection;
-
-import org.junit.Test;
-
-import com.google.common.collect.BiMap;
-import com.google.common.collect.HashBasedTable;
-import com.google.common.collect.HashBiMap;
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.Multimap;
-import com.google.common.collect.Table;
-
-public class AdvancedMapDemo {
-
- /**
- * Guava的同一个key可以有多个value的Map.
- */
- @Test
- public void multiMap() {
- Multimap multimap = HashMultimap.create();
- multimap.put(1, "a");
- multimap.put(2, "b");
- multimap.put(3, "c");
- multimap.put(1, "a2");
-
- // 取出key=1的两个值
- Collection values = multimap.get(1);
- assertEquals(2, values.size());
-
- // size是4不是3
- assertEquals(4, multimap.size());
-
- // 删除其中一个值
- multimap.remove(1, "a");
- assertEquals(1, multimap.get(1).size());
-
- }
-
- /**
- * Guava的BiMap,可随时调转Key与Value.
- */
- @Test
- public void biMap() {
- BiMap bimap = HashBiMap.create();
- BiMap inverseMap = bimap.inverse();
-
- bimap.put(1, "a");
- bimap.put(2, "b");
- assertEquals(Integer.valueOf(2), inverseMap.get("b"));
-
- inverseMap.put("c", 3);
- assertEquals("c", bimap.get(3));
- }
-
- /*
- * Guava的Table等于有兩个key的Map,可用来替代Map
- */
- @Test
- public void table() {
- Table table = HashBasedTable.create();
- table.put(1, "a", "1a");
- table.put(1, "b", "1b");
- table.put(2, "a", "2a");
- table.put(2, "b", "2b");
-
- assertEquals("2a", table.get(2, "a"));
- }
-
-}
diff --git a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/utilities/collection/CollectionsDemo.java b/examples/showcase/src/main/java/org/springside/examples/showcase/demos/utilities/collection/CollectionsDemo.java
deleted file mode 100644
index f867aa3ae..000000000
--- a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/utilities/collection/CollectionsDemo.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package org.springside.examples.showcase.demos.utilities.collection;
-
-import static org.junit.Assert.*;
-
-import java.util.List;
-import java.util.Map;
-
-import org.junit.Test;
-import org.springside.examples.showcase.entity.User;
-import org.springside.modules.utils.Collections3;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-
-/**
- * 演示各种Collections如何简化Collection操作.
- *
- * @author calvin
- */
-public class CollectionsDemo {
-
- @Test
- public void init() {
- // 无需在等号右边重新定义泛型的创建ArrayList
- List list = Lists.newArrayList();
- // 创建的同时初始化数据
- List list2 = Lists.newArrayList("a", "b", "c");
-
- // 无需在等号右边重新定义泛型的创建HashMap
- Map map = Maps.newHashMap();
- // 创建Map的同时初始化值,不过这个map是不可修改的,主要用于编写测试用例。
- Map unmodifiedMap = ImmutableMap.of(1, "foo", 2, "bar");
- }
-
- @Test
- public void operation() {
- List list = Lists.newArrayList("a", "b", "c");
- List list2 = Lists.newArrayList("a", "b");
-
- // nullsafe的判断是否为空
- assertFalse(Collections3.isEmpty(list));
-
- // 获取最后一个
- assertEquals("c", Collections3.getLast(list));
-
- // list+list2的新List
- List result = Collections3.union(list, list2);
- assertEquals("[a, b, c, a, b]", result.toString());
-
- // list-list2的新List
- result = Collections3.subtract(list, list2);
- assertEquals("[c]", result.toString());
-
- // list与list2的交集的新List
- result = Collections3.intersection(list, list2);
- assertEquals("[a, b]", result.toString());
-
- }
-}
diff --git a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/utilities/dozer/DozerDemo.java b/examples/showcase/src/main/java/org/springside/examples/showcase/demos/utilities/dozer/DozerDemo.java
deleted file mode 100644
index 2ca6e5d52..000000000
--- a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/utilities/dozer/DozerDemo.java
+++ /dev/null
@@ -1,205 +0,0 @@
-package org.springside.examples.showcase.demos.utilities.dozer;
-
-import static org.junit.Assert.*;
-
-import java.util.List;
-
-import org.dozer.Mapping;
-import org.junit.Test;
-import org.springside.modules.mapper.BeanMapper;
-
-/**
- * 演示Dozer如何只要属性名相同,可以罔顾属性类型是基础类型<->String的差别,Array转为List,甚至完全另一种DTO的差别。
- * 并且能完美解决循环依赖问题。
- * 使用@Mapping能解决属性名不匹配的情况.
- */
-public class DozerDemo {
-
- /**
- * 从一个ProductDTO实例,创建出一个新的Product实例。
- */
- @Test
- public void map() {
- ProductDTO productDTO = new ProductDTO();
- productDTO.setName("car");
- productDTO.setPrice("200");
-
- PartDTO partDTO = new PartDTO();
- partDTO.setName("door");
- partDTO.setProduct(productDTO);
-
- productDTO.setParts(new PartDTO[] { partDTO });
-
- // ProductDTO->Product
- Product product = BeanMapper.map(productDTO, Product.class);
-
- assertEquals("car", product.getProductName());
- // 原来的字符串被Map成Double。
- assertEquals(Double.valueOf(200), product.getPrice());
- // 原来的PartDTO同样被Map成Part ,Array被Map成List
- assertEquals("door", product.getParts().get(0).getName());
- // Part中循环依赖的Product同样被赋值。
- assertEquals("car", product.getParts().get(0).getProduct().getProductName());
-
- // 再反向从Product->ProductDTO
- ProductDTO productDTO2 = BeanMapper.map(product, ProductDTO.class);
- assertEquals("car", productDTO2.getName());
- assertEquals("200.0", productDTO2.getPrice());
- assertEquals("door", productDTO2.getParts()[0].getName());
- }
-
- /**
- * 演示将一个ProductDTO实例的内容,Copy到另一个已存在的Product实例.
- */
- @Test
- public void copy() {
- ProductDTO productDTO = new ProductDTO();
- productDTO.setName("car");
- productDTO.setPrice("200");
-
- PartDTO partDTO = new PartDTO();
- partDTO.setName("door");
- partDTO.setProduct(productDTO);
-
- productDTO.setParts(new PartDTO[] { partDTO });
-
- // 已存在的Product实例
- Product product = new Product();
- product.setProductName("horse");
- product.setWeight(new Double(20));
-
- BeanMapper.copy(productDTO, product);
-
- // 原来的horse,被替换成car
- assertEquals("car", product.getProductName());
- // 原来的20的属性被覆盖成200,同样被从字符串被专为Double。
- assertEquals(Double.valueOf(200), product.getPrice());
- // DTO中没有的属性值,在Product中被保留
- assertEquals(Double.valueOf(20), product.getWeight());
- // Part中循环依赖的Product同样被赋值。
- assertEquals("car", product.getParts().get(0).getProduct().getProductName());
- }
-
- public static class Product {
- private String productName;
- private Double price;
- private List parts;
- // DTO中没有的属性
- private Double weight;
-
- public String getProductName() {
- return productName;
- }
-
- public void setProductName(String productName) {
- this.productName = productName;
- }
-
- public Double getPrice() {
- return price;
- }
-
- public void setPrice(Double price) {
- this.price = price;
- }
-
- public List getParts() {
- return parts;
- }
-
- public void setParts(List parts) {
- this.parts = parts;
- }
-
- public Double getWeight() {
- return weight;
- }
-
- public void setWeight(Double weight) {
- this.weight = weight;
- }
-
- }
-
- public static class Part {
- // 反向依赖Product
- private Product product;
-
- private String name;
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public Product getProduct() {
- return product;
- }
-
- public void setProduct(Product product) {
- this.product = product;
- }
- }
-
- public static class ProductDTO {
- // 定义到Product中的productName,只要在一边定义,双向转换都可以使用.
- @Mapping("productName")
- private String name;
- // 类型为String 而非 Double
- private String price;
- // 类型为Array而非List, PartDTO而非Part
- private PartDTO[] parts;
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public String getPrice() {
- return price;
- }
-
- public void setPrice(String price) {
- this.price = price;
- }
-
- public PartDTO[] getParts() {
- return parts;
- }
-
- public void setParts(PartDTO[] parts) {
- this.parts = parts;
- }
- }
-
- public static class PartDTO {
- // 反向依赖ProductDTO
- private ProductDTO product;
-
- private String name;
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public ProductDTO getProduct() {
- return product;
- }
-
- public void setProduct(ProductDTO product) {
- this.product = product;
- }
-
- }
-
-}
diff --git a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/utilities/email/MimeMailService.java b/examples/showcase/src/main/java/org/springside/examples/showcase/demos/utilities/email/MimeMailService.java
deleted file mode 100644
index 4029a9156..000000000
--- a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/utilities/email/MimeMailService.java
+++ /dev/null
@@ -1,112 +0,0 @@
-package org.springside.examples.showcase.demos.utilities.email;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.Collections;
-import java.util.Map;
-
-import javax.mail.MessagingException;
-import javax.mail.internet.MimeMessage;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.core.io.ClassPathResource;
-import org.springframework.core.io.Resource;
-import org.springframework.mail.javamail.JavaMailSender;
-import org.springframework.mail.javamail.MimeMessageHelper;
-import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
-
-import freemarker.template.Configuration;
-import freemarker.template.Template;
-import freemarker.template.TemplateException;
-
-/**
- * MIME邮件服务类.
- *
- * 演示由Freemarker引擎生成的的html格式邮件, 并带有附件.
- *
- * @author calvin
- */
-public class MimeMailService {
-
- private static final String DEFAULT_ENCODING = "utf-8";
-
- private static Logger logger = LoggerFactory.getLogger(MimeMailService.class);
-
- private JavaMailSender mailSender;
-
- private Template template;
-
- /**
- * 发送MIME格式的用户修改通知邮件.
- */
- public void sendNotificationMail(String userName) {
-
- try {
- MimeMessage msg = mailSender.createMimeMessage();
- MimeMessageHelper helper = new MimeMessageHelper(msg, true, DEFAULT_ENCODING);
-
- helper.setTo("springside3.demo@gmail.com");
- helper.setFrom("springside3.demo@gmail.com");
- helper.setSubject("用户修改通知");
-
- String content = generateContent(userName);
- helper.setText(content, true);
-
- File attachment = generateAttachment();
- helper.addAttachment("mailAttachment.txt", attachment);
-
- mailSender.send(msg);
- logger.info("HTML版邮件已发送至springside3.demo@gmail.com");
- } catch (MessagingException e) {
- logger.error("构造邮件失败", e);
- } catch (Exception e) {
- logger.error("发送邮件失败", e);
- }
- }
-
- /**
- * 使用Freemarker生成html格式内容.
- */
- private String generateContent(String userName) throws MessagingException {
-
- try {
- Map context = Collections.singletonMap("userName", userName);
- return FreeMarkerTemplateUtils.processTemplateIntoString(template, context);
- } catch (IOException e) {
- logger.error("生成邮件内容失败, FreeMarker模板不存在", e);
- throw new MessagingException("FreeMarker模板不存在", e);
- } catch (TemplateException e) {
- logger.error("生成邮件内容失败, FreeMarker处理失败", e);
- throw new MessagingException("FreeMarker处理失败", e);
- }
- }
-
- /**
- * 获取classpath中的附件.
- */
- private File generateAttachment() throws MessagingException {
- try {
- Resource resource = new ClassPathResource("/email/mailAttachment.txt");
- return resource.getFile();
- } catch (IOException e) {
- logger.error("构造邮件失败,附件文件不存在", e);
- throw new MessagingException("附件文件不存在", e);
- }
- }
-
- /**
- * Spring的MailSender.
- */
- public void setMailSender(JavaMailSender mailSender) {
- this.mailSender = mailSender;
- }
-
- /**
- * 注入Freemarker引擎配置,构造Freemarker 邮件内容模板.
- */
- public void setFreemarkerConfiguration(Configuration freemarkerConfiguration) throws IOException {
- // 根据freemarkerConfiguration的templateLoaderPath载入文件.
- template = freemarkerConfiguration.getTemplate("mailTemplate.ftl", DEFAULT_ENCODING);
- }
-}
diff --git a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/utilities/email/SimpleMailService.java b/examples/showcase/src/main/java/org/springside/examples/showcase/demos/utilities/email/SimpleMailService.java
deleted file mode 100644
index c00f23183..000000000
--- a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/utilities/email/SimpleMailService.java
+++ /dev/null
@@ -1,58 +0,0 @@
-package org.springside.examples.showcase.demos.utilities.email;
-
-import java.util.Date;
-
-import org.apache.commons.lang3.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.mail.SimpleMailMessage;
-import org.springframework.mail.javamail.JavaMailSender;
-
-/**
- * 纯文本邮件服务类.
- *
- * @author calvin
- */
-public class SimpleMailService {
- private static Logger logger = LoggerFactory.getLogger(SimpleMailService.class);
-
- private JavaMailSender mailSender;
- private String textTemplate;
-
- /**
- * 发送纯文本的用户修改通知邮件.
- */
- public void sendNotificationMail(String userName) {
- SimpleMailMessage msg = new SimpleMailMessage();
- msg.setFrom("springside3.demo@gmail.com");
- msg.setTo("springside3.demo@gmail.com");
- msg.setSubject("用户修改通知");
-
- // 将用户名与当期日期格式化到邮件内容的字符串模板
- String content = String.format(textTemplate, userName, new Date());
- msg.setText(content);
-
- try {
- mailSender.send(msg);
- if (logger.isInfoEnabled()) {
- logger.info("纯文本邮件已发送至{}", StringUtils.join(msg.getTo(), ","));
- }
- } catch (Exception e) {
- logger.error("发送邮件失败", e);
- }
- }
-
- /**
- * Spring的MailSender.
- */
- public void setMailSender(JavaMailSender mailSender) {
- this.mailSender = mailSender;
- }
-
- /**
- * 邮件内容的字符串模板.
- */
- public void setTextTemplate(String textTemplate) {
- this.textTemplate = textTemplate;
- }
-}
diff --git a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/utilities/io/IODemo.java b/examples/showcase/src/main/java/org/springside/examples/showcase/demos/utilities/io/IODemo.java
deleted file mode 100644
index 3e9db96d2..000000000
--- a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/utilities/io/IODemo.java
+++ /dev/null
@@ -1,118 +0,0 @@
-package org.springside.examples.showcase.demos.utilities.io;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
-import java.io.StringWriter;
-import java.util.List;
-
-import org.apache.commons.io.FileUtils;
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.io.input.ReaderInputStream;
-import org.apache.commons.io.output.WriterOutputStream;
-import org.junit.Test;
-import org.springside.modules.utils.Exceptions;
-
-import com.google.common.base.Charsets;
-
-/**
- * 演示各种IO操作.
- *
- * @author calvin
- */
-public class IODemo {
-
- @Test
- public void workWithFileContent() {
- File file = new File("woop.txt");
- File destFile = new File("bar.txt");
- try {
- // text -> file, 类似的还有Collection, byte[] ->file
- FileUtils.writeStringToFile(file, "Hey sailor!\nHaha\n", "UTF-8");
-
- // inputstream -> file,
- InputStream source = IOUtils.toInputStream("Hej", "UTF-8");
- FileUtils.copyInputStreamToFile(source, file);
-
- // ///////////////////////////
- // file -> outputstream
- System.out.println("copy File to outputstream:");
- FileUtils.copyFile(file, System.out);
-
- // file -> file
- FileUtils.copyFile(file, destFile);
-
- // file -> string
- System.out.println("File to String:");
- System.out.println(FileUtils.readFileToString(file, "UTF-8"));
-
- // file -> list
- System.out.println("File to List:");
- List lines = FileUtils.readLines(file, "UTF-8");
- for (String string : lines) {
- System.out.println(string);
- }
- } catch (IOException e) {
- Exceptions.unchecked(e);
- }
- }
-
- /*
- * String/Input/OutputStream/Reader/Writer
- */
- @Test
- public void workWithStream() {
- InputStream in = null;
- try {
- String content = "Stream testing";
-
- // String - > InputStream.
- in = IOUtils.toInputStream(content, "UTF-8");
-
- // String - > OutputStream
- System.out.println("String to OutputStram:");
- IOUtils.write(content, System.out, "UTF-8");
-
- // //////////////////
- // InputStream/Reader -> String
- System.out.println("\nInputStram to String:");
- System.out.println(IOUtils.toString(in, "UTF-8"));
-
- // InputStream/Reader -> OutputStream/Writer, 四者间可任意组合.
- InputStream in2 = IOUtils.toInputStream(content); // 重新准备inputSteam
- System.out.println("InputStream to OutputStream:");
- IOUtils.copy(in2, System.out);
-
- // /////////////////
- // InputStream ->Reader
- InputStreamReader reader = new InputStreamReader(in, Charsets.UTF_8);
- // Reader->InputStream
- ReaderInputStream in3 = new ReaderInputStream(reader, Charsets.UTF_8);
-
- // OutputStream ->Writer
- OutputStreamWriter writer = new OutputStreamWriter(System.out, Charsets.UTF_8);
- // Writer->OutputStream
- WriterOutputStream out2 = new WriterOutputStream(writer, Charsets.UTF_8);
-
- // ////////////////////
- // 收集Writer的输出内容到String.
- StringWriter sw = new StringWriter();
- sw.write("I am String writer");
- System.out.println("\nCollect writer content:");
- System.out.println(sw.toString());
-
- } catch (IOException e) {
- Exceptions.unchecked(e);
- } finally {
- // 安静的关闭Stream
- IOUtils.closeQuietly(in);
- }
- }
-
- @Test
- public void workWithFileAndDir() {
- // 看FileUtils的JavaDoc即可
- }
-}
diff --git a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/utilities/json/JsonDemo.java b/examples/showcase/src/main/java/org/springside/examples/showcase/demos/utilities/json/JsonDemo.java
deleted file mode 100644
index 4de6af02e..000000000
--- a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/utilities/json/JsonDemo.java
+++ /dev/null
@@ -1,725 +0,0 @@
-package org.springside.examples.showcase.demos.utilities.json;
-
-import static org.junit.Assert.*;
-
-import java.io.IOException;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-
-import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlTransient;
-import javax.xml.bind.annotation.XmlType;
-
-import org.joda.time.DateTime;
-import org.joda.time.format.DateTimeFormat;
-import org.junit.Test;
-import org.springside.modules.mapper.JsonMapper;
-
-import com.fasterxml.jackson.annotation.JsonAnyGetter;
-import com.fasterxml.jackson.annotation.JsonAnySetter;
-import com.fasterxml.jackson.annotation.JsonBackReference;
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import com.fasterxml.jackson.annotation.JsonManagedReference;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.annotation.JsonPropertyOrder;
-import com.fasterxml.jackson.annotation.JsonView;
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.databind.DeserializationContext;
-import com.fasterxml.jackson.databind.JavaType;
-import com.fasterxml.jackson.databind.JsonMappingException;
-import com.fasterxml.jackson.databind.ObjectWriter;
-import com.fasterxml.jackson.databind.PropertyNamingStrategy;
-import com.fasterxml.jackson.databind.SerializerProvider;
-import com.fasterxml.jackson.databind.cfg.MapperConfig;
-import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
-import com.fasterxml.jackson.databind.introspect.AnnotatedMethod;
-import com.fasterxml.jackson.databind.module.SimpleModule;
-import com.fasterxml.jackson.databind.ser.std.StdSerializer;
-import com.fasterxml.jackson.datatype.joda.JodaModule;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-
-/**
- * 演示Jackson的基本使用方式及大量的特殊Feature.
- *
- * @author calvin
- */
-public class JsonDemo {
-
- private static JsonMapper mapper = JsonMapper.nonDefaultMapper();
-
- // // 基本操作 演示 ////
-
- /**
- * 序列化对象/集合到Json字符串.
- */
- @Test
- public void toJson() throws Exception {
- // Bean
- TestBean bean = new TestBean("A");
- String beanString = mapper.toJson(bean);
- System.out.println("Bean:" + beanString);
- assertEquals("{\"name\":\"A\"}", beanString);
-
- // Map
- Map map = Maps.newLinkedHashMap();
- map.put("name", "A");
- map.put("age", 2);
- String mapString = mapper.toJson(map);
- System.out.println("Map:" + mapString);
- assertEquals("{\"name\":\"A\",\"age\":2}", mapString);
-
- // List
- List stringList = Lists.newArrayList("A", "B", "C");
- String listString = mapper.toJson(stringList);
- System.out.println("String List:" + listString);
- assertEquals("[\"A\",\"B\",\"C\"]", listString);
-
- // List
- List beanList = Lists.newArrayList(new TestBean("A"), new TestBean("B"));
- String beanListString = mapper.toJson(beanList);
- System.out.println("Bean List:" + beanListString);
- assertEquals("[{\"name\":\"A\"},{\"name\":\"B\"}]", beanListString);
-
- // Bean[]
- TestBean[] beanArray = new TestBean[] { new TestBean("A"), new TestBean("B") };
- String beanArrayString = mapper.toJson(beanArray);
- System.out.println("Array List:" + beanArrayString);
- assertEquals("[{\"name\":\"A\"},{\"name\":\"B\"}]", beanArrayString);
- }
-
- /**
- * 从Json字符串反序列化对象/集合.
- */
- @Test
- public void fromJson() throws Exception {
- // Bean
- String beanString = "{\"name\":\"A\"}";
- TestBean bean = mapper.fromJson(beanString, TestBean.class);
- System.out.println("Bean:" + bean);
-
- // Map
- String mapString = "{\"name\":\"A\",\"age\":2}";
- Map map = mapper.fromJson(mapString, HashMap.class);
- System.out.println("Map:");
- for (Entry entry : map.entrySet()) {
- System.out.println(entry.getKey() + " " + entry.getValue());
- }
-
- // List
- String listString = "[\"A\",\"B\",\"C\"]";
- List stringList = mapper.fromJson(listString, List.class);
- System.out.println("String List:");
- for (String element : stringList) {
- System.out.println(element);
- }
-
- // List
- String beanListString = "[{\"name\":\"A\"},{\"name\":\"B\"}]";
- JavaType beanListType = mapper.contructCollectionType(List.class, TestBean.class);
- List beanList = mapper.fromJson(beanListString, beanListType);
- System.out.println("Bean List:");
- for (TestBean element : beanList) {
- System.out.println(element);
- }
- }
-
- /**
- * 测试三种不同的Inclusion风格.
- */
- @Test
- public void threeTypeInclusion() {
- TestBean bean = new TestBean("A");
-
- // 打印全部属性
- JsonMapper normalMapper = new JsonMapper();
- assertEquals("{\"name\":\"A\",\"defaultValue\":\"hello\",\"nullValue\":null}", normalMapper.toJson(bean));
-
- // 不打印nullValue属性
- JsonMapper nonEmptyMapper = JsonMapper.nonEmptyMapper();
- assertEquals("{\"name\":\"A\",\"defaultValue\":\"hello\"}", nonEmptyMapper.toJson(bean));
-
- // 不打印默认值未改变的nullValue与defaultValue属性
- JsonMapper nonDefaultMaper = JsonMapper.nonDefaultMapper();
- assertEquals("{\"name\":\"A\"}", nonDefaultMaper.toJson(bean));
- }
-
- /*
- * 测试类似Jaxb的常用annotaion,如properName,ignore,propertyOrder
- */
- @Test
- public void jacksonAnnoation() {
- TestBean2 testBean = new TestBean2(1, "foo", 18);
- // 结果name属性输出在前,且被改名为productName,且age属性被ignore
- assertEquals("{\"productName\":\"foo\",\"id\":1}", mapper.toJson(testBean));
- }
-
- /*
- * 测试直接使用Jaxb的annotaion
- */
- @Test
- public void jaxbAnnoation() {
- JsonMapper newMapper = new JsonMapper();
- newMapper.enableJaxbAnnotation();
- TestBean3 testBean = new TestBean3(1, "foo", 18);
- // 结果name属性输出在前,且被改名为productName,且age属性被ignore
- assertEquals("{\"productName\":\"foo\",\"id\":1}", newMapper.toJson(testBean));
- }
-
- // 调转顺序
- @JsonPropertyOrder({ "name", "id" })
- public static class TestBean2 {
-
- public long id;
-
- @JsonProperty("productName")
- public String name;
-
- @JsonIgnore
- public int age;
-
- public TestBean2() {
-
- }
-
- public TestBean2(long id, String name, int age) {
- this.id = id;
- this.name = name;
- this.age = age;
- }
-
- }
-
- // 调转顺序
- @XmlType(propOrder = { "name", "id" })
- public static class TestBean3 {
-
- public long id;
-
- @XmlElement(name = "productName")
- public String name;
-
- @XmlTransient
- public int age;
-
- public TestBean3() {
-
- }
-
- public TestBean3(long id, String name, int age) {
- this.id = id;
- this.name = name;
- this.age = age;
- }
-
- }
-
- /**
- * 更新一個已存在Bean,JSON字符串裡只含有Bean的部分屬性,只覆蓋这部分的屬性.
- */
- @Test
- public void updateBean() {
- String jsonString = "{\"name\":\"A\"}";
-
- TestBean bean = new TestBean();
- bean.setDefaultValue("Foobar");
-
- mapper.update(jsonString, bean);
-
- // name被赋值
- assertEquals("A", bean.getName());
- // DefaultValue不在Json串中,依然保留。
- assertEquals("Foobar", bean.getDefaultValue());
- }
-
- /**
- * 測試輸出jsonp格式內容.
- */
- @Test
- public void jsonp() {
- TestBean bean = new TestBean("foo");
- String jsonpString = mapper.toJsonP("callback", bean);
- assertEquals("callback({\"name\":\"foo\"})", jsonpString);
- }
-
- /**
- * 演示用的Bean, 主要演示不同風格的Mapper對Null值,初始化後沒改變過的屬性值的處理.
- */
- public static class TestBean {
-
- private String name;
- private String defaultValue = "hello"; // 默认值没被修改过的属性,可能会不序列化
- private String nullValue = null; // 空值的据行,可能会不序列化
-
- public TestBean() {
- }
-
- public TestBean(String name) {
- this.name = name;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public String getDefaultValue() {
- return defaultValue;
- }
-
- public void setDefaultValue(String defaultValue) {
- this.defaultValue = defaultValue;
- }
-
- public String getNullValue() {
- return nullValue;
- }
-
- public void setNullValue(String nullValue) {
- this.nullValue = nullValue;
- }
-
- @Override
- public String toString() {
- return "TestBean [defaultValue=" + defaultValue + ", name=" + name + ", nullValue=" + nullValue + "]";
- }
- }
-
- // //特殊数据类型演示////
-
- /**
- * 测试对枚举的序列化.
- */
- @Test
- public void enumType() {
- // toJSon默認使用enum.name()
- assertEquals("\"One\"", mapper.toJson(TestEnum.One));
- // fromJson使用enum.name()或enum.order()
- assertEquals(TestEnum.One, mapper.fromJson("\"One\"", TestEnum.class));
- assertEquals(TestEnum.One, mapper.fromJson("0", TestEnum.class));
-
- // 使用enum.toString(), 注意配置必須在所有讀寫動作之前調用.
- // 建议toString()使用index数字属性,比enum.name()节约了空间,比enum.order()则不会有顺序随时改变不确定的问题。
- JsonMapper newMapper = new JsonMapper();
- newMapper.enableEnumUseToString();
- assertEquals("\"1\"", newMapper.toJson(TestEnum.One));
- assertEquals(TestEnum.One, newMapper.fromJson("\"1\"", TestEnum.class));
- }
-
- /**
- * 枚舉類型的演示Bean.
- */
- public static enum TestEnum {
- One(1), Two(2), Three(3);
-
- private final int index;
-
- TestEnum(int index) {
- this.index = index;
- }
-
- @Override
- public String toString() {
- return String.valueOf(index);
- }
- }
-
- /**
- * 测试对日期的序列化,日期默认以Timestamp方式存储,也可以用2.0后也可以用@JsonFormat在属性上格式化.
- * 但JodaTime仍然只支持Timestamp形式, 或调用JodaTime.toString().
- */
- @Test
- public void dateType() {
-
- mapper.getMapper().registerModule(new JodaModule());
-
- Date date = new Date();
- DateTime dateTime = new DateTime(date);
- String timestampString = String.valueOf(date.getTime());
- String format = "yyyy-MM-dd HH:mm:ss";
- String formatedString = new DateTime(date).toString(format);
-
- DateBean dateBean = new DateBean();
- dateBean.startDate = date;
- dateBean.endDate = date;
- dateBean.dateTime = dateTime;
-
- // to json
- String expectedJson = "{\"startDate\":" + timestampString + ",\"endDate\":\"" + formatedString
- + "\",\"dateTime\":" + timestampString + "}";
- assertEquals(expectedJson, mapper.toJson(dateBean));
-
- // from json
- Date expectedEndDate = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss").parseDateTime(formatedString).toDate();
-
- DateBean resultBean = mapper.fromJson(expectedJson, DateBean.class);
- assertEquals(date, resultBean.startDate);
- assertEquals(expectedEndDate, resultBean.endDate);
- }
-
- public static class DateBean {
- // 默认timestamp存储
- public Date startDate;
- // 按annotation中的日期格式存储。
- @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+08:00")
- public Date endDate;
-
- public DateTime dateTime;
- }
-
- /**
- * 测试传入空对象,空字符串,Empty的集合,"null"字符串的结果.
- */
- @Test
- public void nullAndEmpty() {
- // toJson测试 //
-
- // Null Bean
- TestBean nullBean = null;
- String nullBeanString = mapper.toJson(nullBean);
- assertEquals("null", nullBeanString);
-
- // Empty List
- List emptyList = Lists.newArrayList();
- String emptyListString = mapper.toJson(emptyList);
- assertEquals("[]", emptyListString);
-
- // fromJson测试 //
-
- // Null String for Bean
- TestBean nullBeanResult = mapper.fromJson(null, TestBean.class);
- assertNull(nullBeanResult);
-
- nullBeanResult = mapper.fromJson("null", TestBean.class);
- assertNull(nullBeanResult);
-
- // Null/Empty String for List
- List nullListResult = mapper.fromJson(null, List.class);
- assertNull(nullListResult);
-
- nullListResult = mapper.fromJson("null", List.class);
- assertNull(nullListResult);
-
- nullListResult = mapper.fromJson("[]", List.class);
- assertEquals(0, nullListResult.size());
- }
-
- // // 高级应用 ////
- /**
- * 測試父子POJO間的循環引用.
- */
- @Test
- public void cycleReferenceBean() {
- // 初始化对象关系,parent的children里含有 child1,child2, child1/child2的parent均指向parent.
- CycleReferenceBean parent = new CycleReferenceBean("parent");
-
- CycleReferenceBean child1 = new CycleReferenceBean("child1");
- child1.setParent(parent);
- parent.getChildren().add(child1);
-
- CycleReferenceBean child2 = new CycleReferenceBean("child2");
- child2.setParent(parent);
- parent.getChildren().add(child2);
-
- // 序列化是, json字符串裡children中的child1/child2都不包含到parent的屬性
- String jsonString = "{\"name\":\"parent\",\"children\":[{\"name\":\"child1\"},{\"name\":\"child2\"}]}";
- assertEquals(jsonString, mapper.toJson(parent));
-
- // 注意此時如果單獨序列化child1,也不會打印parent,信息將丟失。
- assertEquals("{\"name\":\"child1\"}", mapper.toJson(child1));
-
- // 反向序列化时,Json已很聪明的把parent填入child1/child2中.
- CycleReferenceBean parentResult = mapper.fromJson(jsonString, CycleReferenceBean.class);
- assertEquals("parent", parentResult.getChildren().get(0).getParent().getName());
-
- // 单独反序列化child1,当然parent也是空
- CycleReferenceBean child1Result = mapper.fromJson("{\"name\":\"child1\"}", CycleReferenceBean.class);
- assertNull(child1Result.parent);
- assertEquals("child1", child1Result.getName());
- }
-
- /**
- * 父子POJO間的循環引用的演示Bean,@JsonBackReference 与 @JsonManagedReference 是关键.
- */
- public static class CycleReferenceBean {
-
- private String name;
- private CycleReferenceBean parent;
- private List children = Lists.newArrayList();
-
- public CycleReferenceBean() {
- }
-
- public CycleReferenceBean(String name) {
- this.name = name;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- // 注意getter與setter都要添加annotation
- @JsonBackReference
- public CycleReferenceBean getParent() {
- return parent;
- }
-
- @JsonBackReference
- public void setParent(CycleReferenceBean parent) {
- this.parent = parent;
- }
-
- @JsonManagedReference
- public List getChildren() {
- return children;
- }
-
- @JsonManagedReference
- public void setChildren(List children) {
- this.children = children;
- }
- }
-
- /**
- * 測試可擴展Bean.
- * 可扩展Bean的设计会混合一些的固定属性和用一个Map存放的扩展属性。
- * 通常,哪那些是固定属性,哪些是扩展属性,在应用不断演进中是不断变化的。
- * Jackson支持将所有属性都序列化成平行的属性列表,没有固定属性与Map中属性的区别,然后智能的将不在固定列的属性都丢到被@JsonAnyGetter/Setter注释的Map里面去。
- */
- @Test
- public void extensibleBean() {
- // 一个没有区分是变量还是Map的普通JSON字符串.
- String jsonString = "{\"name\" : \"Foobar\",\"age\" : 37,\"occupation\" : \"coder man\"}";
- ExtensibleBean extensibleBean = mapper.fromJson(jsonString, ExtensibleBean.class);
- // 固定属性
- assertEquals("Foobar", extensibleBean.getName());
- assertEquals(null, extensibleBean.getProperties().get("name"));
-
- // 可扩展属性
- assertEquals("coder man", extensibleBean.getProperties().get("occupation"));
- }
-
- /**
- * 演示用的可擴展Bean.@JsonAnySetter与@JsonAnyGetter是关键.
- */
- public static class ExtensibleBean {
- // 固定属性
- private String name;
- // 扩展属性
- private final Map properties = Maps.newHashMap();
-
- public ExtensibleBean() {
- }
-
- @JsonAnySetter
- public void add(String key, String value) {
- properties.put(key, value);
- }
-
- @JsonAnyGetter
- public Map getProperties() {
- return properties;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
- }
-
- /**
- * 同一种POJO,在不同场景下可能需要序列化不同的属性组,Jackson支持使用View来定义.
- */
- @Test
- public void multiViewBean() throws IOException {
- MultiViewBean multiViewBean = new MultiViewBean();
- multiViewBean.setName("Foo");
- multiViewBean.setAge(16);
- multiViewBean.setOtherValue("others");
-
- // public view
- ObjectWriter publicWriter = mapper.getMapper().writerWithView(Views.Public.class);
- assertEquals("{\"name\":\"Foo\",\"otherValue\":\"others\"}", publicWriter.writeValueAsString(multiViewBean));
-
- // internal view
- ObjectWriter internalWriter = mapper.getMapper().writerWithView(Views.Internal.class);
- assertEquals("{\"age\":16,\"otherValue\":\"others\"}", internalWriter.writeValueAsString(multiViewBean));
-
- }
-
- public static class Views {
- static class Public {
- }
-
- static class Internal {
- }
- }
-
- /**
- * 演示序列化不同View不同属性的Bean.
- */
- public static class MultiViewBean {
- private String name;
- private int age;
- private String otherValue;
-
- @JsonView(Views.Public.class)
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- @JsonView(Views.Internal.class)
- public int getAge() {
- return age;
- }
-
- public void setAge(int age) {
- this.age = age;
- }
-
- public String getOtherValue() {
- return otherValue;
- }
-
- public void setOtherValue(String otherValue) {
- this.otherValue = otherValue;
- }
- }
-
- // //自定制行为////
-
- /**
- * 测试自定义转换器,整体感觉稍显复杂。这里是将Money和Long互转.
- */
- @Test
- public void customConverter() {
-
- JsonMapper newMapper = JsonMapper.nonEmptyMapper();
-
- SimpleModule moneyModule = new SimpleModule("MoneyModule");
- moneyModule.addSerializer(new MoneySerializer());
- moneyModule.addDeserializer(Money.class, new MoneyDeserializer());
- newMapper.getMapper().registerModule(moneyModule);
-
- // tojson
- User user = new User();
- user.setName("foo");
- user.setSalary(new Money(1.2));
-
- String jsonString = newMapper.toJson(user);
-
- assertEquals("{\"name\":\"foo\",\"salary\":\"1.2\"}", jsonString);
-
- // from
- User resultUser = newMapper.fromJson(jsonString, User.class);
- assertEquals(Double.valueOf(1.2), resultUser.getSalary().value);
-
- }
-
- public class MoneySerializer extends StdSerializer {
- public MoneySerializer() {
- super(Money.class);
- }
-
- @Override
- public void serialize(Money value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
-
- jgen.writeString(value.toString());
- }
- }
-
- public class MoneyDeserializer extends StdDeserializer {
- public MoneyDeserializer() {
- super(Money.class);
- }
-
- @Override
- public Money deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
- return Money.valueOf(jp.getText());
- }
-
- }
-
- public static class Money {
- private final Double value;
-
- public Money(Double value) {
- this.value = value;
- }
-
- public static Money valueOf(String value) {
- Double srcValue = Double.valueOf(value);
- return new Money(srcValue);
- }
-
- @Override
- public String toString() {
- return value.toString();
- }
- }
-
- /**
- * 包含Money属性的对象.
- */
- public static class User {
- private String name;
- private Money salary;
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public Money getSalary() {
- return salary;
- }
-
- public void setSalary(Money salary) {
- this.salary = salary;
- }
-
- }
-
- /**
- * 测试修改 属性名策略。
- */
- @Test
- public void customPropertyNaming() throws JsonMappingException {
-
- TestBean bean = new TestBean("foo");
- bean.setDefaultValue("bar");
- JsonMapper newMapper = JsonMapper.nonEmptyMapper();
- newMapper.getMapper().setPropertyNamingStrategy(new LowerCaseNaming());
- String jsonpString = newMapper.toJson(bean);
- assertEquals("{\"name\":\"foo\",\"defaultvalue\":\"bar\"}", jsonpString);
- }
-
- public static class LowerCaseNaming extends PropertyNamingStrategy {
- @Override
- public String nameForGetterMethod(MapperConfig> config, AnnotatedMethod method, String defaultName) {
- return defaultName.toLowerCase();
- }
- }
-}
\ No newline at end of file
diff --git a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/utilities/string/StringDemo.java b/examples/showcase/src/main/java/org/springside/examples/showcase/demos/utilities/string/StringDemo.java
deleted file mode 100644
index 4f79b407e..000000000
--- a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/utilities/string/StringDemo.java
+++ /dev/null
@@ -1,126 +0,0 @@
-package org.springside.examples.showcase.demos.utilities.string;
-
-import static org.junit.Assert.*;
-
-import java.util.List;
-import java.util.Map;
-
-import org.apache.commons.lang3.StringUtils;
-import org.junit.Test;
-
-import com.google.common.base.CaseFormat;
-import com.google.common.base.Joiner;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-
-/**
- * 演示Apache Commons Lang3的StringUtils 和 Guava的Joiner和Spliter。
- *
- * Apache的StringUtils已提供绝大多数常用的Null Safe的函数,
- * Guava提供的是高级版的Joiner和Spliter,Case Format转换等高级函数.
- *
- * @author calvin
- */
-public class StringDemo {
-
- /**
- * Apache提供的最常用的Null Safe的函数。
- *
- * 另有一些与String一样,但Null Safe的函数,没有一一演示。
- *
- */
- @Test
- public void utilsByApache() {
- // 判断非空,最常用函数
- assertFalse(StringUtils.isNotBlank(null));
- assertFalse(StringUtils.isNotBlank(""));
- assertFalse(StringUtils.isNotBlank(" "));
-
- // null的default值
- assertEquals("", StringUtils.defaultString(null));
- assertEquals("defaultStr", StringUtils.defaultString(null, "defaultStr"));
- assertEquals("defaultStr", StringUtils.defaultIfBlank(null, "defaultStr"));
- assertEquals("defaultStr", StringUtils.defaultIfBlank(" ", "defaultStr"));
-
- // 截取字符串
- String input = "hahakaka";
- String result = StringUtils.substringAfter(input, "ha");
- assertEquals("hakaka", result);
-
- result = StringUtils.substringAfterLast(input, "ha");
- assertEquals("kaka", result);
-
- assertEquals("haha", StringUtils.substringBetween("'haha'", "'"));
- assertEquals("haha", StringUtils.substringBetween("{haha}", "{", "}"));
-
- // join
- List inputList = Lists.newArrayList("a", "b", "c");
- result = StringUtils.join(inputList, ",");
- assertEquals("a,b,c", result);
-
- // ignoreCase的比较函数:contains/startWith/EndWith/indexOf/lastIndexOf
- assertTrue(StringUtils.containsIgnoreCase("Aaabbb", "aaa"));
- assertEquals(0, StringUtils.indexOfIgnoreCase("Aaabbb", "aaa"));
-
- // /split
- input = "a,b,c";
- String[] resultArray = StringUtils.split(input, ",");
- assertEquals("b", resultArray[1]);
-
- // 左边补0
- result = StringUtils.leftPad("1", 3, '0');
- assertEquals("001", result);
-
- // 超长部分变省略号
- assertEquals("abcdefg", StringUtils.abbreviate("abcdefg", 7));
- assertEquals("abc...", StringUtils.abbreviate("abcdefg", 6));
-
- // 首字母大写
- assertEquals("Abc", StringUtils.capitalize("abc"));
- assertEquals("abc", StringUtils.uncapitalize("Abc"));
- }
-
- /**
- * Guava的高级版Joiner,
- *
- * Splitter的函数与Joiner功能类似,不再演示。
- */
- @Test
- public void joinerByGuava() {
-
- // 忽略Null值。
- String[] fantasyGenres = { "Space Opera", null, "Horror", "Magic realism", null, "Religion" };
- String joined = Joiner.on(", ").skipNulls().join(fantasyGenres);
- assertEquals("Space Opera, Horror, Magic realism, Religion", joined);
-
- // 将Null值转换为特定字符串.
- String[] fantasyGenres2 = { "Space Opera", null, "Horror", "Magic realism", null, "Religion" };
- joined = Joiner.on(", ").useForNull("NULL!!!").join(fantasyGenres2);
- assertEquals("Space Opera, NULL!!!, Horror, Magic realism, NULL!!!, Religion", joined);
-
- // join Map类型
- Map map = Maps.newHashMap();
- map.put(1, "Space Opera");
- map.put(2, "Horror");
- map.put(3, "Magic realism");
- joined = Joiner.on(",").withKeyValueSeparator(":").join(map);
- assertEquals("1:Space Opera,2:Horror,3:Magic realism", joined);
-
- // append一个已存在的字符串
- StringBuilder sb = new StringBuilder("Append StringBulder demo: ");
- joined = Joiner.on(", ").skipNulls().appendTo(sb, fantasyGenres).toString();
- assertEquals("Append StringBulder demo: Space Opera, Horror, Magic realism, Religion", joined);
- }
-
- /**
- * 好玩的CaseFormat转换,在spaceSize->space_size之间转换,比如数据库表名与Java类名,变量名之间的转换。
- */
- @Test
- public void caseFormatByGuava() {
- String name = "SPACE_SIZE";
- assertEquals("SpaceSize", CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, name));
- assertEquals("spaceSize", CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, name));
- assertEquals("space_size", CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_UNDERSCORE, name));
- assertEquals("space-size", CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_HYPHEN, name));
- }
-}
diff --git a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/utilities/time/JodaDemo.java b/examples/showcase/src/main/java/org/springside/examples/showcase/demos/utilities/time/JodaDemo.java
deleted file mode 100644
index 582316578..000000000
--- a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/utilities/time/JodaDemo.java
+++ /dev/null
@@ -1,139 +0,0 @@
-package org.springside.examples.showcase.demos.utilities.time;
-
-import static org.junit.Assert.*;
-
-import java.util.Locale;
-
-import org.joda.time.DateTime;
-import org.joda.time.DateTimeZone;
-import org.joda.time.Years;
-import org.joda.time.format.DateTimeFormat;
-import org.joda.time.format.DateTimeFormatter;
-import org.junit.Test;
-
-public class JodaDemo {
-
- @Test
- public void convertToString() {
- String format = "yyyy-MM-dd HH:mm:ss";
- DateTime fooDate = new DateTime(1978, 6, 1, 12, 10, 8, 0);
- // 第一种方法 直接使用DateTime的toString方法
- System.out.println(fooDate.toString(format));
-
- // 第二种方法,使用Formatter
- DateTimeFormatter fmt = DateTimeFormat.forPattern(format);
- System.out.println(fmt.print(fooDate));
- }
-
- @Test
- public void convertFromString() {
- String dateString = "1978-06-01 12:10:08";
- DateTimeFormatter fmt = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");
- // 第一种方法,直接构造函数,注意日期和时间之间用T分割
- DateTime dt1 = new DateTime("1978-06-01");
- assertEquals(1978, dt1.getYear());
- DateTime dt2 = new DateTime("1978-06-01T12:10:08");
- assertEquals(1978, dt2.getYear());
-
- // 第二种方法,使用Formatter
- DateTime dt3 = fmt.parseDateTime(dateString);
- assertEquals(1978, dt3.getYear());
-
- }
-
- @Test
- public void timeZone() {
-
- System.out.println("演示时区");
-
- String format = "yyyy-MM-dd HH:mm:ss zZZ";
-
- // DateTime的毫秒即System的毫秒,即1970到现在的UTC的毫秒数.
- System.out.println(new DateTime().getMillis() + " " + System.currentTimeMillis());
-
- // 将日期按默认时区打印
- DateTime fooDate = new DateTime(1978, 6, 1, 12, 10, 8, 0);
- System.out.println(fooDate.toString(format) + " " + fooDate.getMillis()); // "1978-06-01 12:10:08"
-
- // 将日期按UTC时区打印
- DateTime zoneWithUTC = fooDate.withZone(DateTimeZone.UTC);
- System.out.println(zoneWithUTC.toString(format) + " " + zoneWithUTC.getMillis());// "1978-06-01 04:10:08",
- // sameMillis
-
- // 按不同的时区分析字符串,得到不同的时间
- String dateString = "1978-06-01 12:10:08";
- DateTimeFormatter fmt = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");
-
- DateTime parserResult1 = fmt.withZone(DateTimeZone.forID("US/Pacific")).parseDateTime(dateString);
- DateTime parserResult2 = fmt.withZoneUTC().parseDateTime(dateString);
-
- System.out.println(parserResult1.toString(format) + " " + parserResult1.getMillis());
- System.out.println(parserResult2.toString(format) + " " + parserResult2.getMillis());
- }
-
- /**
- * 打印当地语言年,月,日到写法
- */
- @Test
- public void locale() {
-
- System.out.println("演示Locale");
-
- DateTime dateTime = new DateTime().withZone(DateTimeZone.UTC);
-
- // 打印中文与英文下不同长度的日期格式串
- System.out.println("S: " + formatDateTime(dateTime, "SS", "zh"));
- System.out.println("M: " + formatDateTime(dateTime, "MM", "zh"));
- System.out.println("L: " + formatDateTime(dateTime, "LL", "zh"));
- System.out.println("XL: " + formatDateTime(dateTime, "FF", "zh"));
- System.out.println("");
-
- System.out.println("S: " + formatDateTime(dateTime, "SS", "en"));
- System.out.println("M: " + formatDateTime(dateTime, "MM", "en"));
- System.out.println("L: " + formatDateTime(dateTime, "LL", "en"));
- System.out.println("XL: " + formatDateTime(dateTime, "FF", "en"));
- System.out.println("");
- System.out.println("");
-
- // 直接打印TimeStamp, 日期是M,时间是L
- DateTimeFormatter formatter = DateTimeFormat.forStyle("ML").withLocale(new Locale("zh"))
- .withZone(DateTimeZone.UTC);
-
- System.out.println("ML Mix: " + formatter.print(dateTime.getMillis()));
-
- // 只打印日期不打印时间
- System.out.println("Date only :" + formatDateTime(dateTime, "M-", "zh"));
-
- }
-
- public static String formatDateTime(DateTime dateTime, String style, String lang) {
- DateTimeFormatter formatter = DateTimeFormat.forStyle(style).withLocale(new Locale(lang));
- return dateTime.toString(formatter);
- }
-
- /**
- * 演示日期的加减以及计算日期间的间隔,可使用任意时间单位进行加减和计算间隔.
- */
- @Test
- public void daysPlusAndMinusBetweenAndBetweenx() {
- DateTime now = new DateTime();
- DateTime birthDate = now.minusYears(10);
- assertEquals(10, Years.yearsBetween(birthDate, new DateTime()).getYears());
- birthDate = now.minusYears(10).plusDays(2);
- assertEquals(9, Years.yearsBetween(birthDate, new DateTime()).getYears());
- }
-
- /**
- * 取得月份的头一天和最后一天. 取得一天的0:00和23:59:59 其他如年,星期的头一天,最后一天同理可证
- */
- @Test
- public void beginAndEndOfDates() {
- String dateString = "1978-06-10T12:10:08";
- DateTime dt = new DateTime(dateString);
- DateTime startOfMonth = dt.dayOfMonth().withMinimumValue().withTimeAtStartOfDay();
- System.out.println(startOfMonth.toString());
-
- DateTime endOfMonth = dt.dayOfMonth().withMaximumValue().millisOfDay().withMaximumValue();
- System.out.println(endOfMonth);
- }
-}
diff --git a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/utilities/validate/ValidateDemo.java b/examples/showcase/src/main/java/org/springside/examples/showcase/demos/utilities/validate/ValidateDemo.java
deleted file mode 100644
index f0a2381bc..000000000
--- a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/utilities/validate/ValidateDemo.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package org.springside.examples.showcase.demos.utilities.validate;
-
-import static org.junit.Assert.*;
-
-import java.util.List;
-
-import org.apache.commons.lang3.Validate;
-import org.junit.Assert;
-import org.junit.Test;
-
-import com.google.common.collect.Lists;
-
-/**
- * 演示用Apache Commons3的Validate,在代码中进行防御性校验.
- *
- * @author calvin
- */
-public class ValidateDemo {
-
- @Test
- public void asserts() {
-
- // not null Object
- try {
- String parameter = "abc";
-
- Validate.notNull(parameter);
-
- // 检验not null,用默认出错信息.
- Validate.notNull(null);
- Assert.fail();
- } catch (NullPointerException e) {
- assertEquals("The validated object is null", e.getMessage());
- }
-
- // notBlank String
- try {
- String parameter = "abc";
- // 可选择将输入参数赋值到新变量
- String result = Validate.notBlank(parameter);
- assertEquals("abc", result);
-
- // 检验not null,用自定义出错信息.
- Validate.notBlank("", "The name must not be blank");
- Assert.fail();
-
- } catch (IllegalArgumentException e) {
- assertEquals("The name must not be blank", e.getMessage());
- }
-
- // notEmpty Collection
- try {
- List parameter = Lists.newArrayList();
- Validate.notEmpty(parameter);
- Assert.fail();
- } catch (IllegalArgumentException e) {
- assertEquals("The validated collection is empty", e.getMessage());
- }
-
- // is true
- try {
- // 出錯信息可格式化參數
- Validate.isTrue(1 == 3, "Message %s", "foo");
- Assert.fail();
- } catch (IllegalArgumentException e) {
- assertEquals("Message foo", e.getMessage());
- }
- }
-}
diff --git a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/utilities/xml/HouseMapAdapter.java b/examples/showcase/src/main/java/org/springside/examples/showcase/demos/utilities/xml/HouseMapAdapter.java
deleted file mode 100644
index a91048a00..000000000
--- a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/utilities/xml/HouseMapAdapter.java
+++ /dev/null
@@ -1,80 +0,0 @@
-package org.springside.examples.showcase.demos.utilities.xml;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-import javax.xml.bind.annotation.XmlAttribute;
-import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlType;
-import javax.xml.bind.annotation.XmlValue;
-import javax.xml.bind.annotation.adapters.XmlAdapter;
-
-import org.springside.examples.showcase.demos.utilities.xml.HouseMapAdapter.HouseMap.HouseEntry;
-
-import com.google.common.collect.Maps;
-
-/**
- * 为使Map houses转化为有业务意义的xml的巨大努力,
- * 分别定义了一个Adapter--HouseMapAdapter, 一个List Wrapper类--HouseMap, 一个MapEntry表达类--HouseEntry.
- * 最后的劳动成果是:
- *
- *
- *
- * house1
- * house2
- *
- *
- *
- * @author calvin
- */
-public class HouseMapAdapter extends XmlAdapter> {
-
- @Override
- public HouseMap marshal(Map map) throws Exception {
- HouseMap houseMap = new HouseMap();
- for (Map.Entry e : map.entrySet()) {
- houseMap.entries.add(new HouseEntry(e));
- }
- return houseMap;
- }
-
- @Override
- public Map unmarshal(HouseMap houseMap) throws Exception {
- Map map = Maps.newLinkedHashMap();
- for (HouseEntry e : houseMap.entries) {
- map.put(e.key, e.value);
- }
- return map;
- }
-
- /**
- * List的Adapter类.
- *
- * @author calvin
- */
- @XmlType(name = "houses")
- public static class HouseMap {
- @XmlElement(name = "house")
- List entries = new ArrayList();
-
- /**
- * HouseMap中的Entry类.
- */
- static class HouseEntry {
- @XmlAttribute
- String key;
-
- @XmlValue
- String value;
-
- public HouseEntry() {
- }
-
- public HouseEntry(Map.Entry e) {
- key = e.getKey();
- value = e.getValue();
- }
- }
- }
-}
\ No newline at end of file
diff --git a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/utilities/xml/JaxbDemo.java b/examples/showcase/src/main/java/org/springside/examples/showcase/demos/utilities/xml/JaxbDemo.java
deleted file mode 100644
index b5c7e1f79..000000000
--- a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/utilities/xml/JaxbDemo.java
+++ /dev/null
@@ -1,150 +0,0 @@
-package org.springside.examples.showcase.demos.utilities.xml;
-
-import static org.junit.Assert.*;
-
-import java.util.List;
-
-import org.dom4j.Document;
-import org.dom4j.DocumentException;
-import org.dom4j.DocumentHelper;
-import org.dom4j.Element;
-import org.junit.Test;
-import org.springside.modules.mapper.JaxbMapper;
-
-import com.google.common.collect.Lists;
-
-/**
- * 演示基于JAXB2.0的Java对象-XML转换及Dom4j的使用.
- *
- * 演示用xml如下:
- *
- *
- *
- *
- * calvin
- *
- *
- *
- *
- *
- * movie
- * sports
- *
- *
- * house1
- * house2
- *
- *
- *
- */
-public class JaxbDemo {
-
- @Test
- public void objectToXml() {
- User user = new User();
- user.setId(1L);
- user.setName("calvin");
-
- user.getRoles().add(new Role(1L, "admin"));
- user.getRoles().add(new Role(2L, "user"));
- user.getInterests().add("movie");
- user.getInterests().add("sports");
-
- user.getHouses().put("bj", "house1");
- user.getHouses().put("gz", "house2");
-
- String xml = JaxbMapper.toXml(user, "UTF-8");
- System.out.println("Jaxb Object to Xml result:\n" + xml);
- assertXmlByDom4j(xml);
- }
-
- @Test
- public void xmlToObject() {
- String xml = generateXmlByDom4j();
- User user = JaxbMapper.fromXml(xml, User.class);
-
- System.out.println("Jaxb Xml to Object result:\n" + user);
-
- assertEquals(Long.valueOf(1L), user.getId());
- assertEquals(2, user.getRoles().size());
- assertEquals("admin", user.getRoles().get(0).getName());
-
- assertEquals(2, user.getInterests().size());
- assertEquals("movie", user.getInterests().get(0));
-
- assertEquals(2, user.getHouses().size());
- assertEquals("house1", user.getHouses().get("bj"));
- }
-
- /**
- * 测试以List对象作为根节点时的XML输出
- */
- @Test
- public void toXmlWithListAsRoot() {
- User user1 = new User();
- user1.setId(1L);
- user1.setName("calvin");
-
- User user2 = new User();
- user2.setId(2L);
- user2.setName("kate");
-
- List userList = Lists.newArrayList(user1, user2);
-
- String xml = JaxbMapper.toXml(userList, "userList", User.class, "UTF-8");
- System.out.println("Jaxb Object List to Xml result:\n" + xml);
- }
-
- /**
- * 使用Dom4j生成测试用的XML文档字符串.
- */
- private static String generateXmlByDom4j() {
- Document document = DocumentHelper.createDocument();
-
- Element root = document.addElement("user").addAttribute("id", "1");
-
- root.addElement("name").setText("calvin");
-
- // List
- Element roles = root.addElement("roles");
- roles.addElement("role").addAttribute("id", "1").addAttribute("name", "admin");
- roles.addElement("role").addAttribute("id", "2").addAttribute("name", "user");
-
- // List
- Element interests = root.addElement("interests");
- interests.addElement("interest").addText("movie");
- interests.addElement("interest").addText("sports");
-
- // Map
- Element houses = root.addElement("houses");
- houses.addElement("house").addAttribute("key", "bj").addText("house1");
- houses.addElement("house").addAttribute("key", "gz").addText("house2");
-
- return document.asXML();
- }
-
- /**
- * 使用Dom4j验证Jaxb所生成XML的正确性.
- */
- private static void assertXmlByDom4j(String xml) {
- Document doc = null;
- try {
- doc = DocumentHelper.parseText(xml);
- } catch (DocumentException e) {
- fail(e.getMessage());
- }
- Element user = doc.getRootElement();
- assertEquals("1", user.attribute("id").getValue());
-
- Element adminRole = (Element) doc.selectSingleNode("//roles/role[@id=1]");
- assertEquals(2, adminRole.getParent().elements().size());
- assertEquals("admin", adminRole.attribute("name").getValue());
-
- Element interests = (Element) doc.selectSingleNode("//interests");
- assertEquals(2, interests.elements().size());
- assertEquals("movie", ((Element) interests.elements().get(0)).getText());
-
- Element house1 = (Element) doc.selectSingleNode("//houses/house[@key='bj']");
- assertEquals("house1", house1.getText());
- }
-}
diff --git a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/utilities/xml/Role.java b/examples/showcase/src/main/java/org/springside/examples/showcase/demos/utilities/xml/Role.java
deleted file mode 100644
index 9209ae2fa..000000000
--- a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/utilities/xml/Role.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package org.springside.examples.showcase.demos.utilities.xml;
-
-import javax.xml.bind.annotation.XmlAttribute;
-
-import org.apache.commons.lang3.builder.ToStringBuilder;
-
-/**
- * 使用JAXB2.0标注的待转换Java Bean.
- */
-public class Role {
- private Long id;
- private String name;
-
- public Role() {
- }
-
- public Role(Long id, String name) {
- this.id = id;
- this.name = name;
- }
-
- @XmlAttribute
- public Long getId() {
- return id;
- }
-
- public void setId(Long id) {
- this.id = id;
- }
-
- @XmlAttribute
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- @Override
- public String toString() {
- return ToStringBuilder.reflectionToString(this);
- }
-}
diff --git a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/utilities/xml/User.java b/examples/showcase/src/main/java/org/springside/examples/showcase/demos/utilities/xml/User.java
deleted file mode 100644
index 9c5b9a995..000000000
--- a/examples/showcase/src/main/java/org/springside/examples/showcase/demos/utilities/xml/User.java
+++ /dev/null
@@ -1,100 +0,0 @@
-package org.springside.examples.showcase.demos.utilities.xml;
-
-import java.util.List;
-import java.util.Map;
-
-import javax.xml.bind.annotation.XmlAttribute;
-import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlElementWrapper;
-import javax.xml.bind.annotation.XmlRootElement;
-import javax.xml.bind.annotation.XmlTransient;
-import javax.xml.bind.annotation.XmlType;
-import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
-
-import org.apache.commons.lang3.builder.ToStringBuilder;
-
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-
-/**
- * 使用JAXB2.0标注的待转换Java Bean.
- */
-// 根节点
-@XmlRootElement
-// 指定子节点的顺序
-@XmlType(propOrder = { "name", "roles", "interests", "houses" })
-public class User {
-
- private Long id;
- private String name;
- private String password;
-
- private List roles = Lists.newArrayList();
- private List interests = Lists.newArrayList();
- private Map houses = Maps.newHashMap();
-
- // 设置转换为xml节点中的属性
- @XmlAttribute
- public Long getId() {
- return id;
- }
-
- public void setId(Long id) {
- this.id = id;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- // 设置不转换为xml
- @XmlTransient
- public String getPassword() {
- return password;
- }
-
- public void setPassword(String password) {
- this.password = password;
- }
-
- // 设置对List