第 9 部分 spring业务模块
主要实现 JavaEE 层面整体的业务逻辑,通过 Spring 进行构建,对接业务需求。部署在 Tomcat 上。
在MovieRecommendSystem项目中新建model为busnessServer的子项目
pom.xml文件导入依赖
<packaging>war</packaging>
<properties>
<spring.version>4.3.6.RELEASE</spring.version>
<spring.data.jpa.version>1.11.0.RELEASE</spring.data.jpa.version>
<jackson.version>2.8.6</jackson.version>
<servlet.version>3.0.1</servlet.version>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.9.1</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>${servlet.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>transport</artifactId>
<version>5.6.2</version>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver</artifactId>
<version>3.5.0</version>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- Spring End -->
<!-- fasterxml -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<!-- fasterxml end -->
</dependencies>
<build>
<finalName>BusinessServer</finalName>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<!-- http port -->
<port>8088</port>
<path>/</path>
<contextReloadable>true</contextReloadable>
</configuration>
</plugin>
</plugins>
</build>
在com.atguigu.business.model中分别建立domin,recom,request子包.
在domin中子包
新建Movie实体类
package com.atguigu.business.model.domain;
import com.fasterxml.jackson.annotation.JsonIgnore;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class Movie {
@JsonIgnore
private String _id;
private int mid;
private String name;
private String descri;
private String timelong;
private String issue;
private String shoot;
private Double score;
private String language;
private String genres;
private String actors;
private String directors;
public int getMid() {
return mid;
}
public void setMid(int mid) {
this.mid = mid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescri() {
return descri;
}
public void setDescri(String descri) {
this.descri = descri;
}
public String getTimelong() {
return timelong;
}
public void setTimelong(String timelong) {
this.timelong = timelong;
}
public String getIssue() {
return issue;
}
public void setIssue(String issue) {
this.issue = issue;
}
public String getShoot() {
return shoot;
}
public void setShoot(String shoot) {
this.shoot = shoot;
}
public String getLanguage() {
return language;
}
public void setLanguage(String language) {
this.language = language;
}
public String getGenres() {
return genres;
}
public void setGenres(String genres) {
this.genres = genres;
}
public String getActors() {
return actors;
}
public void setActors(String actors) {
this.actors = actors;
}
public String getDirectors() {
return directors;
}
public void setDirectors(String directors) {
this.directors = directors;
}
public Double getScore() {
return score;
}
public void setScore(Double score) {
this.score = score;
}
public String get_id() {
return _id;
}
public void set_id(String _id) {
this._id = _id;
}
}
在domin中新建Rating实体类
package com.atguigu.business.model.domain;
import com.fasterxml.jackson.annotation.JsonIgnore;
import java.io.Serializable;
import java.util.Date;
public class Rating {
@JsonIgnore
private String _id;
private int uid;
private int mid;
private double score;
private long timestamp;
public Rating() {
}
public Rating(int uid, int mid, double score) {
this.uid = uid;
this.mid = mid;
this.score = score;
this.timestamp = new Date().getTime();
}
public int getUid() {
return uid;
}
public void setUid(int uid) {
this.uid = uid;
}
public int getMid() {
return mid;
}
public void setMid(int mid) {
this.mid = mid;
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
public long getTimestamp() {
return timestamp;
}
public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
public String get_id() {
return _id;
}
public void set_id(String _id) {
this._id = _id;
}
}
在domin中新建Tag实体类
package com.atguigu.business.model.domain;
import com.fasterxml.jackson.annotation.JsonIgnore;
import java.io.Serializable;
import java.util.Date;
import java.util.UUID;
public class Tag {
@JsonIgnore
private String _id;
private int uid;
private int mid;
private String tag;
private long timestamp;
public Tag(int uid, int mid, String tag) {
this.uid = uid;
this.mid = mid;
this.tag = tag;
this.timestamp = new Date().getTime();
}
public Tag() {
}
public int getUid() {
return uid;
}
public void setUid(int uid) {
this.uid = uid;
}
public int getMid() {
return mid;
}
public void setMid(int mid) {
this.mid = mid;
}
public String getTag() {
return tag;
}
public void setTag(String tag) {
this.tag = tag;
}
public long getTimestamp() {
return timestamp;
}
public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
public String get_id() {
return _id;
}
public void set_id(String _id) {
this._id = _id;
}
}
在domin中新建User实体类
package com.atguigu.business.model.domain;
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.bson.Document;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class User {
@JsonIgnore
private String _id;
private int uid;
private String username;
private String password;
private boolean first;
private long timestamp;
private List<String> prefGenres = new ArrayList<>();
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.uid = username.hashCode();
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public boolean isFirst() {
return first;
}
public void setFirst(boolean first) {
this.first = first;
}
public long getTimestamp() {
return timestamp;
}
public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
public boolean passwordMatch(String password) {
return this.password.compareTo(password) == 0;
}
public int getUid() {
return uid;
}
public void setUid(int uid) {
this.uid = uid;
}
public String get_id() {
return _id;
}
public void set_id(String _id) {
this._id = _id;
}
public List<String> getPrefGenres() {
return prefGenres;
}
public void setPrefGenres(List<String> prefGenres) {
this.prefGenres = prefGenres;
}
}
在recom中
新建Recommendation包装类
package com.atguigu.business.model.recom;
/**
* 推荐项目的包装
*/
public class Recommendation {
// 电影ID
private int mid;
// 电影的推荐得分
private Double score;
public Recommendation() {
}
public Recommendation(int mid, Double score) {
this.mid = mid;
this.score = score;
}
public int getMid() {
return mid;
}
public void setMid(int mid) {
this.mid = mid;
}
public Double getScore() {
return score;
}
public void setScore(Double score) {
this.score = score;
}
}
在request中
新建HotRecommendationRequest请求
package com.atguigu.business.model.request;
public class HotRecommendationRequest {
private int sum;
public HotRecommendationRequest(int sum) {
this.sum = sum;
}
public int getSum() {
return sum;
}
public void setSum(int sum) {
this.sum = sum;
}
}
在request中新建LoginUserRequest请求
package com.atguigu.business.model.request;
public class LoginUserRequest {
private String username;
private String password;
public LoginUserRequest(String username, String password) {
this.username = username;
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
在request中新建MovieHybridRecommendationRequest请求
package com.atguigu.business.model.request;
public class MovieHybridRecommendationRequest {
private int mid;
private int sum;
public MovieHybridRecommendationRequest(int mid, int sum) {
this.mid = mid;
this.sum = sum;
}
public int getSum() {
return sum;
}
public void setSum(int sum) {
this.sum = sum;
}
public int getMid() {
return mid;
}
public void setMid(int mid) {
this.mid = mid;
}
}
在request中新建MovieRatingRequest请求
package com.atguigu.business.model.request;
public class MovieRatingRequest {
private int uid;
private int mid;
private Double score;
public MovieRatingRequest(int uid, int mid, Double score) {
this.uid = uid;
this.mid = mid;
this.score = score;
}
public int getUid() {
return uid;
}
public void setUid(int uid) {
this.uid = uid;
}
public int getMid() {
return mid;
}
public void setMid(int mid) {
this.mid = mid;
}
public Double getScore() {
return Double.parseDouble(String.format("%.2f",score/2D));
}
public void setScore(Double score) {
this.score = score;
}
}
在request中新建MovieRecommendationRequest请求
package com.atguigu.business.model.request;
public class MovieRecommendationRequest {
private int mid;
private int sum;
public MovieRecommendationRequest(int mid, int sum) {
this.mid = mid;
this.sum = sum;
}
public int getSum() {
return sum;
}
public void setSum(int sum) {
this.sum = sum;
}
public int getMid() {
return mid;
}
public void setMid(int mid) {
this.mid = mid;
}
}
在request中新建NewRecommendationRequest请求
package com.atguigu.business.model.request;
public class NewRecommendationRequest {
private int sum;
public NewRecommendationRequest(int sum) {
this.sum = sum;
}
public int getSum() {
return sum;
}
public void setSum(int sum) {
this.sum = sum;
}
}
在request中新建RateMoreRecommendationRequest请求
package com.atguigu.business.model.request;
public class RateMoreRecommendationRequest {
private int sum;
public RateMoreRecommendationRequest(int sum) {
this.sum = sum;
}
public int getSum() {
return sum;
}
public void setSum(int sum) {
this.sum = sum;
}
}
在request中新建RegisterUserRequest请求
package com.atguigu.business.model.request;
public class RegisterUserRequest {
private String username;
private String password;
public RegisterUserRequest(String username, String password) {
this.username = username;
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
在request中新建SearchRecommendationRequest请求
package com.atguigu.business.model.request;
public class SearchRecommendationRequest {
private String text;
private int sum;
public SearchRecommendationRequest(String text, int sum) {
this.text = text;
this.sum = sum;
}
public int getSum() {
return sum;
}
public void setSum(int sum) {
this.sum = sum;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}
在request中新建TopGenresRecommendationRequest请求
package com.atguigu.business.model.request;
public class TopGenresRecommendationRequest {
private int sum;
private String genres;
public TopGenresRecommendationRequest(String genres, int sum) {
this.genres = genres;
this.sum = sum;
}
public int getSum() {
return sum;
}
public void setSum(int sum) {
this.sum = sum;
}
public String getGenres() {
return genres;
}
public void setGenres(String genres) {
this.genres = genres;
}
}
在request中新建UserRecommendationRequest请求
package com.atguigu.business.model.request;
public class UserRecommendationRequest {
private int uid;
private int sum;
public UserRecommendationRequest(int uid, int sum) {
this.uid = uid;
this.sum = sum;
}
public int getSum() {
return sum;
}
public void setSum(int sum) {
this.sum = sum;
}
public int getUid() {
return uid;
}
public void setUid(int uid) {
this.uid = uid;
}
}
在rest中
新建MovieRestApi控制器
package com.atguigu.business.rest;
import com.atguigu.business.model.domain.Tag;
import com.atguigu.business.model.recom.Recommendation;
import com.atguigu.business.model.request.*;
import com.atguigu.business.service.*;
import com.atguigu.business.model.domain.User;
import com.atguigu.business.utils.Constant;
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.apache.log4j.Logger;
import java.util.List;
import java.util.Random;
@RequestMapping("/rest/movie")
@Controller
public class MovieRestApi {
// private Logger logger = LoggerFactory.getLogger(MovieRestApi.class);
private static Logger logger = Logger.getLogger(MovieRestApi.class.getName());
@Autowired
private RecommenderService recommenderService;
@Autowired
private MovieService movieService;
@Autowired
private UserService userService;
@Autowired
private RatingService ratingService;
@Autowired
private TagService tagService;
/**
* 获取推荐的电影【实时推荐6 + 内容推荐4】
* @param username
* @param model
* @return
*/
// TODO: 2017/10/20 bug 混合推荐结果中,基于内容的推荐,基于MID,而非UID
@RequestMapping(value = "/guess", produces = "application/json", method = RequestMethod.GET )
@ResponseBody
public Model getGuessMovies(@RequestParam("username")String username,@RequestParam("num")int num, Model model) {
User user = userService.findByUsername(username);
List<Recommendation> recommendations = recommenderService.getHybridRecommendations(new MovieHybridRecommendationRequest(user.getUid(),num));
if(recommendations.size()==0){
String randomGenres = user.getPrefGenres().get(new Random().nextInt(user.getPrefGenres().size()));
recommendations = recommenderService.getTopGenresRecommendations(new TopGenresRecommendationRequest(randomGenres.split(" ")[0],num));
}
model.addAttribute("success",true);
model.addAttribute("movies",movieService.getHybirdRecommendeMovies(recommendations));
return model;
}
/**
*
* @param username
* @param model
* @return
*/
@RequestMapping(value = "/wish", produces = "application/json", method = RequestMethod.GET )
@ResponseBody
public Model getWishMovies(@RequestParam("username")String username,@RequestParam("num")int num, Model model) {
User user = userService.findByUsername(username);
List<Recommendation> recommendations = recommenderService.getCollaborativeFilteringRecommendations(new UserRecommendationRequest(user.getUid(),num));
if(recommendations.size()==0){
String randomGenres = user.getPrefGenres().get(new Random().nextInt(user.getPrefGenres().size()));
recommendations = recommenderService.getTopGenresRecommendations(new TopGenresRecommendationRequest(randomGenres.split(" ")[0],num));
}
model.addAttribute("success",true);
model.addAttribute("movies",movieService.getRecommendeMovies(recommendations));
return model;
}
/**
* 获取热门推荐
* @param model
* @return
*/
@RequestMapping(value = "/hot", produces = "application/json", method = RequestMethod.GET )
@ResponseBody
public Model getHotMovies(@RequestParam("num")int num, Model model) {
List<Recommendation> recommendations = recommenderService.getHotRecommendations(new HotRecommendationRequest(num));
model.addAttribute("success",true);
model.addAttribute("movies",movieService.getRecommendeMovies(recommendations));
return model;
}
/**
* 获取投票最多的电影
* @param model
* @return
*/
@RequestMapping(value = "/rate", produces = "application/json", method = RequestMethod.GET )
@ResponseBody
public Model getRateMoreMovies(@RequestParam("num")int num, Model model) {
List<Recommendation> recommendations = recommenderService.getRateMoreRecommendations(new RateMoreRecommendationRequest(num));
model.addAttribute("success",true);
model.addAttribute("movies",movieService.getRecommendeMovies(recommendations));
return model;
}
/**
* 获取新添加的电影
* @param model
* @return
*/
@RequestMapping(value = "/new", produces = "application/json", method = RequestMethod.GET )
@ResponseBody
public Model getNewMovies(@RequestParam("num")int num, Model model) {
model.addAttribute("success",true);
model.addAttribute("movies",movieService.getNewMovies(new NewRecommendationRequest(num)));
return model;
}
/**
* 获取电影详细页面相似的电影集合
* @param id
* @param model
* @return
*/
@RequestMapping(value = "/same/{id}", produces = "application/json", method = RequestMethod.GET )
@ResponseBody
public Model getSameMovie(@PathVariable("id")int id,@RequestParam("num")int num, Model model) {
List<Recommendation> recommendations = recommenderService.getCollaborativeFilteringRecommendations(new MovieRecommendationRequest(id,num));
model.addAttribute("success",true);
model.addAttribute("movies",movieService.getRecommendeMovies(recommendations));
return model;
}
/**
* 获取单个电影的信息
* @param id
* @param model
* @return
*/
@RequestMapping(value = "/info/{id}", produces = "application/json", method = RequestMethod.GET )
@ResponseBody
public Model getMovieInfo(@PathVariable("id")int id, Model model) {
model.addAttribute("success",true);
model.addAttribute("movie",movieService.findByMID(id));
return model;
}
/**
* 模糊查询电影
* @param query
* @param model
* @return
*/
@RequestMapping(value = "/search", produces = "application/json", method = RequestMethod.GET )
@ResponseBody
public Model getSearchMovies(@RequestParam("query")String query, Model model) {
List<Recommendation> recommendations = recommenderService.getContentBasedSearchRecommendations(new SearchRecommendationRequest(query,100));
model.addAttribute("success",true);
model.addAttribute("movies",movieService.getRecommendeMovies(recommendations));
return model;
}
/**
* 查询类别电影
* @param category
* @param model
* @return
*/
@RequestMapping(value = "/genres", produces = "application/json", method = RequestMethod.GET )
@ResponseBody
public Model getGenresMovies(@RequestParam("category")String category, Model model) {
List<Recommendation> recommendations = recommenderService.getContentBasedGenresRecommendations(new SearchRecommendationRequest(category,100));
model.addAttribute("success",true);
model.addAttribute("movies",movieService.getRecommendeMovies(recommendations));
return model;
}
/**
* 获取用户评分过得电影
* @param username
* @param model
* @return
*/
@RequestMapping(value = "/myrate", produces = "application/json", method = RequestMethod.GET )
@ResponseBody
public Model getMyRateMovies(@RequestParam("username")String username, Model model) {
User user = userService.findByUsername(username);
model.addAttribute("success",true);
model.addAttribute("movies",movieService.getMyRateMovies(user.getUid()));
return model;
}
@RequestMapping(value = "/rate/{id}", produces = "application/json", method = RequestMethod.GET )
@ResponseBody
public Model rateToMovie(@PathVariable("id")int id,@RequestParam("score")Double score,@RequestParam("username")String username, Model model) {
User user = userService.findByUsername(username);
MovieRatingRequest request = new MovieRatingRequest(user.getUid(),id,score);
boolean complete = ratingService.movieRating(request);
//埋点日志
if(complete) {
System.out.print("=========complete=========");
logger.info(Constant.MOVIE_RATING_PREFIX + ":" + user.getUid() +"|"+ id +"|"+ request.getScore() +"|"+ System.currentTimeMillis()/1000);
}
model.addAttribute("success",true);
model.addAttribute("message"," 已完成评分!");
return model;
}
@RequestMapping(value = "/tag/{mid}", produces = "application/json", method = RequestMethod.GET )
@ResponseBody
public Model getMovieTags(@PathVariable("mid")int mid, Model model) {
model.addAttribute("success",true);
model.addAttribute("tags",tagService.findMovieTags(mid));
return model;
}
@RequestMapping(value = "/mytag/{mid}", produces = "application/json", method = RequestMethod.GET )
@ResponseBody
public Model getMyTags(@PathVariable("mid")int mid,@RequestParam("username")String username, Model model) {
User user = userService.findByUsername(username);
model.addAttribute("success",true);
model.addAttribute("tags",tagService.findMyMovieTags(user.getUid(),mid));
return model;
}
@RequestMapping(value = "/newtag/{mid}", produces = "application/json", method = RequestMethod.GET )
@ResponseBody
public Model addMyTags(@PathVariable("mid")int mid,@RequestParam("tagname")String tagname,@RequestParam("username")String username, Model model) {
User user = userService.findByUsername(username);
Tag tag = new Tag(user.getUid(),mid,tagname);
tagService.newTag(tag);
model.addAttribute("success",true);
model.addAttribute("tag",tag);
return model;
}
@RequestMapping(value = "/stat", produces = "application/json", method = RequestMethod.GET )
@ResponseBody
public Model getMyRatingStat(@RequestParam("username")String username, Model model) {
User user = userService.findByUsername(username);
model.addAttribute("success",true);
model.addAttribute("stat",ratingService.getMyRatingStat(user));
return model;
}
}
在rest中新建UserRestApi控制器
package com.atguigu.business.rest;
import com.atguigu.business.model.domain.User;
import com.atguigu.business.model.request.LoginUserRequest;
import com.atguigu.business.model.request.RegisterUserRequest;
import com.atguigu.business.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@RequestMapping("/rest/users")
@Controller
public class UserRestApi {
@Autowired
private UserService userService;
@RequestMapping(value = "/login", produces = "application/json", method = RequestMethod.GET )
@ResponseBody
public Model login(@RequestParam("username") String username, @RequestParam("password") String password, Model model) {
User user =userService.loginUser(new LoginUserRequest(username,password));
model.addAttribute("success",user != null);
model.addAttribute("user",user);
return model;
}
@RequestMapping(value = "/register", produces = "application/json", method = RequestMethod.GET)
@ResponseBody
public Model addUser(@RequestParam("username") String username,@RequestParam("password") String password,Model model) {
if(userService.checkUserExist(username)){
model.addAttribute("success",false);
model.addAttribute("message"," 用户名已经被注册!");
return model;
}
model.addAttribute("success",userService.registerUser(new RegisterUserRequest(username,password)));
return model;
}
//冷启动问题
@RequestMapping(value = "/pref", produces = "application/json", method = RequestMethod.GET)
@ResponseBody
public Model addPrefGenres(@RequestParam("username") String username,@RequestParam("genres") String genres,Model model) {
User user = userService.findByUsername(username);
user.getPrefGenres().addAll(Arrays.asList(genres.split(",")));
user.setFirst(false);
model.addAttribute("success",userService.updateUser(user));
return model;
}
}
在service中
新建MovieService服务器
package com.atguigu.business.service;
import com.atguigu.business.model.domain.Movie;
import com.atguigu.business.model.domain.Rating;
import com.atguigu.business.model.recom.Recommendation;
import com.atguigu.business.model.request.NewRecommendationRequest;
import com.atguigu.business.utils.Constant;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mongodb.MongoClient;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.model.Filters;
import com.mongodb.client.model.Sorts;
import com.mongodb.util.JSON;
import org.bson.Document;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Service
public class MovieService {
@Autowired
private MongoClient mongoClient;
@Autowired
private ObjectMapper objectMapper;
private MongoCollection<Document> movieCollection;
private MongoCollection<Document> averageMoviesScoreCollection;
private MongoCollection<Document> rateCollection;
private MongoCollection<Document> getMovieCollection(){
if(null == movieCollection)
movieCollection = mongoClient.getDatabase(Constant.MONGODB_DATABASE).getCollection(Constant.MONGODB_MOVIE_COLLECTION);
return movieCollection;
}
private MongoCollection<Document> getAverageMoviesScoreCollection(){
if(null == averageMoviesScoreCollection)
averageMoviesScoreCollection = mongoClient.getDatabase(Constant.MONGODB_DATABASE).getCollection(Constant.MONGODB_AVERAGE_MOVIES_SCORE_COLLECTION);
return averageMoviesScoreCollection;
}
private MongoCollection<Document> getRateCollection(){
if(null == rateCollection)
rateCollection = mongoClient.getDatabase(Constant.MONGODB_DATABASE).getCollection(Constant.MONGODB_RATING_COLLECTION);
return rateCollection;
}
public List<Movie> getRecommendeMovies(List<Recommendation> recommendations){
List<Integer> ids = new ArrayList<>();
for (Recommendation rec: recommendations) {
ids.add(rec.getMid());
}
return getMovies(ids);
}
public List<Movie> getHybirdRecommendeMovies(List<Recommendation> recommendations){
List<Integer> ids = new ArrayList<>();
for (Recommendation rec: recommendations) {
ids.add(rec.getMid());
}
return getMovies(ids);
}
public List<Movie> getMovies(List<Integer> mids){
FindIterable<Document> documents = getMovieCollection().find(Filters.in("mid",mids));
List<Movie> movies = new ArrayList<>();
for (Document document: documents) {
movies.add(documentToMovie(document));
}
return movies;
}
private Movie documentToMovie(Document document){
Movie movie = null;
try{
movie = objectMapper.readValue(JSON.serialize(document),Movie.class);
Document score = getAverageMoviesScoreCollection().find(Filters.eq("mid",movie.getMid())).first();
if(null == score || score.isEmpty())
movie.setScore(0D);
else
movie.setScore((Double) score.get("avg",0D));
}catch (IOException e) {
e.printStackTrace();
}
return movie;
}
private Rating documentToRating(Document document){
Rating rating = null;
try{
rating = objectMapper.readValue(JSON.serialize(document),Rating.class);
}catch (IOException e) {
e.printStackTrace();
}
return rating;
}
public boolean movieExist(int mid){
return null != findByMID(mid);
}
public Movie findByMID(int mid){
Document document = getMovieCollection().find(new Document("mid",mid)).first();
if(document == null || document.isEmpty())
return null;
return documentToMovie(document);
}
public void removeMovie(int mid){
getMovieCollection().deleteOne(new Document("mid",mid));
}
public List<Movie> getMyRateMovies(int uid){
FindIterable<Document> documents = getRateCollection().find(Filters.eq("uid",uid));
List<Integer> ids = new ArrayList<>();
Map<Integer,Double> scores = new HashMap<>();
for (Document document: documents) {
Rating rating = documentToRating(document);
ids.add(rating.getMid());
scores.put(rating.getMid(),rating.getScore());
}
List<Movie> movies = getMovies(ids);
for (Movie movie: movies) {
movie.setScore(scores.getOrDefault(movie.getMid(),movie.getScore()));
}
return movies;
}
public List<Movie> getNewMovies(NewRecommendationRequest request){
FindIterable<Document> documents = getMovieCollection().find().sort(Sorts.descending("issue")).limit(request.getSum());
List<Movie> movies = new ArrayList<>();
for (Document document: documents) {
movies.add(documentToMovie(document));
}
return movies;
}
}
在service中
新建RatingService服务器
package com.atguigu.business.service;
import com.atguigu.business.model.domain.Rating;
import com.atguigu.business.model.domain.User;
import com.atguigu.business.model.request.MovieRatingRequest;
import com.atguigu.business.utils.Constant;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mongodb.BasicDBObject;
import com.mongodb.MongoClient;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.util.JSON;
import org.bson.Document;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import redis.clients.jedis.Jedis;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@Service
public class RatingService {
@Autowired
private MongoClient mongoClient;
@Autowired
private ObjectMapper objectMapper;
@Autowired
private Jedis jedis;
private MongoCollection<Document> ratingCollection;
private MongoCollection<Document> getRatingCollection() {
if (null == ratingCollection)
ratingCollection = mongoClient.getDatabase(Constant.MONGODB_DATABASE).getCollection(Constant.MONGODB_RATING_COLLECTION);
return ratingCollection;
}
private Rating documentToRating(Document document) {
Rating rating = null;
try {
rating = objectMapper.readValue(JSON.serialize(document), Rating.class);
} catch (IOException e) {
e.printStackTrace();
}
return rating;
}
public boolean movieRating(MovieRatingRequest request) {
Rating rating = new Rating(request.getUid(), request.getMid(), request.getScore());
updateRedis(rating);
if (ratingExist(rating.getUid(), rating.getMid())) {
return updateRating(rating);
} else {
return newRating(rating);
}
}
private void updateRedis(Rating rating) {
if (jedis.exists("uid:" + rating.getUid()) && jedis.llen("uid:" + rating.getUid()) >= Constant.REDIS_MOVIE_RATING_QUEUE_SIZE) {
jedis.rpop("uid:" + rating.getUid());
}
jedis.lpush("uid:" + rating.getUid(), rating.getMid() + ":" + rating.getScore());
}
public boolean newRating(Rating rating) {
try {
getRatingCollection().insertOne(Document.parse(objectMapper.writeValueAsString(rating)));
return true;
} catch (JsonProcessingException e) {
e.printStackTrace();
return false;
}
}
public boolean ratingExist(int uid, int mid) {
return null != findRating(uid, mid);
}
public boolean updateRating(Rating rating) {
BasicDBObject basicDBObject = new BasicDBObject();
basicDBObject.append("uid", rating.getUid());
basicDBObject.append("mid", rating.getMid());
getRatingCollection().updateOne(basicDBObject,
new Document().append("$set", new Document("score", rating.getScore())));
return true;
}
public Rating findRating(int uid, int mid) {
BasicDBObject basicDBObject = new BasicDBObject();
basicDBObject.append("uid", uid);
basicDBObject.append("mid", mid);
FindIterable<Document> documents = getRatingCollection().find(basicDBObject);
if (documents.first() == null)
return null;
return documentToRating(documents.first());
}
public void removeRating(int uid, int mid) {
BasicDBObject basicDBObject = new BasicDBObject();
basicDBObject.append("uid", uid);
basicDBObject.append("mid", mid);
getRatingCollection().deleteOne(basicDBObject);
}
public int[] getMyRatingStat(User user) {
FindIterable<Document> documents = getRatingCollection().find(new Document("uid", user.getUid()));
int[] stats = new int[10];
for (Document document : documents) {
Rating rating = documentToRating(document);
Long index = Math.round(rating.getScore() / 0.5);
stats[index.intValue()] = stats[index.intValue()] + 1;
}
return stats;
}
}
在service中
新建RecommenderService服务器
package com.atguigu.business.service;
import com.atguigu.business.model.recom.Recommendation;
import com.atguigu.business.model.request.*;
import com.atguigu.business.utils.Constant;
import com.mongodb.MongoClient;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.model.Filters;
import com.mongodb.client.model.Sorts;
import org.bson.Document;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.SearchHit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
@Service
public class RecommenderService {
// 混合推荐中CF的比例
private static Double CF_RATING_FACTOR = 0.3;
private static Double CB_RATING_FACTOR = 0.3;
private static Double SR_RATING_FACTOR = 0.4;
@Autowired
private MongoClient mongoClient;
@Autowired
private TransportClient esClient;
// 协同过滤推荐【电影相似性】
private List<Recommendation> findMovieCFRecs(int mid, int maxItems) {
MongoCollection<Document> movieRecsCollection = mongoClient.getDatabase(Constant.MONGODB_DATABASE).getCollection(Constant.MONGODB_MOVIE_RECS_COLLECTION);
Document movieRecs = movieRecsCollection.find(new Document("mid", mid)).first();
return parseRecs(movieRecs, maxItems);
}
// 协同过滤推荐【用户电影矩阵】
private List<Recommendation> findUserCFRecs(int uid, int maxItems) {
MongoCollection<Document> movieRecsCollection = mongoClient.getDatabase(Constant.MONGODB_DATABASE).getCollection(Constant.MONGODB_USER_RECS_COLLECTION);
Document userRecs = movieRecsCollection.find(new Document("uid", uid)).first();
return parseRecs(userRecs, maxItems);
}
// 基于内容的推荐算法
private List<Recommendation> findContentBasedMoreLikeThisRecommendations(int mid, int maxItems) {
MoreLikeThisQueryBuilder query = QueryBuilders.moreLikeThisQuery(/*new String[]{"name", "descri", "genres", "actors", "directors", "tags"},*/
new MoreLikeThisQueryBuilder.Item[]{new MoreLikeThisQueryBuilder.Item(Constant.ES_INDEX, Constant.ES_MOVIE_TYPE, String.valueOf(mid))});
return parseESResponse(esClient.prepareSearch().setQuery(query).setSize(maxItems).execute().actionGet());
}
// 实时推荐
private List<Recommendation> findStreamRecs(int uid,int maxItems){
MongoCollection<Document> streamRecsCollection = mongoClient.getDatabase(Constant.MONGODB_DATABASE).getCollection(Constant.MONGODB_STREAM_RECS_COLLECTION);
Document streamRecs = streamRecsCollection.find(new Document("uid", uid)).first();
return parseRecs(streamRecs, maxItems);
}
private List<Recommendation> parseRecs(Document document, int maxItems) {
List<Recommendation> recommendations = new ArrayList<>();
if (null == document || document.isEmpty())
return recommendations;
ArrayList<Document> recs = document.get("recs", ArrayList.class);
for (Document recDoc : recs) {
recommendations.add(new Recommendation(recDoc.getInteger("mid"), recDoc.getDouble("score")));
}
Collections.sort(recommendations, new Comparator<Recommendation>() {
@Override
public int compare(Recommendation o1, Recommendation o2) {
return o1.getScore() > o2.getScore() ? -1 : 1;
}
});
return recommendations.subList(0, maxItems > recommendations.size() ? recommendations.size() : maxItems);
}
// 全文检索
private List<Recommendation> findContentBasedSearchRecommendations(String text, int maxItems) {
MultiMatchQueryBuilder query = QueryBuilders.multiMatchQuery(text, "name", "descri");
return parseESResponse(esClient.prepareSearch().setIndices(Constant.ES_INDEX).setTypes(Constant.ES_MOVIE_TYPE).setQuery(query).setSize(maxItems).execute().actionGet());
}
private List<Recommendation> parseESResponse(SearchResponse response) {
List<Recommendation> recommendations = new ArrayList<>();
for (SearchHit hit : response.getHits()) {
recommendations.add(new Recommendation((int) hit.getSourceAsMap().get("mid"), (double) hit.getScore()));
}
return recommendations;
}
// 混合推荐算法
private List<Recommendation> findHybridRecommendations(int productId, int maxItems) {
List<Recommendation> hybridRecommendations = new ArrayList<>();
List<Recommendation> cfRecs = findMovieCFRecs(productId, maxItems);
for (Recommendation recommendation : cfRecs) {
hybridRecommendations.add(new Recommendation(recommendation.getMid(), recommendation.getScore() * CF_RATING_FACTOR));
}
List<Recommendation> cbRecs = findContentBasedMoreLikeThisRecommendations(productId, maxItems);
for (Recommendation recommendation : cbRecs) {
hybridRecommendations.add(new Recommendation(recommendation.getMid(), recommendation.getScore() * CB_RATING_FACTOR));
}
List<Recommendation> streamRecs = findStreamRecs(productId,maxItems);
for (Recommendation recommendation : streamRecs) {
hybridRecommendations.add(new Recommendation(recommendation.getMid(), recommendation.getScore() * SR_RATING_FACTOR));
}
Collections.sort(hybridRecommendations, new Comparator<Recommendation>() {
@Override
public int compare(Recommendation o1, Recommendation o2) {
return o1.getScore() > o2.getScore() ? -1 : 1;
}
});
return hybridRecommendations.subList(0, maxItems > hybridRecommendations.size() ? hybridRecommendations.size() : maxItems);
}
public List<Recommendation> getCollaborativeFilteringRecommendations(MovieRecommendationRequest request) {
return findMovieCFRecs(request.getMid(), request.getSum());
}
public List<Recommendation> getCollaborativeFilteringRecommendations(UserRecommendationRequest request) {
return findUserCFRecs(request.getUid(), request.getSum());
}
public List<Recommendation> getContentBasedMoreLikeThisRecommendations(MovieRecommendationRequest request) {
return findContentBasedMoreLikeThisRecommendations(request.getMid(), request.getSum());
}
public List<Recommendation> getContentBasedSearchRecommendations(SearchRecommendationRequest request) {
return findContentBasedSearchRecommendations(request.getText(), request.getSum());
}
public List<Recommendation> getHybridRecommendations(MovieHybridRecommendationRequest request) {
return findHybridRecommendations(request.getMid(), request.getSum());
}
public List<Recommendation> getHotRecommendations(HotRecommendationRequest request) {
// 获取热门电影的条目
MongoCollection<Document> rateMoreMoviesRecentlyCollection = mongoClient.getDatabase(Constant.MONGODB_DATABASE).getCollection(Constant.MONGODB_RATE_MORE_MOVIES_RECENTLY_COLLECTION);
FindIterable<Document> documents = rateMoreMoviesRecentlyCollection.find().sort(Sorts.descending("yeahmonth")).limit(request.getSum());
List<Recommendation> recommendations = new ArrayList<>();
for (Document document : documents) {
recommendations.add(new Recommendation(document.getInteger("mid"), 0D));
}
return recommendations;
}
public List<Recommendation> getRateMoreRecommendations(RateMoreRecommendationRequest request) {
// 获取评分最多电影的条目
MongoCollection<Document> rateMoreMoviesCollection = mongoClient.getDatabase(Constant.MONGODB_DATABASE).getCollection(Constant.MONGODB_RATE_MORE_MOVIES_COLLECTION);
FindIterable<Document> documents = rateMoreMoviesCollection.find().sort(Sorts.descending("count")).limit(request.getSum());
List<Recommendation> recommendations = new ArrayList<>();
for (Document document : documents) {
recommendations.add(new Recommendation(document.getInteger("mid"), 0D));
}
return recommendations;
}
public List<Recommendation> getContentBasedGenresRecommendations(SearchRecommendationRequest request) {
FuzzyQueryBuilder query = QueryBuilders.fuzzyQuery("genres", request.getText());
return parseESResponse(esClient.prepareSearch().setIndices(Constant.ES_INDEX).setTypes(Constant.ES_MOVIE_TYPE).setQuery(query).setSize(request.getSum()).execute().actionGet());
}
public List<Recommendation> getTopGenresRecommendations(TopGenresRecommendationRequest request){
Document genresTopMovies = mongoClient.getDatabase(Constant.MONGODB_DATABASE).getCollection(Constant.MONGODB_GENRES_TOP_MOVIES_COLLECTION)
.find(Filters.eq("genres",request.getGenres())).first();
return parseRecs(genresTopMovies,request.getSum());
}
}
在service中
新建TagService服务器
package com.atguigu.business.service;
import com.atguigu.business.model.domain.Tag;
import com.atguigu.business.model.domain.User;
import com.atguigu.business.utils.Constant;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mongodb.BasicDBObject;
import com.mongodb.MongoClient;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.util.JSON;
import org.bson.Document;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
@Service
public class TagService {
@Autowired
private MongoClient mongoClient;
@Autowired
private ObjectMapper objectMapper;
@Autowired
private TransportClient esClient;
private MongoCollection<Document> tagCollection;
private MongoCollection<Document> getTagCollection(){
if(null == tagCollection)
tagCollection = mongoClient.getDatabase(Constant.MONGODB_DATABASE).getCollection(Constant.MONGODB_TAG_COLLECTION);
return tagCollection;
}
private Tag documentToTag(Document document){
try{
return objectMapper.readValue(JSON.serialize(document),Tag.class);
} catch (JsonParseException e) {
e.printStackTrace();
return null;
} catch (JsonMappingException e) {
e.printStackTrace();
return null;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
public void newTag(Tag tag){
try{
getTagCollection().insertOne(Document.parse(objectMapper.writeValueAsString(tag)));
updateElasticSearchIndex(tag);
}catch (JsonProcessingException e) {
e.printStackTrace();
}
}
private void updateElasticSearchIndex(Tag tag){
GetResponse getResponse = esClient.prepareGet(Constant.ES_INDEX,Constant.ES_MOVIE_TYPE,String.valueOf(tag.getMid())).get();
Object value = getResponse.getSourceAsMap().get("tags");
UpdateRequest updateRequest = new UpdateRequest(Constant.ES_INDEX,Constant.ES_MOVIE_TYPE,String.valueOf(tag.getMid()));
try{
if(value == null){
updateRequest.doc(XContentFactory.jsonBuilder().startObject().field("tags",tag.getTag()).endObject());
}else{
updateRequest.doc(XContentFactory.jsonBuilder().startObject().field("tags",value+"|"+tag.getTag()).endObject());
}
esClient.update(updateRequest).get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public List<Tag> findMovieTags(int mid){
List<Tag> tags = new ArrayList<>();
FindIterable<Document> documents = getTagCollection().find(new Document("mid",mid));
for (Document document: documents) {
tags.add(documentToTag(document));
}
return tags;
}
public List<Tag> findMyMovieTags(int uid, int mid){
List<Tag> tags = new ArrayList<>();
BasicDBObject basicDBObject = new BasicDBObject();
basicDBObject.append("uid",uid);
basicDBObject.append("mid",mid);
FindIterable<Document> documents = getTagCollection().find(basicDBObject);
for (Document document: documents) {
tags.add(documentToTag(document));
}
return tags;
}
public void removeTag(int eid){
getTagCollection().deleteOne(new Document("eid",eid));
}
}
在service中
新建UserService服务器
package com.atguigu.business.service;
import com.atguigu.business.model.domain.Tag;
import com.atguigu.business.model.domain.User;
import com.atguigu.business.model.request.LoginUserRequest;
import com.atguigu.business.model.request.RegisterUserRequest;
import com.atguigu.business.utils.Constant;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mongodb.MongoClient;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.model.Filters;
import com.mongodb.util.JSON;
import org.bson.Document;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.util.List;
@Service
public class UserService {
@Autowired
private MongoClient mongoClient;
@Autowired
private ObjectMapper objectMapper;
private MongoCollection<Document> userCollection;
private MongoCollection<Document> getUserCollection(){
if(null == userCollection)
userCollection = mongoClient.getDatabase(Constant.MONGODB_DATABASE).getCollection(Constant.MONGODB_USER_COLLECTION);
return userCollection;
}
public boolean registerUser(RegisterUserRequest request){
User user = new User();
user.setUsername(request.getUsername());
user.setPassword(request.getPassword());
user.setFirst(true);
user.setTimestamp(System.currentTimeMillis());
try{
getUserCollection().insertOne(Document.parse(objectMapper.writeValueAsString(user)));
return true;
}catch (JsonProcessingException e){
e.printStackTrace();
return false;
}
}
public User loginUser(LoginUserRequest request){
User user = findByUsername(request.getUsername());
if(null == user) {
return null;
}else if(!user.passwordMatch(request.getPassword())){
return null;
}
return user;
}
private User documentToUser(Document document){
try{
return objectMapper.readValue(JSON.serialize(document),User.class);
} catch (JsonParseException e) {
e.printStackTrace();
return null;
} catch (JsonMappingException e) {
e.printStackTrace();
return null;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
public boolean checkUserExist(String username){
return null != findByUsername(username);
}
public User findByUsername(String username){
Document user = getUserCollection().find(new Document("username",username)).first();
if(null == user || user.isEmpty())
return null;
return documentToUser(user);
}
public boolean updateUser(User user){
getUserCollection().updateOne(Filters.eq("uid", user.getUid()), new Document().append("$set",new Document("first", user.isFirst())));
getUserCollection().updateOne(Filters.eq("uid", user.getUid()), new Document().append("$set",new Document("prefGenres", user.getPrefGenres())));
return true;
}
public User findByUID(int uid){
Document user = getUserCollection().find(new Document("uid",uid)).first();
if(null == user || user.isEmpty())
return null;
return documentToUser(user);
}
public void removeUser(String username){
getUserCollection().deleteOne(new Document("username",username));
}
}
在utils中
新建Application工具类
package com.atguigu.business;
import com.atguigu.business.model.domain.Tag;
import com.atguigu.business.model.domain.User;
import com.atguigu.business.utils.Constant;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mongodb.MongoClient;
import com.mongodb.client.model.Filters;
import org.bson.Document;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.index.get.GetField;
import org.elasticsearch.transport.client.PreBuiltTransportClient;
import java.io.IOException;
import java.net.InetAddress;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.ApplicationContext;
/**
* Created by wuyufei on 08/08/2017.
*/
public class Application {
public static void main(String[] args) throws IOException, ExecutionException, InterruptedException {
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:application.xml");
Settings settings = Settings.builder().put("cluster.name","es-cluster").build();
TransportClient esClient = new PreBuiltTransportClient(settings);
esClient.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("hadoop99"), 9300));
GetResponse getResponse = esClient.prepareGet(Constant.ES_INDEX,Constant.ES_MOVIE_TYPE,"3062").get();
//Map<String,GetField> filed = getResponse.getFields();
Object value = getResponse.getSourceAsMap().get("tags");
if(value == null){
UpdateRequest updateRequest = new UpdateRequest(Constant.ES_INDEX,Constant.ES_MOVIE_TYPE,"3062");
updateRequest.doc(XContentFactory.jsonBuilder().startObject()
.field("tags","abc")
.endObject());
esClient.update(updateRequest).get();
}else{
UpdateRequest updateRequest = new UpdateRequest(Constant.ES_INDEX,Constant.ES_MOVIE_TYPE,"2542");
updateRequest.doc(XContentFactory.jsonBuilder().startObject()
.field("tags",value+"|abc")
.endObject());
esClient.update(updateRequest).get();
}
System.out.println(Math.round(4.466D));
}
}
在utils中
新建package-info.java类引用
package com.atguigu.business;
日志和资源
在log包中新建空白的agent.log日志文件
在resources包中
application.xml文件中,添加组件扫描,路径,映射文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.atguigu.business"/>
<context:property-placeholder location="classpath:recommend.properties" ignore-unresolvable="true"/>
<bean id="mapper" class="com.fasterxml.jackson.databind.ObjectMapper"/>
</beans>
新建log4j.properties文件
添加输出的日志格式,时间,Windows下的真实路径
log4j.rootLogger=INFO, file, stdout
# write to stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p --- [%50t] %-80c(line:%5L) : %m%n
# write to file
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.File=E:\\idea\\project\\MovieRecommendSystem\\businessServer\\src\\main\\log\\agent.log
log4j.appender.file.MaxFileSize=1024KB
log4j.appender.file.MaxBackupIndex=1
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p --- [%50t] %-80c(line:%6L) : %m%n
新建log4j2.xml文件
添加警告级别
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
</Appenders>
<Loggers>
<Root level="error">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>
新建recommend.properties文件
提供推荐elasticSearch,Mongodb,Redis的主机,端口号等信息
#elasticSearch
es.host=hadoop99
es.port=9300
es.cluster.name=es-cluster
#Mongodb
mongo.host=hadoop99
mongo.port=27017
#Redis
redis.host=hadoop99
第 10 部分 AngularJS2用户可视化模块
主要负责实现和用户的交互以及业务数据的展示,主体采用AngularJS2 进行实现,部署在 Apache 服务上。
若要在linux上就需要安装Apache,
1.第一步命令安装apache:
yum install httpd httpd-devel -y
2.第二步执行命令:
开启服务器
systemctl start httpd.service
执行下面命令,使服务器随Linux的启动而启动:
systemctl enable httpd.service
3.做到这里还是不行的,因为Linux系统中的防火墙会没有给Apache开放端口,所以需要做以下操作:
firewall-cmd --zone=public --add-port=80/tcp --permanent
firewall-cmd --reload
4.此时就可以在浏览器地址栏输入服务器的ip地址访问了,可以看到这样的界面:
这样apache服务器就成功安装完成!
5.安装完成以后apache默认的安装地址为 etc/httpd/conf/httpd.conf
打开配置文件后将里面的/var/www/html/为默认文件夹
模块整体结构
在webapp中assets文件主要是样式定义,images是图片文件夹
WEB-INF中application-servlet.xml存放整个应用服务器配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd">
<context:component-scan base-package="com.atguigu.business.rest" />
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<bean class="org.springframework.http.converter.StringHttpMessageConverter"/>
<bean class="org.springframework.http.converter.BufferedImageHttpMessageConverter"/>
<bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter"/>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/html; charset=UTF-8</value>
<value>application/json;charset=UTF-8</value>
</list>
</property>
<property name="objectMapper">
<bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
<property name="featuresToEnable">
<array>
<util:constant static-field="com.fasterxml.jackson.databind.SerializationFeature.CLOSE_CLOSEABLE"/>
</array>
</property>
<property name="featuresToDisable">
<array>
<util:constant static-field="com.fasterxml.jackson.databind.SerializationFeature.FAIL_ON_EMPTY_BEANS"/>
</array>
</property>
</bean>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="contentNegotiationManager" ref="contentNegotiationManager" />
<property name="viewResolvers">
<list>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/"/>
<property name="suffix" value=".jsp"/>
</bean>
</list>
</property>
<property name="defaultViews">
<list>
<bean class="org.springframework.web.servlet.view.json.MappingJackson2JsonView" />
</list>
</property>
<property name="useNotAcceptableStatusCode" value="true" />
</bean>
<bean id="contentNegotiationManager"
class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<property name="defaultContentType" value="application/json" />
<property name="mediaTypes">
<value>
json=application/json
xml=text/xml
html=text/html
</value>
</property>
</bean>
<mvc:default-servlet-handler />
<mvc:cors>
<mvc:mapping path="/**" allowed-origins="*" allow-credentials="true" max-age="1800" allowed-methods="GET,POST,OPTIONS"/>
</mvc:cors>
</beans>
WEB-INF中web.xml存放过滤器,监听器,服务器映射等配置
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app
version="3.0"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<display-name>recommender</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:application.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>recommend</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/application-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>recommend</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
index.html是首页显示
<!--这是别人访问你的网站是看到的主页面的HTML文件。 大多数情况下你都不用编辑它。 在构建应用时,CLI会自动把所有js和css文件添加进去,所以你不必在这里手动添加任何 <script> 或 <link> 标签。-->
<!DOCTYPE html>
<html>
<head>
<base href="/">
<title>MovieLens海外电影推荐系统</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
<movie-app>加载中...</movie-app>
<script type="text/javascript" src="inline.bundle.js"></script><script type="text/javascript" src="polyfills.bundle.js"></script><script type="text/javascript" src="scripts.bundle.js"></script><script type="text/javascript" src="styles.bundle.js"></script><script type="text/javascript" src="vendor.bundle.js"></script><script type="text/javascript" src="main.bundle.js"></script></body>
<script type="application/javascript">
document.oncontextmenu=function(){return false;}
document.onkeydown=function(event){
var e = event || window.event || arguments.callee.caller.arguments[0];
if(e && e.keyCode==116){
return false;
}
}
</script>
</html>
后面的各种AngularJS2样式配置js文件等
运行businessServer的Tomcat服务,开启可视化
点击Maven Projects中的Tomcat.run插件