基于javaweb+mysql的springboot协同过滤算法新闻推荐管理系统(java+ssm+javascript+html+ajax+mysql)
运行环境
Java≥8、MySQL≥5.7
开发工具
eclipse/idea/myeclipse/sts等均可配置运行
适用
课程设计,大作业,毕业设计,项目练习,学习演示等
功能说明
基于javaweb+mysql的SpringBoot协同过滤算法新闻推荐管理系统(java+ssm+javascript+html+ajax+mysql)
项目介绍
本项目新闻推荐管理系统;
前台:
登录、首页、全部新闻、系统特色、猜你喜欢、分类、评论
后台: (1)文件管理:文件列表。 (2)用户管理:用户管理。 (3)新闻管理:新闻管理。 (4)三联管理:联动管理。 (5)新闻审核:新闻的审核和管理。
技术栈
SSM+mysql+layui+CSS+JavaScript
使用说明
- 使用Navicat或者其它工具,在mysql中创建对应名称的数据库,并导入项目的sql文件; 2. 使用IDEA/Eclipse/MyEclipse导入项目,导入成功后请执行maven clean;maven install命令,然后运行; 3. 将项目中application.properties配置文件中的数据库配置改为自己的配置; 4. 运行项目,在浏览器中输入http://localhost:8080 访问
Long categoryId = queryParam.getCategoryId();
queryWrapper.eq(categoryId!=null,"category_id",categoryId);
String title = queryParam.getTitle();
queryWrapper.like(!StringUtils.isEmpty(title),"title",title);
if(!StringUtils.isEmpty(vagueParam)){
// and ( title like '%XXXX%' or theme like '%YYYY%')
queryWrapper.and(
e->e.like("title",vagueParam)
.or()
.like("theme",vagueParam)
);
}
queryWrapper.orderByDesc("id");
IPage<CheckNews> indexPage = new Page<>(pageNum, pageSize);
IPage<CheckNews> newsIPage = checkNewsService.page(indexPage, queryWrapper);
logger.debug("获取的新闻列表:"+newsIPage);
Map resultMap = ToolsUtils.wrapperResult(newsIPage, "newsList");
return ResultUtil.successData(resultMap);
}
/**
* 新闻审核管理
* @param news
* @return
*/
@RequestMapping("/check")
@ResponseBody
public ResponseBean updateById(CheckNews news, HttpSession session) {
if (news == null||news.getId()==null) {
return ResultUtil.error(CommonEnum.BAD_PARAM);
}
Long categoryId = news.getCategoryId();
news.setCategoryName(newsCategoryService.getById(categoryId)==null?"":newsCategoryService.getById(categoryId).getName());
news.setUserId(ToolsUtils.getLoginUserId(session));
news.setUserName(ToolsUtils.getLoginUserName(session));
news.setUpdateTime(LocalDateTime.now());
boolean i = checkNewsService.updateById(news);
return ResultUtil.successData(news);
}
/**
* 跳转到新闻审核页面
* @param id
* @param model
* @return
*/
@RequestMapping("/checkedit/{id}")
public String editPage(@PathVariable Long id, Model model) {
model.addAttribute("checknews", checkNewsService.getById(id));
return "checknews/checkedit";
}
*/
@Controller
@RequestMapping({"/newsComment","/home/newsComment"})
public class NewsCommentController {
private static final Logger logger= LoggerFactory.getLogger(NewsCommentController.class);
private static final String page_prefix="news/comment/";
@Autowired
NewsCommentService commentService;
@Autowired
SysNewsService newsService;
/**
* 跳转列表页面
* @return
*/
@RequestMapping("/listPage")
public String listPage() {
return page_prefix+"list";
}
/**
* 添加用户评论
* @param comment
* @param session
* @return
*/
@RequestMapping("/add")
@ResponseBody
public ResponseBean add(NewsComment comment, HttpSession session){
//变量类型 变量名 = 类/对象 . 方法 方法入参
SysUser loginUser = ToolsUtils.getLoginUser(session);
//将loginUser的Id 设置为comment的userId
comment.setUserId(loginUser.getId());
comment.setUserName(loginUser.getName());
comment.setField1(loginUser.getField1());
Long newsId = comment.getNewsId();
SysNews news = newsService.getById(newsId);
comment.setNewsTitle(news==null?"已经被删除":news.getTitle());
boolean save = commentService.save(comment);
return save?ResultUtil.successData(comment):ResultUtil.error();
}
/**
* 新闻评论列表查询
* @param pageNum 页码
* @param pageSize 每页大小
boolean delete = userService.removeByIds(idList);
logger.debug("批量删除结果:"+delete);
return new ResponseBean<Map<String, Object>>(true, null, CommonEnum.SUCCESS_REQUEST);
}
//删除单个用户
@RequestMapping("deleteById")
@ResponseBody
public ResponseBean deleteById(@RequestParam Long id){
logger.debug("deleteById:"+id);
if(id==null||id<0){
return new ResponseBean(false,CommonEnum.BAD_REQUEST);
}
boolean delete = userService.removeById(id);
logger.debug("删除结果:"+delete);
return new ResponseBean<Map<String, Object>>(true, null, CommonEnum.SUCCESS_REQUEST);
}
}
/**
* <p>
* 用户转发表 前端控制器
* </p>
*
*/
@Controller
@RequestMapping("/newsForward")
public class NewsForwardController {
private static final Logger logger= LoggerFactory.getLogger(NewsForwardController.class);
private static final String page_prefix="news/forward/";
@Autowired
NewsForwardService forwardService;
/**
* 跳转列表页面
* @return
*/
@RequestMapping("/listPage")
public String listPage() {
return page_prefix+"list";
}
/**
* 新闻转发列表查询
* @param pageNum 页码
* @param pageSize 每页大小
* @param queryParam 查询参数
* @param vagueParam 模糊参数
* @return
*/
@ApiOperation("获取新闻转发列表")
@RequestMapping("/list/{pageNum}/{pageSize}")
pageInfo.put("pages", listPage.getPages());
pageInfo.put("total", listPage.getTotal());
Map<String, Object> resultMap = new HashMap<String, Object>();
resultMap.put(listCode, listPage.getRecords());
resultMap.put("pageInfo", pageInfo);
return resultMap;
}
/**
* 从Excel中获取单元格数据,返回格式为String
* @param cell
* @return
*/
public static String getValFromCell(Cell cell){
if(cell==null){
return null;
}
CellType cellTypeEnum = cell.getCellType();
switch (cellTypeEnum) {
case NUMERIC:return String.valueOf(cell.getNumericCellValue());
case STRING:return cell.getStringCellValue();
case BOOLEAN:return String.valueOf(cell.getBooleanCellValue());
case ERROR:return String.valueOf(cell.getErrorCellValue());
case FORMULA:
case _NONE:
case BLANK:return null;
default:
return null;
}
}
//从cell获取日期类型值
public static String getDateCellVal(Cell cell,String pattern){
if(cell==null){
return null;
}
Date value = cell.getDateCellValue();
return DateUtils.format(value,pattern);
}
/**
* 获取登录用户信息
* */
public static SysUser getLoginUser(HttpSession session){
/**
* <p>
* 用户转发表 前端控制器
* </p>
*
*/
@Controller
@RequestMapping("/newsForward")
public class NewsForwardController {
private static final Logger logger= LoggerFactory.getLogger(NewsForwardController.class);
private static final String page_prefix="news/forward/";
@Autowired
NewsForwardService forwardService;
/**
* 跳转列表页面
* @return
*/
@RequestMapping("/listPage")
public String listPage() {
return page_prefix+"list";
}
/**
* 新闻转发列表查询
* @param pageNum 页码
* @param pageSize 每页大小
* @param queryParam 查询参数
* @param vagueParam 模糊参数
* @return
logger.debug("服务器环境,请将config.json放到"+rootPath+"的上一级下面!");
}
logger.debug("rootPath:" + rootPath);
//将存盘目录设置到request 作用域 在百度上传的类中读取
// request.setAttribute("uploadPath","");
/**
* 1.如果ContextPath为空,则rootPath+RequestURI的父级决定config.json位置
* 2.如果ContextPath为空不为空 originalPath = this.rootPath + uri.substring(contextPath.length());
* originalPath.getParentFile()+config.json即为最终完整config.json路径
*/
try {
String exec = new ActionEnter(new StorageManager(), request, rootPath, configPath).exec();
// exec:{"state": "SUCCESS","original": "\u5b9e\u9a8c\u75301.jpg","size": "42389","title": "1580809982781059908.jpg",
// "type": ".jpg","url": "/ueditor/jsp/upload/image/20200204/1580809982781059908.jpg"}
String ee = "{\"state\": \"SUCCESS\",\"original\": \"\\u5b9e\\u9a8c\\u75301.jpg\",\"size\": \"42389\",\"title\": \"1580809982781059908.jpg\",\n" +
" \"type\": \".jpg\",\"url\": \"/ueditor/jsp/upload/image/20200204/1580809982781059908.jpg\"}";
System.out.println("exec:" + exec);
JSONObject parse = JSON.parseObject(exec);
if(parse.containsKey("url")){
String oldUrl = parse.getString("url");
String urlNew="/ueditor/jsp/upload?filePath="+oldUrl;
parse.put("url",urlNew);
logger.debug("封装后的exec:"+parse);
}
PrintWriter writer = response.getWriter();
writer.write(parse.toJSONString());
writer.flush();
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
* @param session
* @return
*/
@ApiOperation("获取我的发布列表")
@RequestMapping("/mypublish/{pageNum}/{pageSize}")
@ResponseBody
public ResponseBean mypublish(@PathVariable Integer pageNum,@PathVariable Integer pageSize,
SysNews queryParam,HttpSession session) {
logger.debug("查询热门新闻列表参数:"+queryParam+",pageNum:"+pageNum+",pageSize:"+pageSize);
QueryWrapper<SysNews> queryWrapper=new QueryWrapper<>();
queryWrapper.eq("user_id",ToolsUtils.getLoginUserId(session));
IPage<SysNews> newsIPage = new Page<>(pageNum,pageSize);
IPage<SysNews> listPage = newsService.page(newsIPage, queryWrapper);
Map resultMap = ToolsUtils.wrapperResult(listPage, "mypublishList");
return ResultUtil.successData(resultMap);
}
@ApiOperation("获取热门新闻列表")
@RequestMapping("/hotlist/{pageNum}/{pageSize}")
@ResponseBody
public ResponseBean hotlist(@PathVariable Integer pageNum,@PathVariable Integer pageSize,
SysNews queryParam,String vagueParam) {
logger.debug("查询热门新闻列表参数:"+queryParam+",pageNum:"+pageNum+",pageSize:"+pageSize);
Date startTime=DateUtils.addMinute(new Date(),-10);
Date endTime=new Date();
List<SysNews> newsList = newsService.hotList(startTime, endTime);
logger.debug("获取的热门新闻列表:"+newsList);
IPage<SysNews> newsIPage = new Page<>(pageNum,pageSize);
newsIPage.setRecords(newsList);
Map resultMap = ToolsUtils.wrapperResult(newsIPage, "hotNewsList");
return ResultUtil.successData(resultMap);
}
@ApiOperation("获取系统特色新闻列表")
@RequestMapping("/featureList/{pageNum}/{pageSize}")
@ResponseBody
public ResponseBean featureList(@PathVariable Integer pageNum,@PathVariable Integer pageSize,
SysNews queryParam,String vagueParam) {
logger.debug("查询系统特色新闻列表参数:"+queryParam+",pageNum:"+pageNum+",pageSize:"+pageSize);
QueryWrapper<SysNews> queryWrapper=new QueryWrapper<>();
// 获取新闻分类id
Long categoryId = queryParam.getCategoryId();
if(categoryId==null){
queryParam.setCategoryId(1L);
/**
* <p>
* 新闻分类表 前端控制器
* </p>
*
*/
@Controller
@RequestMapping({"/category","/home/category"})
public class NewsCategoryController {
private static final Logger logger= LoggerFactory.getLogger(NewsCategoryController.class);
private static final String page_prefix="news/category/";
@Autowired
SysNewsService newsService;
@Autowired
NewsCategoryService categoryService;
/**
* 跳到添加页面
* @param model
* @return
*/
/**
* <p>
* 新闻评论表 前端控制器
* </p>
*
*/
@Controller
@RequestMapping({"/newsComment","/home/newsComment"})
public class NewsCommentController {
private static final Logger logger= LoggerFactory.getLogger(NewsCommentController.class);
private static final String page_prefix="news/comment/";
@Autowired
NewsCommentService commentService;
@Autowired
SysNewsService newsService;
/**
* 跳转列表页面
* @return
*/
@RequestMapping("/listPage")
public String listPage() {
return page_prefix+"list";
}
/**
* 添加用户评论
* @param comment
* @param session
* @return
*/
@RequestMapping("/add")
@ResponseBody
public ResponseBean add(NewsComment comment, HttpSession session){
//变量类型 变量名 = 类/对象 . 方法 方法入参
SysUser loginUser = ToolsUtils.getLoginUser(session);
//将loginUser的Id 设置为comment的userId
comment.setUserId(loginUser.getId());
comment.setUserName(loginUser.getName());
* 跳转列表页面
* @return
*/
@RequestMapping("/listPage")
public String listPage() {
return page_prefix+"list";
}
/**
* 新闻点赞列表查询
* @param pageNum 页码
* @param pageSize 每页大小
* @param queryParam 查询参数
* @param vagueParam 模糊参数
* @return
*/
@ApiOperation("获取新闻点赞列表")
@RequestMapping("/list/{pageNum}/{pageSize}")
@ResponseBody
public ResponseBean getList(@PathVariable Integer pageNum, @PathVariable Integer pageSize,
NewsFavor queryParam, String vagueParam) {
logger.debug("查询新闻点赞列表参数:"+queryParam+",pageNum:"+pageNum+",pageSize:"+pageSize);
QueryWrapper<NewsFavor> queryWrapper=new QueryWrapper<>();
String newsTitle = queryParam.getNewsTitle();
String userName = queryParam.getUserName();
queryWrapper.like(!StringUtils.isEmpty(newsTitle),"news_title",newsTitle)
.like(!StringUtils.isEmpty(userName),"user_name",userName);
IPage<NewsFavor> indexPage = new Page<>(pageNum, pageSize);
IPage<NewsFavor> listPage = favorService.page(indexPage, queryWrapper);
logger.debug("获取的新闻点赞列表:"+listPage);
//调用工具类对结果进行封装然后返回
Map resultMap = ToolsUtils.wrapperResult(listPage, "favorList");
return ResultUtil.successData(resultMap);
}
/**
* 批量删除点赞
* @param idList
* @return
*/
@RequestMapping("deleteBatchByIds")
@ResponseBody
public ResponseBean deleteBatchByIds(@RequestParam List<Long> idList){
logger.debug("deleteBatchByIds:"+idList);
in.read(body);
} catch (IOException e1) {
logger.debug("文件读入出错,文件路径为:"+fileUrl);
e1.printStackTrace();
}
//添加响应头
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Disposition", "attachment;filename="+fileName);
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
HttpStatus statusCode = HttpStatus.OK;
ResponseEntity<byte[]> response = new ResponseEntity<byte[]>(body, headers, statusCode);
return response;
}
//通用从classpath下载文件文件
@RequestMapping(value = "/export")
public ResponseEntity<byte[]> fileExport(String fileName){
byte [] body = null;
InputStream in=null;
try {
//获取到文件流
in = FileController.class.getClassLoader().getResourceAsStream(fileName);
if(in.available()<1){
in=new FileInputStream(new File(configJsonPath+File.separator+fileName));
}
logger.debug("需要导出的模板:{},获取的流为:{}",fileName,in);
body = new byte[in.available()];
logger.debug("导出模板大小:{},读入body大小:{}",in.available(),body.length);
in.read(body);
//添加响应头
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Disposition", "attachment;filename="+ URLEncoder.encode(fileName,"UTF-8"));
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
HttpStatus statusCode = HttpStatus.OK;
ResponseEntity<byte[]> response = new ResponseEntity<byte[]>(body, headers, statusCode);
return response;
} catch (Exception e) {
logger.error(e.getMessage(),e);
return null;
}finally {
try {
in.close();
} catch (IOException e) {
logger.error(e.getMessage(),e);
}
}
}
}
@RequestMapping("featureListPage")
public String featureListPage(String categoryId,Model model){
model.addAttribute("categoryId",StringUtils.isEmpty(categoryId)?"1":categoryId);
return "home/feature/list";
}
/**
* 跳到前台新闻发布页面
* @return
*/
@RequestMapping("homeAddPage")
public String homeAddPage(){
return "home/news/add";
}
//跳到前台热点新闻列表页面
@RequestMapping("/homeListPage")
public String homeListPage(){
return "home/news/list";
}
//跳到前台新闻图示列表页面
@RequestMapping("/homeListPicPage")
public String homeListPicPage(){
return "home/news/listpic";
}
//跳到前台新闻详情页面
/**
* @RequestMapping+return string ===返回到某个页面
* @param id
* @param model
* @param session
* @return
*/
@RequestMapping("/homeDetail/{id}")
public String homeDetail(@PathVariable Long id,Model model,HttpSession session){
SysNews news = newsService.getById(id);
model.addAttribute("news",news);
Long userId = news.getUserId();
//发布新闻的用户
SysUser newsUser = userService.getById(userId);
model.addAttribute("newsUser",newsUser);
return false;
}
/**
* 获取文件名的后缀
*
* @param file 表单文件
* @return 后缀名
*/
public static final String getExtension(MultipartFile file)
{
String extension = FilenameUtils.getExtension(file.getOriginalFilename());
if (StringUtils.isEmpty(extension)){
extension = MimeTypeUtils.getExtension(file.getContentType());
}
return extension;
}
/**
* 输出指定文件的byte数组
*
* @param filePath 文件路径
* @param os 输出流
* @return
*/
public static void writeBytes(String filePath, OutputStream os) throws IOException
{
FileInputStream fis = null;
try
{
File file = new File(filePath);
if (!file.exists())
{
throw new FileNotFoundException(filePath);
}
fis = new FileInputStream(file);
byte[] b = new byte[1024];
int length;
while ((length = fis.read(b)) > 0)
{
os.write(b, 0, length);
}
}
catch (IOException e)
{
throw e;
}
finally
{
if (os != null)
{
try
{
os.close();
/**
* #娱乐明星 4-20074
*
* #娱乐电影 4-20075
* #娱乐音乐 4-20077
*
*
*/
@Controller
@RequestMapping("grap")
public class GrapNewsController {
@Autowired
SysNewsService newsService;
@Autowired
SysUserService userService;
@Autowired
NewsCategoryService categoryService;
private static final Logger logger= LoggerFactory.getLogger(GrapNewsController.class);
//设置爬取网页
private static String baseUrlStar="https://ent.ifeng.com/star/";//娱乐·明星首页
private static String baseUrlMovie="https://ent.ifeng.com/movie/";//娱乐·电影首页
private static String baseUrlMusic="https://ent.ifeng.com/music/";//娱乐·音乐首页
//爬取文件存放路径
//
@Value("${com.cgx.file.baseFilePath}")
private String baseFilePath;
private static String yuleyiyueUrl="https://shankapi.ifeng.com/shanklist/_/getColumnInfo/_/default/{id}/{idTimeMills}/20/4-20077-/getColumnInfoCallback?callback=getColumnInfoCallback&_={currTimeMills}";
private static String yulestarUrl="https://shankapi.ifeng.com/shanklist/_/getColumnInfo/_/default/{id}/{idTimeMills}/20/4-20074-/getColumnInfoCallback?callback=getColumnInfoCallback&_={currTimeMills}";
private static String yulefilmUrl="https://shankapi.ifeng.com/shanklist/_/getColumnInfo/_/default/{id}/{idTimeMills}/20/4-20075-/getColumnInfoCallback?callback=getColumnInfoCallback&_={currTimeMills}";
private String defaultYuLeId="6760584714211311643";//娱乐音乐
private String defaultYuLeTimeMills="1611846336000";//娱乐音乐
private String defaultYuLeStarId="6776520715089744701";//娱乐明星
private String defaultYuLeStarTimeMills="1615739836000";//娱乐明星
private String defaultYuLeFilmId="6776324094754296302";//娱乐电影
private String defaultYuLeFilmTimeMills="1615604038000";//娱乐电影
logger.debug("配置文件配置的configJsonPath:"+configJsonPath);
String requestURL = request.getRequestURL().toString();
logger.debug("requestURL:"+requestURL);
logger.debug("RequestURI:"+request.getRequestURI());
logger.debug("ContextPath:"+request.getContextPath());
String rootPath = ClassUtils.getDefaultClassLoader().getResource("").getPath()+"static";
String configPath=request.getRequestURI();
if(requestURL.contains("127.0.0.1")||requestURL.contains("localhost")||requestURL.contains("192.168")){
logger.debug("本地环境");
}else{
rootPath=configJsonPath;
configPath="/test";//这里随便写
logger.debug("服务器环境,请将config.json放到"+rootPath+"的上一级下面!");
}
logger.debug("rootPath:" + rootPath);
//将存盘目录设置到request 作用域 在百度上传的类中读取
// request.setAttribute("uploadPath","");
/**
* 1.如果ContextPath为空,则rootPath+RequestURI的父级决定config.json位置
* 2.如果ContextPath为空不为空 originalPath = this.rootPath + uri.substring(contextPath.length());
* originalPath.getParentFile()+config.json即为最终完整config.json路径
*/
try {
String exec = new ActionEnter(new StorageManager(), request, rootPath, configPath).exec();
// exec:{"state": "SUCCESS","original": "\u5b9e\u9a8c\u75301.jpg","size": "42389","title": "1580809982781059908.jpg",
// "type": ".jpg","url": "/ueditor/jsp/upload/image/20200204/1580809982781059908.jpg"}
String ee = "{\"state\": \"SUCCESS\",\"original\": \"\\u5b9e\\u9a8c\\u75301.jpg\",\"size\": \"42389\",\"title\": \"1580809982781059908.jpg\",\n" +
" \"type\": \".jpg\",\"url\": \"/ueditor/jsp/upload/image/20200204/1580809982781059908.jpg\"}";
System.out.println("exec:" + exec);
JSONObject parse = JSON.parseObject(exec);
if(parse.containsKey("url")){
String oldUrl = parse.getString("url");
String urlNew="/ueditor/jsp/upload?filePath="+oldUrl;
parse.put("url",urlNew);
logger.debug("封装后的exec:"+parse);
}
PrintWriter writer = response.getWriter();
writer.write(parse.toJSONString());
writer.flush();
if ( callbackName != null ) {
if ( !validCallbackName( callbackName ) ) {
return new BaseState( false, AppInfo.ILLEGAL ).toJSONString();
}
return callbackName+"("+this.invoke()+");";
} else {
return this.invoke();
}
}
public String invoke() {
if ( actionType == null || !ActionMap.mapping.containsKey( actionType ) ) {
return new BaseState( false, AppInfo.INVALID_ACTION ).toJSONString();
}
if ( this.configManager == null || !this.configManager.valid() ) {
return new BaseState( false, AppInfo.CONFIG_ERROR ).toJSONString();
}
State state = null;
int actionCode = ActionMap.getType( this.actionType );
Map<String, Object> conf = null;
switch ( actionCode ) {
case ActionMap.CONFIG:
return this.configManager.getAllConfig().toString();
case ActionMap.UPLOAD_IMAGE:
case ActionMap.UPLOAD_SCRAWL:
case ActionMap.UPLOAD_VIDEO:
case ActionMap.UPLOAD_FILE:
conf = this.configManager.getConfig( actionCode );
state = new Uploader( request, conf ).doExec();
break;