我是不熟悉Web服务的新手,并且有新手q'。我已经创建了一个rest类,并希望使用helper类来处理某些操作。因此,例如,我创建了以下服务:
/*! rangeslider.js - v2.3.0 | (c) 2016 @andreruffert | MIT license | https://github.com/andreruffert/rangeslider.js */
(function(factory) {
'use strict';
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['jquery'],factory);
} else if (typeof exports === 'object') {
// CommonJS
module.exports = factory(require('jquery'));
} else {
// Browser globals
factory(jQuery);
}
}(function($) {
'use strict';
// Polyfill Number.isnaN(value)
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isnaN
Number.isnaN = Number.isnaN || function(value) {
return typeof value === 'number' && value !== value;
};
/**
* Range feature detection
* @return {Boolean}
*/
function supportsrange() {
var input = document.createElement('input');
input.setattribute('type','range');
return input.type !== 'text';
}
var pluginName = 'rangeslider',pluginIdentifier = 0,hasInputRangeSupport = supportsrange(),defaults = {
polyfill: true,orientation: 'horizontal',rangeclass: 'rangeslider',disabledClass: 'rangeslider--disabled',activeclass: 'rangeslider--active',horizontalClass: 'rangeslider--horizontal',verticalClass: 'rangeslider--vertical',fillClass: 'rangeslider__fill',handleclass: 'rangeslider__handle',startEvent: ['mousedown','touchstart','pointerdown'],moveEvent: ['mousemove','touchmove','pointermove'],endEvent: ['mouseup','touchend','pointerup']
},constants = {
orientation: {
horizontal: {
dimension: 'width',direction: 'left',directionStyle: 'left',coordinate: 'x'
},vertical: {
dimension: 'height',direction: 'top',directionStyle: 'bottom',coordinate: 'y'
}
}
};
/**
* Delays a function for the given number of milliseconds,and then calls
* it with the arguments supplied.
*
* @param {Function} fn [description]
* @param {Number} wait [description]
* @return {Function}
*/
function delay(fn,wait) {
var args = Array.prototype.slice.call(arguments,2);
return setTimeout(function(){ return fn.apply(null,args); },wait);
}
/**
* Returns a debounced function that will make sure the given
* function is not triggered too much.
*
* @param {Function} fn Function to debounce.
* @param {Number} debounceDuration OPTIONAL. The amount of time in milliseconds for which we will debounce the function. (defaults to 100ms)
* @return {Function}
*/
function debounce(fn,debounceDuration) {
debounceDuration = debounceDuration || 100;
return function() {
if (!fn.debouncing) {
var args = Array.prototype.slice.apply(arguments);
fn.lastReturnVal = fn.apply(window,args);
fn.debouncing = true;
}
clearTimeout(fn.debounceTimeout);
fn.debounceTimeout = setTimeout(function(){
fn.debouncing = false;
},debounceDuration);
return fn.lastReturnVal;
};
}
/**
* Check if a `element` is visible in the DOM
*
* @param {Element} element
* @return {Boolean}
*/
function isHidden(element) {
return (
element && (
element.offsetWidth === 0 ||
element.offsetHeight === 0 ||
// Also Consider native `<details>` elements.
element.open === false
)
);
}
/**
* Get hidden parentNodes of an `element`
*
* @param {Element} element
* @return {[type]}
*/
function getHiddenParentNodes(element) {
var parents = [],node = element.parentNode;
while (isHidden(node)) {
parents.push(node);
node = node.parentNode;
}
return parents;
}
/**
* Returns dimensions for an element even if it is not visible in the DOM.
*
* @param {Element} element
* @param {String} key (e.g. offsetWidth …)
* @return {Number}
*/
function getDimension(element,key) {
var hiddenParentNodes = getHiddenParentNodes(element),hiddenParentNodesLength = hiddenParentNodes.length,inlinestyle = [],dimension = element[key];
// Used for native `<details>` elements
function toggleOpenProperty(element) {
if (typeof element.open !== 'undefined') {
element.open = (element.open) ? false : true;
}
}
if (hiddenParentNodesLength) {
for (var i = 0; i < hiddenParentNodesLength; i++) {
// Cache style attribute to restore it later.
inlinestyle[i] = hiddenParentNodes[i].style.cssText;
// visually hide
if (hiddenParentNodes[i].style.setProperty) {
hiddenParentNodes[i].style.setProperty('display','block','important');
} else {
hiddenParentNodes[i].style.cssText += ';display: block !important';
}
hiddenParentNodes[i].style.height = '0';
hiddenParentNodes[i].style.overflow = 'hidden';
hiddenParentNodes[i].style.visibility = 'hidden';
toggleOpenProperty(hiddenParentNodes[i]);
}
// Update dimension
dimension = element[key];
for (var j = 0; j < hiddenParentNodesLength; j++) {
// Restore the style attribute
hiddenParentNodes[j].style.cssText = inlinestyle[j];
toggleOpenProperty(hiddenParentNodes[j]);
}
}
return dimension;
}
/**
* Returns the parsed float or the default if it failed.
*
* @param {String} str
* @param {Number} defaultvalue
* @return {Number}
*/
function tryParseFloat(str,defaultvalue) {
var value = parseFloat(str);
return Number.isnaN(value) ? defaultvalue : value;
}
/**
* Capitalize the first letter of string
*
* @param {String} str
* @return {String}
*/
function ucfirst(str) {
return str.charAt(0).toUpperCase() + str.substr(1);
}
/**
* Plugin
* @param {String} element
* @param {Object} options
*/
function Plugin(element,options) {
this.$window = $(window);
this.$document = $(document);
this.$element = $(element);
this.options = $.extend( {},defaults,options );
this.polyfill = this.options.polyfill;
this.orientation = this.$element[0].getattribute('data-orientation') || this.options.orientation;
this.onInit = this.options.onInit;
this.onSlide = this.options.onSlide;
this.onSlideEnd = this.options.onSlideEnd;
this.DIMENSION = constants.orientation[this.orientation].dimension;
this.DIRECTION = constants.orientation[this.orientation].direction;
this.DIRECTION_STYLE = constants.orientation[this.orientation].directionStyle;
this.COORDINATE = constants.orientation[this.orientation].coordinate;
// Plugin should only be used as a polyfill
if (this.polyfill) {
// Input range support?
if (hasInputRangeSupport) { return false; }
}
this.identifier = 'js-' + pluginName + '-' +(pluginIdentifier++);
this.startEvent = this.options.startEvent.join('.' + this.identifier + ' ') + '.' + this.identifier;
this.moveEvent = this.options.moveEvent.join('.' + this.identifier + ' ') + '.' + this.identifier;
this.endEvent = this.options.endEvent.join('.' + this.identifier + ' ') + '.' + this.identifier;
this.toFixed = (this.step + '').replace('.','').length - 1;
this.$fill = $('<div class="' + this.options.fillClass + '" />');
this.$handle = $('<div class="' + this.options.handleclass + '" />');
this.$range = $('<div class="' + this.options.rangeclass + ' ' + this.options[this.orientation + 'Class'] + '" id="' + this.identifier + '" />').insertAfter(this.$element).prepend(this.$fill,this.$handle);
// visually hide the input
this.$element.css({
'position': 'absolute','width': '1px','height': '1px','overflow': 'hidden','opacity': '0'
});
// Store context
this.handleDown = $.proxy(this.handleDown,this);
this.handleMove = $.proxy(this.handleMove,this);
this.handleEnd = $.proxy(this.handleEnd,this);
this.init();
// Attach Events
var _this = this;
this.$window.on('resize.' + this.identifier,debounce(function() {
// Simulate resizeEnd event.
delay(function() { _this.update(false,false); },300);
},20));
this.$document.on(this.startEvent,'#' + this.identifier + ':not(.' + this.options.disabledClass + ')',this.handleDown);
// Listen to programmatic value changes
this.$element.on('change.' + this.identifier,function(e,data) {
if (data && data.origin === _this.identifier) {
return;
}
var value = e.target.value,pos = _this.getPositionFromValue(value);
_this.setPosition(pos);
});
}
Plugin.prototype.init = function() {
this.update(true,false);
if (this.onInit && typeof this.onInit === 'function') {
this.onInit();
}
};
Plugin.prototype.update = function(updateAttributes,triggerSlide) {
updateAttributes = updateAttributes || false;
if (updateAttributes) {
this.min = tryParseFloat(this.$element[0].getattribute('min'),0);
this.max = tryParseFloat(this.$element[0].getattribute('max'),100);
this.value = tryParseFloat(this.$element[0].value,Math.round(this.min + (this.max-this.min)/2));
this.step = tryParseFloat(this.$element[0].getattribute('step'),1);
}
this.handleDimension = getDimension(this.$handle[0],'offset' + ucfirst(this.DIMENSION));
this.rangeDimension = getDimension(this.$range[0],'offset' + ucfirst(this.DIMENSION));
this.maxHandlePos = this.rangeDimension - this.handleDimension;
this.grabPos = this.handleDimension / 2;
this.position = this.getPositionFromValue(this.value);
// Consider disabled state
if (this.$element[0].disabled) {
this.$range.addClass(this.options.disabledClass);
} else {
this.$range.removeclass(this.options.disabledClass);
}
this.setPosition(this.position,triggerSlide);
};
Plugin.prototype.handleDown = function(e) {
e.preventDefault();
this.$document.on(this.moveEvent,this.handleMove);
this.$document.on(this.endEvent,this.handleEnd);
// add active class because Firefox is ignoring
// the handle:active pseudo selector because of `e.preventDefault();`
this.$range.addClass(this.options.activeclass);
// If we click on the handle don't set the new position
if ((' ' + e.target.classname + ' ').replace(/[\n\t]/g,' ').indexOf(this.options.handleclass) > -1) {
return;
}
var pos = this.getRelativePosition(e),rangePos = this.$range[0].getBoundingClientRect()[this.DIRECTION],handlePos = this.getPositionFromNode(this.$handle[0]) - rangePos,setPos = (this.orientation === 'vertical') ? (this.maxHandlePos - (pos - this.grabPos)) : (pos - this.grabPos);
this.setPosition(setPos);
if (pos >= handlePos && pos < handlePos + this.handleDimension) {
this.grabPos = pos - handlePos;
}
};
Plugin.prototype.handleMove = function(e) {
e.preventDefault();
var pos = this.getRelativePosition(e);
var setPos = (this.orientation === 'vertical') ? (this.maxHandlePos - (pos - this.grabPos)) : (pos - this.grabPos);
this.setPosition(setPos);
};
Plugin.prototype.handleEnd = function(e) {
e.preventDefault();
this.$document.off(this.moveEvent,this.handleMove);
this.$document.off(this.endEvent,this.handleEnd);
this.$range.removeclass(this.options.activeclass);
// Ok we're done fire the change event
this.$element.trigger('change',{ origin: this.identifier });
if (this.onSlideEnd && typeof this.onSlideEnd === 'function') {
this.onSlideEnd(this.position,this.value);
}
};
Plugin.prototype.cap = function(pos,min,max) {
if (pos < min) { return min; }
if (pos > max) { return max; }
return pos;
};
Plugin.prototype.setPosition = function(pos,triggerSlide) {
var value,newPos;
if (triggerSlide === undefined) {
triggerSlide = true;
}
// snapping steps
value = this.getvalueFromPosition(this.cap(pos,this.maxHandlePos));
newPos = this.getPositionFromValue(value);
// Update ui
this.$fill[0].style[this.DIMENSION] = (newPos + this.grabPos) + 'px';
this.$handle[0].style[this.DIRECTION_STYLE] = newPos + 'px';
this.setvalue(value);
// Update globals
this.position = newPos;
this.value = value;
if (triggerSlide && this.onSlide && typeof this.onSlide === 'function') {
this.onSlide(newPos,value);
}
};
// Returns element position relative to the parent
Plugin.prototype.getPositionFromNode = function(node) {
var i = 0;
while (node !== null) {
i += node.offsetLeft;
node = node.offsetParent;
}
return i;
};
Plugin.prototype.getRelativePosition = function(e) {
// Get the offset DIRECTION relative to the viewport
var ucCoordinate = ucfirst(this.COORDINATE),rangePos = this.$range[0].getBoundingClientRect()[this.DIRECTION],pageCoordinate = 0;
if (typeof e.originalEvent['client' + ucCoordinate] !== 'undefined') {
pageCoordinate = e.originalEvent['client' + ucCoordinate];
}
else if (
e.originalEvent.touches &&
e.originalEvent.touches[0] &&
typeof e.originalEvent.touches[0]['client' + ucCoordinate] !== 'undefined'
) {
pageCoordinate = e.originalEvent.touches[0]['client' + ucCoordinate];
}
else if(e.currentPoint && typeof e.currentPoint[this.COORDINATE] !== 'undefined') {
pageCoordinate = e.currentPoint[this.COORDINATE];
}
return pageCoordinate - rangePos;
};
Plugin.prototype.getPositionFromValue = function(value) {
var percentage,pos;
percentage = (value - this.min)/(this.max - this.min);
pos = (!Number.isnaN(percentage)) ? percentage * this.maxHandlePos : 0;
return pos;
};
Plugin.prototype.getvalueFromPosition = function(pos) {
var percentage,value;
percentage = ((pos) / (this.maxHandlePos || 1));
value = this.step * Math.round(percentage * (this.max - this.min) / this.step) + this.min;
return Number((value).toFixed(this.toFixed));
};
Plugin.prototype.setvalue = function(value) {
if (value === this.value && this.$element[0].value !== '') {
return;
}
// Set the new value and fire the `input` event
this.$element
.val(value)
.trigger('input',{ origin: this.identifier });
};
Plugin.prototype.destroy = function() {
this.$document.off('.' + this.identifier);
this.$window.off('.' + this.identifier);
this.$element
.off('.' + this.identifier)
.removeAttr('style')
.removeData('plugin_' + pluginName);
// Remove the generated markup
if (this.$range && this.$range.length) {
this.$range[0].parentNode.removeChild(this.$range[0]);
}
};
// A really lightweight plugin wrapper around the constructor,// preventing against multiple instantiations
$.fn[pluginName] = function(options) {
var args = Array.prototype.slice.call(arguments,1);
return this.each(function() {
var $this = $(this),data = $this.data('plugin_' + pluginName);
// Create a new instance.
if (!data) {
$this.data('plugin_' + pluginName,(data = new Plugin(this,options)));
}
// Make it possible to access methods from public.
// e.g `$element.rangeslider('method');`
if (typeof options === 'string') {
data[options].apply(data,args);
}
});
};
return 'rangeslider.js is available in jQuery context e.g $(selector).rangeslider(options);';
}));
关于这种方法,我有几个问题:
这是实例化助手类的正确方法吗?还是应该创建一个构造函数并在那里实例化该类?例如:
import statements...
@Path("/UserResources")
public class UserResource {
//Create Spring application context
static ClasspathXmlApplicationContext ctx = new
ClasspathXmlApplicationContext("classpath:/spring.xml");
private UserResourceHelper urh = new UserResourceHelper(); // this is the helper
class UserProfileService userProfileService = ctx.getBean(UserProfileService.class);
@POST
@Path("/createUser")
@Consumes(MediaType.APPLICATION_JSON)
public Response createUser(@Context HttpServletRequest request,Object object) {
StringBuffer sb = new StringBuffer();
User user = userProfileService.findByPrimaryKey(object);
sb.append(urh.createUser(object));
return
Response.status(Status.CREATED.getStatusCode()).entity(result.toString()).build(); } }
在这种方法下,总是会有UserResourceHelper的新实例吗?
如果这样的话,这意味着并发正确不会有问题吗?即。 2个请求同时进入,而createUser方法接收到的第一个对象会突然被突然出现的第二个对象代替?
我正在将Hibernate用于ORM。按照我的代码示例实例化实体的方式是否正确?
感谢您的协助!