").append( jQuery.parseHTML( responseText ) ).find( selector ) :
// Otherwise use the full result
responseText );
}).complete( callback && function( jqXHR, status ) {
self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );
});
}
return this;
};
jQuery.expr.filters.animated = function( elem ) {
return jQuery.grep(jQuery.timers, function( fn ) {
return elem === fn.elem;
}).length;
};
var docElem = window.document.documentElement;
/**
* Gets a window from an element
*/
function getWindow( elem ) {
return jQuery.isWindow( elem ) ?
elem :
elem.nodeType === 9 ?
elem.defaultView || elem.parentWindow :
false;
}
jQuery.offset = {
setOffset: function( elem, options, i ) {
var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,
position = jQuery.css( elem, "position" ),
curElem = jQuery( elem ),
props = {};
// set position first, in-case top/left are set even on static elem
if ( position === "static" ) {
elem.style.position = "relative";
}
curOffset = curElem.offset();
curCSSTop = jQuery.css( elem, "top" );
curCSSLeft = jQuery.css( elem, "left" );
calculatePosition = ( position === "absolute" || position === "fixed" ) &&
jQuery.inArray("auto", [ curCSSTop, curCSSLeft ] ) > -1;
// need to be able to calculate position if either top or left is auto and position is either absolute or fixed
if ( calculatePosition ) {
curPosition = curElem.position();
curTop = curPosition.top;
curLeft = curPosition.left;
} else {
curTop = parseFloat( curCSSTop ) || 0;
curLeft = parseFloat( curCSSLeft ) || 0;
}
if ( jQuery.isFunction( options ) ) {
options = options.call( elem, i, curOffset );
}
if ( options.top != null ) {
props.top = ( options.top - curOffset.top ) + curTop;
}
if ( options.left != null ) {
props.left = ( options.left - curOffset.left ) + curLeft;
}
if ( "using" in options ) {
options.using.call( elem, props );
} else {
curElem.css( props );
}
}
};
jQuery.fn.extend({
offset: function( options ) {
if ( arguments.length ) {
return options === undefined ?
this :
this.each(function( i ) {
jQuery.offset.setOffset( this, options, i );
});
}
var docElem, win,
box = { top: 0, left: 0 },
elem = this[ 0 ],
doc = elem && elem.ownerDocument;
if ( !doc ) {
return;
}
docElem = doc.documentElement;
// Make sure it's not a disconnected DOM node
if ( !jQuery.contains( docElem, elem ) ) {
return box;
}
// If we don't have gBCR, just use 0,0 rather than error
// BlackBerry 5, iOS 3 (original iPhone)
if ( typeof elem.getBoundingClientRect !== strundefined ) {
box = elem.getBoundingClientRect();
}
win = getWindow( doc );
return {
top: box.top + ( win.pageYOffset || docElem.scrollTop ) - ( docElem.clientTop || 0 ),
left: box.left + ( win.pageXOffset || docElem.scrollLeft ) - ( docElem.clientLeft || 0 )
};
},
position: function() {
if ( !this[ 0 ] ) {
return;
}
var offsetParent, offset,
parentOffset = { top: 0, left: 0 },
elem = this[ 0 ];
// fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is its only offset parent
if ( jQuery.css( elem, "position" ) === "fixed" ) {
// we assume that getBoundingClientRect is available when computed position is fixed
offset = elem.getBoundingClientRect();
} else {
// Get *real* offsetParent
offsetParent = this.offsetParent();
// Get correct offsets
offset = this.offset();
if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) {
parentOffset = offsetParent.offset();
}
// Add offsetParent borders
parentOffset.top += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true );
parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true );
}
// Subtract parent offsets and element margins
// note: when an element has margin: auto the offsetLeft and marginLeft
// are the same in Safari causing offset.left to incorrectly be 0
return {
top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true)
};
},
offsetParent: function() {
return this.map(function() {
var offsetParent = this.offsetParent || docElem;
while ( offsetParent && ( !jQuery.nodeName( offsetParent, "html" ) && jQuery.css( offsetParent, "position" ) === "static" ) ) {
offsetParent = offsetParent.offsetParent;
}
return offsetParent || docElem;
});
}
});
// Create scrollLeft and scrollTop methods
jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) {
var top = /Y/.test( prop );
jQuery.fn[ method ] = function( val ) {
return access( this, function( elem, method, val ) {
var win = getWindow( elem );
if ( val === undefined ) {
return win ? (prop in win) ? win[ prop ] :
win.document.documentElement[ method ] :
elem[ method ];
}
if ( win ) {
win.scrollTo(
!top ? val : jQuery( win ).scrollLeft(),
top ? val : jQuery( win ).scrollTop()
);
} else {
elem[ method ] = val;
}
}, method, val, arguments.length, null );
};
});
// Add the top/left cssHooks using jQuery.fn.position
// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
// getComputedStyle returns percent when specified for top/left/bottom/right
// rather than make the css module depend on the offset module, we just check for it here
jQuery.each( [ "top", "left" ], function( i, prop ) {
jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,
function( elem, computed ) {
if ( computed ) {
computed = curCSS( elem, prop );
// if curCSS returns percentage, fallback to offset
return rnumnonpx.test( computed ) ?
jQuery( elem ).position()[ prop ] + "px" :
computed;
}
}
);
});
// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) {
// margin is only for outerHeight, outerWidth
jQuery.fn[ funcName ] = function( margin, value ) {
var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
return access( this, function( elem, type, value ) {
var doc;
if ( jQuery.isWindow( elem ) ) {
// As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there
// isn't a whole lot we can do. See pull request at this URL for discussion:
// https://github.com/jquery/jquery/pull/764
return elem.document.documentElement[ "client" + name ];
}
// Get document width or height
if ( elem.nodeType === 9 ) {
doc = elem.documentElement;
// Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], whichever is greatest
// unfortunately, this causes bug #3838 in IE6/8 only, but there is currently no good, small way to fix it.
return Math.max(
elem.body[ "scroll" + name ], doc[ "scroll" + name ],
elem.body[ "offset" + name ], doc[ "offset" + name ],
doc[ "client" + name ]
);
}
return value === undefined ?
// Get width or height on the element, requesting but not forcing parseFloat
jQuery.css( elem, type, extra ) :
// Set width or height on the element
jQuery.style( elem, type, value, extra );
}, type, chainable ? margin : undefined, chainable, null );
};
});
});
// The number of elements contained in the matched element set
jQuery.fn.size = function() {
return this.length;
};
jQuery.fn.andSelf = jQuery.fn.addBack;
// Register as a named AMD module, since jQuery can be concatenated with other
// files that may use define, but not via a proper concatenation script that
// understands anonymous AMD modules. A named AMD is safest and most robust
// way to register. Lowercase jquery is used because AMD module names are
// derived from file names, and jQuery is normally delivered in a lowercase
// file name. Do this after creating the global so that if an AMD module wants
// to call noConflict to hide this version of jQuery, it will work.
// Note that for maximum portability, libraries that are not jQuery should
// declare themselves as anonymous modules, and avoid setting a global if an
// AMD loader is present. jQuery is a special case. For more information, see
// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon
if ( typeof define === "function" && define.amd ) {
define( "jquery", [], function() {
return jQuery;
});
}
var
// Map over jQuery in case of overwrite
_jQuery = window.jQuery,
// Map over the $ in case of overwrite
_$ = window.$;
jQuery.noConflict = function( deep ) {
if ( window.$ === jQuery ) {
window.$ = _$;
}
if ( deep && window.jQuery === jQuery ) {
window.jQuery = _jQuery;
}
return jQuery;
};
// Expose jQuery and $ identifiers, even in
// AMD (#7102#comment:10, https://github.com/jquery/jquery/pull/557)
// and CommonJS for browser emulators (#13566)
if ( typeof noGlobal === strundefined ) {
window.jQuery = window.$ = jQuery;
}
return jQuery;
}));
================================================
FILE: WebRoot/js/jquery.backstretch.js
================================================
/*! Backstretch - v2.0.4 - 2013-06-19
* http://srobbin.com/jquery-plugins/backstretch/
* Copyright (c) 2013 Scott Robbin; Licensed MIT */
;(function ($, window, undefined) {
'use strict';
/* PLUGIN DEFINITION
* ========================= */
$.fn.backstretch = function (images, options) {
// We need at least one image or method name
if (images === undefined || images.length === 0) {
$.error("No images were supplied for Backstretch");
}
/*
* Scroll the page one pixel to get the right window height on iOS
* Pretty harmless for everyone else
*/
if ($(window).scrollTop() === 0 ) {
window.scrollTo(0, 0);
}
return this.each(function () {
var $this = $(this)
, obj = $this.data('backstretch');
// Do we already have an instance attached to this element?
if (obj) {
// Is this a method they're trying to execute?
if (typeof images == 'string' && typeof obj[images] == 'function') {
// Call the method
obj[images](options);
// No need to do anything further
return;
}
// Merge the old options with the new
options = $.extend(obj.options, options);
// Remove the old instance
obj.destroy(true);
}
obj = new Backstretch(this, images, options);
$this.data('backstretch', obj);
});
};
// If no element is supplied, we'll attach to body
$.backstretch = function (images, options) {
// Return the instance
return $('body')
.backstretch(images, options)
.data('backstretch');
};
// Custom selector
$.expr[':'].backstretch = function(elem) {
return $(elem).data('backstretch') !== undefined;
};
/* DEFAULTS
* ========================= */
$.fn.backstretch.defaults = {
centeredX: true // Should we center the image on the X axis?
, centeredY: true // Should we center the image on the Y axis?
, duration: 5000 // Amount of time in between slides (if slideshow)
, fade: 0 // Speed of fade transition between slides
};
/* STYLES
*
* Baked-in styles that we'll apply to our elements.
* In an effort to keep the plugin simple, these are not exposed as options.
* That said, anyone can override these in their own stylesheet.
* ========================= */
var styles = {
wrap: {
left: 0
, top: 0
, overflow: 'hidden'
, margin: 0
, padding: 0
, height: '100%'
, width: '100%'
, zIndex: -999999
}
, img: {
position: 'absolute'
, display: 'none'
, margin: 0
, padding: 0
, border: 'none'
, width: 'auto'
, height: 'auto'
, maxHeight: 'none'
, maxWidth: 'none'
, zIndex: -999999
}
};
/* CLASS DEFINITION
* ========================= */
var Backstretch = function (container, images, options) {
this.options = $.extend({}, $.fn.backstretch.defaults, options || {});
/* In its simplest form, we allow Backstretch to be called on an image path.
* e.g. $.backstretch('/path/to/image.jpg')
* So, we need to turn this back into an array.
*/
this.images = $.isArray(images) ? images : [images];
// Preload images
$.each(this.images, function () {
$('
![]()
')[0].src = this;
});
// Convenience reference to know if the container is body.
this.isBody = container === document.body;
/* We're keeping track of a few different elements
*
* Container: the element that Backstretch was called on.
* Wrap: a DIV that we place the image into, so we can hide the overflow.
* Root: Convenience reference to help calculate the correct height.
*/
this.$container = $(container);
this.$root = this.isBody ? supportsFixedPosition ? $(window) : $(document) : this.$container;
// Don't create a new wrap if one already exists (from a previous instance of Backstretch)
var $existing = this.$container.children(".backstretch").first();
this.$wrap = $existing.length ? $existing : $('
').css(styles.wrap).appendTo(this.$container);
// Non-body elements need some style adjustments
if (!this.isBody) {
// If the container is statically positioned, we need to make it relative,
// and if no zIndex is defined, we should set it to zero.
var position = this.$container.css('position')
, zIndex = this.$container.css('zIndex');
this.$container.css({
position: position === 'static' ? 'relative' : position
, zIndex: zIndex === 'auto' ? 0 : zIndex
, background: 'none'
});
// Needs a higher z-index
this.$wrap.css({zIndex: -999998});
}
// Fixed or absolute positioning?
this.$wrap.css({
position: this.isBody && supportsFixedPosition ? 'fixed' : 'absolute'
});
// Set the first image
this.index = 0;
this.show(this.index);
// Listen for resize
$(window).on('resize.backstretch', $.proxy(this.resize, this))
.on('orientationchange.backstretch', $.proxy(function () {
// Need to do this in order to get the right window height
if (this.isBody && window.pageYOffset === 0) {
window.scrollTo(0, 1);
this.resize();
}
}, this));
};
/* PUBLIC METHODS
* ========================= */
Backstretch.prototype = {
resize: function () {
try {
var bgCSS = {left: 0, top: 0}
, rootWidth = this.isBody ? this.$root.width() : this.$root.innerWidth()
, bgWidth = rootWidth
, rootHeight = this.isBody ? ( window.innerHeight ? window.innerHeight : this.$root.height() ) : this.$root.innerHeight()
, bgHeight = bgWidth / this.$img.data('ratio')
, bgOffset;
// Make adjustments based on image ratio
if (bgHeight >= rootHeight) {
bgOffset = (bgHeight - rootHeight) / 2;
if(this.options.centeredY) {
bgCSS.top = '-' + bgOffset + 'px';
}
} else {
bgHeight = rootHeight;
bgWidth = bgHeight * this.$img.data('ratio');
bgOffset = (bgWidth - rootWidth) / 2;
if(this.options.centeredX) {
bgCSS.left = '-' + bgOffset + 'px';
}
}
this.$wrap.css({width: rootWidth, height: rootHeight})
.find('img:not(.deleteable)').css({width: bgWidth, height: bgHeight}).css(bgCSS);
} catch(err) {
// IE7 seems to trigger resize before the image is loaded.
// This try/catch block is a hack to let it fail gracefully.
}
return this;
}
// Show the slide at a certain position
, show: function (newIndex) {
// Validate index
if (Math.abs(newIndex) > this.images.length - 1) {
return;
}
// Vars
var self = this
, oldImage = self.$wrap.find('img').addClass('deleteable')
, evtOptions = { relatedTarget: self.$container[0] };
// Trigger the "before" event
self.$container.trigger($.Event('backstretch.before', evtOptions), [self, newIndex]);
// Set the new index
this.index = newIndex;
// Pause the slideshow
clearInterval(self.interval);
// New image
self.$img = $('
![]()
')
.css(styles.img)
.bind('load', function (e) {
var imgWidth = this.width || $(e.target).width()
, imgHeight = this.height || $(e.target).height();
// Save the ratio
$(this).data('ratio', imgWidth / imgHeight);
// Show the image, then delete the old one
// "speed" option has been deprecated, but we want backwards compatibilty
$(this).fadeIn(self.options.speed || self.options.fade, function () {
oldImage.remove();
// Resume the slideshow
if (!self.paused) {
self.cycle();
}
// Trigger the "after" and "show" events
// "show" is being deprecated
$(['after', 'show']).each(function () {
self.$container.trigger($.Event('backstretch.' + this, evtOptions), [self, newIndex]);
});
});
// Resize
self.resize();
})
.appendTo(self.$wrap);
// Hack for IE img onload event
self.$img.attr('src', self.images[newIndex]);
return self;
}
, next: function () {
// Next slide
return this.show(this.index < this.images.length - 1 ? this.index + 1 : 0);
}
, prev: function () {
// Previous slide
return this.show(this.index === 0 ? this.images.length - 1 : this.index - 1);
}
, pause: function () {
// Pause the slideshow
this.paused = true;
return this;
}
, resume: function () {
// Resume the slideshow
this.paused = false;
this.next();
return this;
}
, cycle: function () {
// Start/resume the slideshow
if(this.images.length > 1) {
// Clear the interval, just in case
clearInterval(this.interval);
this.interval = setInterval($.proxy(function () {
// Check for paused slideshow
if (!this.paused) {
this.next();
}
}, this), this.options.duration);
}
return this;
}
, destroy: function (preserveBackground) {
// Stop the resize events
$(window).off('resize.backstretch orientationchange.backstretch');
// Clear the interval
clearInterval(this.interval);
// Remove Backstretch
if(!preserveBackground) {
this.$wrap.remove();
}
this.$container.removeData('backstretch');
}
};
/* SUPPORTS FIXED POSITION?
*
* Based on code from jQuery Mobile 1.1.0
* http://jquerymobile.com/
*
* In a nutshell, we need to figure out if fixed positioning is supported.
* Unfortunately, this is very difficult to do on iOS, and usually involves
* injecting content, scrolling the page, etc.. It's ugly.
* jQuery Mobile uses this workaround. It's not ideal, but works.
*
* Modified to detect IE6
* ========================= */
var supportsFixedPosition = (function () {
var ua = navigator.userAgent
, platform = navigator.platform
// Rendering engine is Webkit, and capture major version
, wkmatch = ua.match( /AppleWebKit\/([0-9]+)/ )
, wkversion = !!wkmatch && wkmatch[ 1 ]
, ffmatch = ua.match( /Fennec\/([0-9]+)/ )
, ffversion = !!ffmatch && ffmatch[ 1 ]
, operammobilematch = ua.match( /Opera Mobi\/([0-9]+)/ )
, omversion = !!operammobilematch && operammobilematch[ 1 ]
, iematch = ua.match( /MSIE ([0-9]+)/ )
, ieversion = !!iematch && iematch[ 1 ];
return !(
// iOS 4.3 and older : Platform is iPhone/Pad/Touch and Webkit version is less than 534 (ios5)
((platform.indexOf( "iPhone" ) > -1 || platform.indexOf( "iPad" ) > -1 || platform.indexOf( "iPod" ) > -1 ) && wkversion && wkversion < 534) ||
// Opera Mini
(window.operamini && ({}).toString.call( window.operamini ) === "[object OperaMini]") ||
(operammobilematch && omversion < 7458) ||
//Android lte 2.1: Platform is Android and Webkit version is less than 533 (Android 2.2)
(ua.indexOf( "Android" ) > -1 && wkversion && wkversion < 533) ||
// Firefox Mobile before 6.0 -
(ffversion && ffversion < 6) ||
// WebOS less than 3
("palmGetResource" in window && wkversion && wkversion < 534) ||
// MeeGo
(ua.indexOf( "MeeGo" ) > -1 && ua.indexOf( "NokiaBrowser/8.5.0" ) > -1) ||
// IE6
(ieversion && ieversion <= 6)
);
}());
}(jQuery, window));
================================================
FILE: WebRoot/js/placeholder.js
================================================
$(document).ready(function(){
$(".form-username").val("Username...");
$(".form-password").val("Password...");
});
================================================
FILE: WebRoot/js/scripts.js
================================================
jQuery(document).ready(function() {
/*
Fullscreen background
*/
$.backstretch("assets/img/backgrounds/1.jpg");
/*
Form validation
*/
$('.login-form input[type="text"], .login-form input[type="password"], .login-form textarea').on('focus', function() {
$(this).removeClass('input-error');
});
$('.login-form').on('submit', function(e) {
$(this).find('input[type="text"], input[type="password"], textarea').each(function(){
if( $(this).val() == "" ) {
e.preventDefault();
$(this).addClass('input-error');
}
else {
$(this).removeClass('input-error');
}
});
});
});
================================================
FILE: WebRoot/recommendResult.jsp
================================================
<%@ page language="java" import="java.util.*,com.rcd.javabean.*" pageEncoding="UTF-8"%>
推荐结果
<%
//接收电影信息
ArrayList
ownMovieInfo = (ArrayList)request.getAttribute("ownMovieInfo");
ArrayList recommendMovieInfo = (ArrayList)request.getAttribute("recommendMovieInfo");
// System.out.println("ownMovieInfo.size()"+ownMovieInfo.size());
// System.out.println("recommendMovieInfo.size()"+recommendMovieInfo.size());
%>
| 你的电影 |
| 电影名称 | 上映年份 | 电影类型 | 评分 | 电影海报 |
<%
//定义一个颜色数组
String []color = {"white","#AAAAFF"};
for(int i=0;i
| <%=ownInfo.getName() %> |
<%=ownInfo.getPublishedYear() %> |
<%=ownInfo.getType() %> |
<%=ownInfo.getPreference() %> |
.jpg" width=150px height=250px> |
<%
}
%>
|
| 推荐的电影 |
| 电影名称 | 上映年份 | 电影类型 | 评分 | 电影海报 |
<%
for(int i=0;i
| <%=recommendInfo.getName() %> |
<%=recommendInfo.getPublishedYear() %> |
<%=recommendInfo.getType() %> |
<%=recommendInfo.getPreference() %> |
.jpg" width=150px height=250px> |
<%
}
%>
|
================================================
FILE: desktop.ini
================================================
[ViewState]
Mode=
Vid=
FolderType=Generic
================================================
FILE: src/META-INF/MANIFEST.MF
================================================
Manifest-Version: 1.0
Class-Path:
================================================
FILE: src/com/rcd/conn/ConnectToMySQL.java
================================================
package com.rcd.conn;
import java.sql.*;
public class ConnectToMySQL {
private static Connection conn = null;
public static Connection getConnection(){
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/movie", "root", "hzb19961010");
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
return conn;
}
}
================================================
FILE: src/com/rcd/im/info/DBUtil.java
================================================
package com.rcd.im.info;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
public class DBUtil {
public static Connection getJDBCConnection() {
String driverClassName = "com.mysql.jdbc.Driver";
String url = "jdbc:mysql://localhost/movie";
String username = "root";
String password = "hzb19961010";
Connection conn = null;
try {
Class.forName(driverClassName);
conn = DriverManager.getConnection(url, username, password);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
}
================================================
FILE: src/com/rcd/im/info/ImportMovies.java
================================================
package com.rcd.im.info;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import com.rcd.javabean.Movie;
public class ImportMovies {
public final static String TABLE_NAME = "movies";
public final static String ID_COLUMN = "id";
public final static String NAME_COLUMN = "name";
public final static String PUBLISHED_YEAR_COLUMN = "published_year";
public final static String TYPE_COLUMN = "type";
/**
* @param args
*/
public static void main(String[] args) {
try {
LineNumberReader lineReader = new LineNumberReader(new FileReader(
"movielens/movies.dat"));
String line = "";
List movieList = new ArrayList();
while ((line = lineReader.readLine()) != null) {
movieList.add(fillMovie(line));
}
persist(movieList);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private static void persist(List movies) {
Connection conn = DBUtil.getJDBCConnection();
PreparedStatement ps = null;
String sql = "insert into " + TABLE_NAME + " ( " + ID_COLUMN + ", "
+ NAME_COLUMN + ", " + PUBLISHED_YEAR_COLUMN + ", "
+ TYPE_COLUMN + ") values (?, ?, ?, ?)";
try {
conn.setAutoCommit(false);
ps = conn.prepareStatement(sql);
for (Movie movie : movies) {
ps.setInt(1, movie.getId());
ps.setString(2, movie.getName());
ps.setString(3, movie.getYear());
ps.setString(4, StringUtil.connectString(movie.getType(), ", "));
ps.addBatch();
}
ps.executeBatch();
conn.commit();
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
ps.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
private static Movie fillMovie(String line) {
Movie movie = new Movie();
String[] mo = line.split("::");
movie.setId(Integer.parseInt(mo[0]));
movie.setName(mo[1].substring(0, mo[1].lastIndexOf("(") - 1));
movie.setYear(mo[1].substring(mo[1].lastIndexOf("(") + 1,
mo[1].lastIndexOf(")")));
List type = new ArrayList();
String[] t = mo[2].split("\\|");
for (int i = 0; i < t.length; i++) {
type.add(t[i]);
}
movie.setType(type);
return movie;
}
}
================================================
FILE: src/com/rcd/im/info/ImportRatings.java
================================================
package com.rcd.im.info;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import com.rcd.javabean.*;
public class ImportRatings {
public final static String TABLE_NAME = "movie_preferences";
public final static String USER_ID_COLUMN = "userID";
public final static String MOVIE_ID_COLUMN = "movieID";
public final static String RATING = "preference";
public final static String TIMESTAMP = "timestamp";
/**
* @param args
*/
public static void main(String[] args) {
try {
LineNumberReader lineReader = new LineNumberReader(new FileReader(
"movielens/ratings.dat"));
String line = "";
List ratingList = new ArrayList();
while ((line = lineReader.readLine()) != null) {
ratingList.add(fillRating(line));
}
insertRatings(ratingList);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private static Rating fillRating(String line) {
String[] ra = line.split("::");
Rating rating = new Rating();
rating.setUser_id(Integer.parseInt(ra[0]));
rating.setMovie_id(Integer.parseInt(ra[1]));
rating.setRating(Integer.parseInt(ra[2]));
rating.setTimestamp(Integer.parseInt(ra[3]));
return rating;
}
public static void insertRatings(List ratings) {
Connection conn = DBUtil.getJDBCConnection();
PreparedStatement ps = null;
String sql = "insert into " + TABLE_NAME + " ( " + USER_ID_COLUMN
+ ", " + MOVIE_ID_COLUMN + ", " + RATING + ", " + TIMESTAMP
+ ") values (?, ?, ?, ?)";
try {
conn.setAutoCommit(false);
ps = conn.prepareStatement(sql);
for (Rating rating : ratings) {
ps.setInt(1, rating.getUser_id());
ps.setInt(2, rating.getMovie_id());
ps.setInt(3, rating.getRating());
ps.setInt(4, rating.getTimestamp());
ps.addBatch();
}
ps.executeBatch();
conn.commit();
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
ps.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
================================================
FILE: src/com/rcd/im/info/StringUtil.java
================================================
package com.rcd.im.info;
import java.util.Collection;
public class StringUtil {
public static String connectString(Collection stringList,
String split) {
StringBuilder builder = new StringBuilder();
boolean flag = false;
for (String s : stringList) {
if (flag)
builder.append(split);
else {
flag = true;
}
builder.append(s);
}
return builder.toString();
}
}
================================================
FILE: src/com/rcd/javabean/Movie.java
================================================
package com.rcd.javabean;
import com.rcd.im.info.*;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Movie {
public static final String ID = "id";
public static final String NAME = "name";
public static final String YEAR = "publish_year";
public static final String TYPE = "type";
private int id;
private String name;
private String year;
private List type;
public Movie() {
}
public Movie(int id, String name, String year, List type) {
this.id = id;
this.name = name;
this.year = year;
this.type = type;
}
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public String getYear() {
return this.year;
}
public void setYear(String year) {
this.year = year;
}
public List getType() {
return this.type;
}
public void setType(List type) {
this.type = type;
}
public double relevance(Movie m) {
String patternString = StringUtil.connectString(this.type, "|");
Pattern pattern = Pattern.compile(patternString);
int count = 0;
for (String mType : m.getType()) {
Matcher matcher = pattern.matcher(mType);
if (matcher.matches()) {
count++;
}
}
return Math.log10(count + 1);
}
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("Name: " + this.name + " ");
sb.append("Publish Year: " + this.year + " ");
sb.append("Type: " + StringUtil.connectString(this.type, ", "));
return sb.toString();
}
public String toJSON() {
StringBuilder sb = new StringBuilder();
sb.append("{\"id\":" + this.id + ", ");
sb.append("\"name\":\"" + this.name + "\", ");
sb.append("\"publish_year\":\"" + this.year + "\", ");
sb.append("\"type\":\"" + StringUtil.connectString(this.type, " ")
+ "\"}");
return sb.toString();
}
}
================================================
FILE: src/com/rcd/javabean/MovieInfo.java
================================================
/**
* movie的javabean
*/
package com.rcd.javabean;
public class MovieInfo {
private String name;
private String publishedYear;
private String type;
private double preference;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPublishedYear() {
return publishedYear;
}
public void setPublishedYear(String publishedYear) {
this.publishedYear = publishedYear;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public double getPreference() {
return preference;
}
public void setPreference(double preference) {
this.preference = preference;
}
}
================================================
FILE: src/com/rcd/javabean/Rating.java
================================================
package com.rcd.javabean;
public class Rating {
private int user_id;
private int movie_id;
private int rating;
private int timestamp;
public int getUser_id() {
return this.user_id;
}
public void setUser_id(int user_id) {
this.user_id = user_id;
}
public int getMovie_id() {
return this.movie_id;
}
public void setMovie_id(int movie_id) {
this.movie_id = movie_id;
}
public int getRating() {
return this.rating;
}
public void setRating(int rating) {
this.rating = rating;
}
public int getTimestamp() {
return this.timestamp;
}
public void setTimestamp(int timestamp) {
this.timestamp = timestamp;
}
}
================================================
FILE: src/com/rcd/model/DataBaseUtil.java
================================================
package com.rcd.model;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
public class DataBaseUtil {
private static DataSource ds;
public static void createDataSource() throws Exception {
try {
Context context = new InitialContext();
if (context == null) {
throw new Exception("create context failed!");
}
ds = (DataSource) context.lookup("java:comp/env/jdbc/movie");
if (ds == null) {
Thread.sleep(2000L);
ds = (DataSource) context.lookup("java:comp/env/jdbc/movie");
if (ds == null)
throw new Exception("get datasource failed!");
}
} catch (NamingException ne) {
throw ne;
} catch (Exception e) {
throw e;
}
}
public static DataSource getDataSource() {
try {
if (ds == null) {
createDataSource();
}
return ds;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static Connection getConnection() {
DataSource dataSource = getDataSource();
try {
return dataSource.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
public static Connection getConnectionFromDataSource() {
try {
Connection con = null;
if (ds == null) {
createDataSource();
}
return ds.getConnection();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
================================================
FILE: src/com/rcd/model/GetMovieInfo.java
================================================
/**
* 获得电影的信息
*/
package com.rcd.model;
import java.sql.*;
import java.util.*;
import org.apache.mahout.cf.taste.recommender.RecommendedItem;
import com.rcd.javabean.*;
import com.rcd.conn.*;
public class GetMovieInfo {
private Connection conn = null;
private PreparedStatement ps = null;
private ResultSet rs = null;
//根据推荐的movie的ID,获得movie的详细信息
public ArrayList getMovieByMovieId(int id){
ArrayList movieList = new ArrayList();
try {
conn = ConnectToMySQL.getConnection();
String sql = "select m.name,m.published_year,m.type from movies m where m.id="+id+"";
ps = conn.prepareStatement(sql);
rs = ps.executeQuery();
while(rs.next()){
MovieInfo movieInfo = new MovieInfo();
movieInfo.setName(rs.getString(1));
movieInfo.setPublishedYear(rs.getString(2));
movieInfo.setType(rs.getString(3));
movieInfo.setPreference(5.0);
movieList.add(movieInfo);
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
finally{
closeAll();
}
return movieList;
}
//根据推荐的movie的ID,获得movie的详细信息
public ArrayList getMovieByMovieId(List recommendations){
ArrayList movieList = new ArrayList();
try {
String sql = "";
conn = ConnectToMySQL.getConnection();
for(int i=0;i getMovieByUserId(long userID){
ArrayList movieList = new ArrayList();
try {
String sql = "select m.name,m.published_year,m.type,mp.preference from movie_preferences mp,movies m where mp.movieID=m.id and mp.userID="+userID+" order by preference desc";
conn = ConnectToMySQL.getConnection();
ps = conn.prepareStatement(sql);
rs = ps.executeQuery();
while(rs.next()){
MovieInfo movieInfo = new MovieInfo();
movieInfo.setName(rs.getString(1));
movieInfo.setPublishedYear(rs.getString(2));
movieInfo.setType(rs.getString(3));
movieInfo.setPreference(rs.getInt(4));
movieList.add(movieInfo);
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}finally{
closeAll();
}
return movieList;
}
//关闭数据库
public void closeAll(){
try {
if(rs !=null){
rs.close();
rs = null;
}
if(ps !=null){
ps.close();
ps = null;
}
if(conn !=null){
conn.close();
conn = null;
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
================================================
FILE: src/com/rcd/model/MyDataModel.java
================================================
package com.rcd.model;
import org.apache.mahout.cf.taste.impl.model.jdbc.ConnectionPoolDataSource;
import org.apache.mahout.cf.taste.impl.model.jdbc.MySQLJDBCDataModel;
import org.apache.mahout.cf.taste.model.JDBCDataModel;
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
public class MyDataModel {
public static JDBCDataModel myDataModel() {
MysqlDataSource dataSource = new MysqlDataSource();
JDBCDataModel dataModel = null;
try {
dataSource.setServerName("localhost");
dataSource.setUser("root");
dataSource.setPassword("hzb19961010");
dataSource.setDatabaseName("movie");
ConnectionPoolDataSource connectionPool=new ConnectionPoolDataSource(dataSource);
// use JNDI
dataModel = new MySQLJDBCDataModel(connectionPool,"movie_preferences", "userID", "movieID","preference");
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
return dataModel;
}
}
================================================
FILE: src/com/rcd/model/recommender/MyItemBasedRecommender.java
================================================
package com.rcd.model.recommender;
import java.io.File;
import java.util.Collection;
import java.util.List;
import org.apache.mahout.cf.taste.impl.model.file.FileDataModel;
import org.apache.mahout.cf.taste.impl.recommender.CachingRecommender;
import org.apache.mahout.cf.taste.impl.recommender.GenericItemBasedRecommender;
import org.apache.mahout.cf.taste.impl.similarity.GenericItemSimilarity;
import org.apache.mahout.cf.taste.impl.similarity.PearsonCorrelationSimilarity;
import org.apache.mahout.cf.taste.model.DataModel;
import org.apache.mahout.cf.taste.recommender.RecommendedItem;
import org.apache.mahout.cf.taste.recommender.Recommender;
import org.apache.mahout.cf.taste.similarity.ItemSimilarity;
public class MyItemBasedRecommender {
public List myItemBasedRecommender(long userID,int size){
List recommendations = null;
try {
DataModel model = new FileDataModel(new File("D:/ml-1m/movie_preferences.txt"));//构造数据模型
ItemSimilarity similarity = new PearsonCorrelationSimilarity(model);//计算内容相似度
Recommender recommender = new GenericItemBasedRecommender(model, similarity);//构造推荐引擎
recommendations = recommender.recommend(userID, size);//得到推荐结果
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
return recommendations;
}
}
================================================
FILE: src/com/rcd/model/recommender/MySlopeOneRecommender.java
================================================
package com.rcd.model.recommender;
import java.io.File;
import java.util.List;
import org.apache.mahout.cf.taste.impl.model.file.FileDataModel;
import org.apache.mahout.cf.taste.impl.recommender.CachingRecommender;
import org.apache.mahout.cf.taste.impl.recommender.slopeone.SlopeOneRecommender;
import org.apache.mahout.cf.taste.impl.similarity.PearsonCorrelationSimilarity;
import org.apache.mahout.cf.taste.model.DataModel;
import org.apache.mahout.cf.taste.recommender.RecommendedItem;
import org.apache.mahout.cf.taste.recommender.Recommender;
import org.apache.mahout.cf.taste.similarity.ItemSimilarity;
public class MySlopeOneRecommender {
public List mySlopeOneRecommender(long userID,int size){
List recommendations = null;
try {
DataModel model = new FileDataModel(new File("D:/ml-1m/movie_preferences.txt"));//构造数据模型
Recommender recommender = new CachingRecommender(new SlopeOneRecommender(model));//构造推荐引擎
recommendations = recommender.recommend(userID, size);//得到推荐的结果,size是推荐接过的数目
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
return recommendations;
}
}
================================================
FILE: src/com/rcd/model/recommender/MyUserBasedRecommender.java
================================================
package com.rcd.model.recommender;
import org.apache.mahout.cf.taste.impl.neighborhood.*;
import org.apache.mahout.cf.taste.impl.recommender.*;
import org.apache.mahout.cf.taste.impl.similarity.*;
import org.apache.mahout.cf.taste.model.*;
import org.apache.mahout.cf.taste.neighborhood.*;
import org.apache.mahout.cf.taste.recommender.*;
import org.apache.mahout.cf.taste.similarity.*;
import com.rcd.model.MyDataModel;
import java.util.*;
public class MyUserBasedRecommender {
public List userBasedRecommender(long userID,int size) {
// step:1 构建模型 2 计算相似度 3 查找k紧邻 4 构造推荐引擎
List recommendations = null;
try {
DataModel model = MyDataModel.myDataModel();//构造数据模型
UserSimilarity similarity = new PearsonCorrelationSimilarity(model);//用PearsonCorrelation 算法计算用户相似度
UserNeighborhood neighborhood = new NearestNUserNeighborhood(3, similarity, model);//计算用户的“邻居”,这里将与该用户最近距离为 3 的用户设置为该用户的“邻居”。
Recommender recommender = new CachingRecommender(new GenericUserBasedRecommender(model, neighborhood, similarity));//采用 CachingRecommender 为 RecommendationItem 进行缓存
recommendations = recommender.recommend(userID, size);//得到推荐的结果,size是推荐结果的数目
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
return recommendations;
}
public static void main(String args[]) throws Exception {
}
}
================================================
FILE: src/com/rcd/model/recommender/RecommenderIntro.java
================================================
package com.rcd.model.recommender;
import java.util.List;
import org.apache.mahout.cf.taste.impl.common.FastByIDMap;
import org.apache.mahout.cf.taste.impl.model.GenericDataModel;
import org.apache.mahout.cf.taste.impl.model.GenericUserPreferenceArray;
import org.apache.mahout.cf.taste.impl.neighborhood.NearestNUserNeighborhood;
import org.apache.mahout.cf.taste.impl.recommender.GenericUserBasedRecommender;
import org.apache.mahout.cf.taste.impl.similarity.PearsonCorrelationSimilarity;
import org.apache.mahout.cf.taste.model.DataModel;
import org.apache.mahout.cf.taste.model.PreferenceArray;
import org.apache.mahout.cf.taste.neighborhood.UserNeighborhood;
import org.apache.mahout.cf.taste.recommender.RecommendedItem;
import org.apache.mahout.cf.taste.recommender.Recommender;
import org.apache.mahout.cf.taste.similarity.UserSimilarity;
public class RecommenderIntro {
public static void main(String[] args) throws Exception {
FastByIDMap preferences = new FastByIDMap();
PreferenceArray prefsForUser1 = new GenericUserPreferenceArray(3);// 注意这里的数字
// 这里是用来存储一个用户的元数据,这些元数据通常来自日志文件,比如浏览历史,等等,不同的业务场合,它的业务语义是不一样
prefsForUser1.setUserID(0, 1);
prefsForUser1.setItemID(0, 101);
prefsForUser1.setValue(0, 5.0f);//<1, 101, 5.0f> < 用户 ID, 物品 ID, 用户偏好 >
prefsForUser1.setItemID(1, 102);
prefsForUser1.setValue(1, 3.0f);//<1, 102, 3.0f>
prefsForUser1.setItemID(2, 103);
prefsForUser1.setValue(2, 2.5f);//<1, 103, 2.5f>
preferences.put(1l, prefsForUser1);// 在这里添加数据,userID作为key
PreferenceArray prefsForUser2 = new GenericUserPreferenceArray(4);
prefsForUser2.setUserID(0, 2);
prefsForUser2.setItemID(0, 101);//<2, 101, 2.0f>
prefsForUser2.setValue(0, 2.0f);
prefsForUser2.setItemID(1, 102);
prefsForUser2.setValue(1, 2.5f);//<2, 102, 2.5f>
prefsForUser2.setItemID(2, 103);
prefsForUser2.setValue(2, 5.0f);//<2, 103, 5.0f>
prefsForUser2.setItemID(3, 104);
prefsForUser2.setValue(3, 2.0f);//<2, 104, 2.0f>
preferences.put(2l, prefsForUser2);
PreferenceArray prefsForUser3 = new GenericUserPreferenceArray(4);
prefsForUser3.setUserID(0, 3);
prefsForUser3.setItemID(0, 101);
prefsForUser3.setValue(0, 2.5f);
prefsForUser3.setItemID(1, 104);
prefsForUser3.setValue(1, 4.0f);
prefsForUser3.setItemID(2, 105);
prefsForUser3.setValue(2, 4.5f);
prefsForUser3.setItemID(3, 107);
prefsForUser3.setValue(3, 5.0f);
preferences.put(3l, prefsForUser3);
PreferenceArray prefsForUser4 = new GenericUserPreferenceArray(4);
prefsForUser4.setUserID(0, 4);
prefsForUser4.setItemID(0, 101);
prefsForUser4.setValue(0, 5.0f);
prefsForUser4.setItemID(1, 103);
prefsForUser4.setValue(1, 3.0f);
prefsForUser4.setItemID(2, 104);
prefsForUser4.setValue(2, 4.5f);
prefsForUser4.setItemID(3, 106);
prefsForUser4.setValue(3, 4.0f);
preferences.put(4l, prefsForUser4);
PreferenceArray prefsForUser5 = new GenericUserPreferenceArray(6);
prefsForUser5.setUserID(0, 5);
prefsForUser5.setItemID(0, 101);
prefsForUser5.setValue(0, 4.0f);
prefsForUser5.setItemID(1, 102);
prefsForUser5.setValue(1, 3.0f);
prefsForUser5.setItemID(2, 103);
prefsForUser5.setValue(2, 2.0f);
prefsForUser5.setItemID(3, 104);
prefsForUser5.setValue(3, 4.0f);
prefsForUser5.setItemID(4, 105);
prefsForUser5.setValue(4, 3.5f);
prefsForUser5.setItemID(5, 106);
prefsForUser5.setValue(5, 4.0f);
preferences.put(5l, prefsForUser5);
DataModel model = new GenericDataModel(preferences);// DataModel的建立
UserSimilarity similarity = new PearsonCorrelationSimilarity(model);//计算相似度
UserNeighborhood neighborhood = new NearestNUserNeighborhood(2,similarity, model);//计算邻居
// 创建推荐引擎
Recommender recommender = new GenericUserBasedRecommender(model,neighborhood, similarity);
//为用户1推荐2个
List recommendations = recommender.recommend(1, 2);
for (RecommendedItem recommendation : recommendations) {
System.out.println(recommendation);
}
}
}
================================================
FILE: src/com/rcd/servlet/RecomendServlet.java
================================================
package com.rcd.servlet;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.mahout.cf.taste.recommender.RecommendedItem;
import com.rcd.javabean.MovieInfo;
import com.rcd.model.GetMovieInfo;
import com.rcd.model.recommender.MyItemBasedRecommender;
import com.rcd.model.recommender.MySlopeOneRecommender;
import com.rcd.model.recommender.MyUserBasedRecommender;
public class RecomendServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//接收用户id
long userID = Long.parseLong(request.getParameter("userID"));
//接收size
int size = Integer.parseInt(request.getParameter("size"));
//接收推荐类型参数
String recommendType = request.getParameter("recommendType");
GetMovieInfo getMovieInfo = new GetMovieInfo();
//用户的所有电影
ArrayList ownMovieInfo = getMovieInfo.getMovieByUserId(userID);
//推荐电影的List
List recommendation = null;
if(recommendType.equals("userBased")){//基于用户
MyUserBasedRecommender mubr = new MyUserBasedRecommender();
//拿到推荐的电影
recommendation = mubr.userBasedRecommender(userID,size);
}else if(recommendType.equals("itemBased")){//基于内容
MyItemBasedRecommender mibr = new MyItemBasedRecommender();
//拿到推荐的电影
recommendation = mibr.myItemBasedRecommender(userID,size);
}else if(recommendType.equals("slopeOne")){//slope one
MySlopeOneRecommender msor = new MySlopeOneRecommender();
//拿到推荐的电影
recommendation = msor.mySlopeOneRecommender(userID,size);
}
//拿到推荐的电影的详细信息
ArrayList recommendMovieInfo = getMovieInfo.getMovieByMovieId(recommendation);
//页面跳转
request.setAttribute("ownMovieInfo", ownMovieInfo);
request.setAttribute("recommendMovieInfo", recommendMovieInfo);
request.getRequestDispatcher("recommendResult.jsp").forward(request, response);
}
}