基于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 访问
/**
* <p>
* 用户点赞表 前端控制器
* </p>
*
*/
@Controller
@RequestMapping({"/newsFavor","/home/newsFavor"})
public class NewsFavorController {
private static final Logger logger= LoggerFactory.getLogger(NewsFavorController.class);
private static final String page_prefix="news/favor/";
@Autowired
NewsFavorService favorService;
@Autowired
SysNewsService newsService;
//前端页面进行点赞和取赞 action 1 关注;2 取关
@RequestMapping("updateFavor")
@ResponseBody
public ResponseBean updateFavor(NewsFavor favor, Long action, HttpSession session){
SysUser loginUser = ToolsUtils.getLoginUser(session);
Long newsId = favor.getNewsId();
SysNews news = newsService.getById(newsId);
if (action==1){
//进行点赞
favor.setNewsTitle(news.getTitle());
favor.setUserId(loginUser.getId());
favor.setUserName(loginUser.getName());
favorService.save(favor);
}else if(action==2){
QueryWrapper<NewsFavor> wrapper=new QueryWrapper();
wrapper.eq("news_id",newsId).eq("user_id",loginUser.getId());
favorService.remove(wrapper);
}
return ResultUtil.success();
filename = URLEncoder.encode(filename, "utf-8");
filename = filename.replace("+", " ");
}
else if (agent.contains("Firefox"))
{
// 火狐浏览器
filename = new String(fileName.getBytes(), "ISO8859-1");
}
else if (agent.contains("Chrome"))
{
// google浏览器
filename = URLEncoder.encode(filename, "utf-8");
}
else
{
// 其它浏览器
filename = URLEncoder.encode(filename, "utf-8");
}
return filename;
}
}
@Controller
@RequestMapping("/common/plugs/ueditor/jsp")
public class UeditorController {
private static final Logger logger= LoggerFactory.getLogger(UeditorController.class);
/**
* 读取配置的请求
* @param request
* @param response
@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,
UserAttention queryParam, String vagueParam) {
logger.debug("查询用户关注列表参数:"+queryParam+",pageNum:"+pageNum+",pageSize:"+pageSize);
QueryWrapper<UserAttention> queryWrapper=new QueryWrapper<>();
String fromUserName = queryParam.getFromUserName();
String toUserName = queryParam.getToUserName();
queryWrapper.like(!StringUtils.isEmpty(fromUserName),"from_user_name",fromUserName)
.like(!StringUtils.isEmpty(toUserName),"to_user_name",toUserName);
IPage<UserAttention> indexPage = new Page<>(pageNum, pageSize);
IPage<UserAttention> listPage = attentionService.page(indexPage, queryWrapper);
logger.debug("获取的用户关注列表:"+listPage);
//调用工具类对结果进行封装然后返回
Map resultMap = ToolsUtils.wrapperResult(listPage, "attentionList");
return ResultUtil.successData(resultMap);
}
/**
* 批量删除关注
* @param idList
* @return
*/
@RequestMapping("deleteBatchByIds")
@ResponseBody
public ResponseBean deleteBatchByIds(@RequestParam List<Long> idList){
@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 = fileService.removeById(id);
logger.debug("删除结果:"+delete);
return new ResponseBean<Map<String, Object>>(true, null, CommonEnum.SUCCESS_REQUEST);
}
@RequestMapping(value = "deleteBatchByIds",method = {RequestMethod.POST,RequestMethod.GET})
@ResponseBody
public ResponseBean deleteBatchByIds(@RequestParam List<Integer> idList){
logger.debug("deleteBatchByIds:"+idList);
if(idList==null||idList.isEmpty()){
return new ResponseBean(false,CommonEnum.BAD_REQUEST);
}
boolean delete = fileService.removeByIds(idList);
logger.debug("批量删除结果:"+delete);
return ResultUtil.success() ;
}
/**
* 分页列表查询
* @param pageNum 页码
* @param pageSize 每页大小
* @param queryParam 查询参数
* @return
*/
@RequestMapping("/list/{pageNum}/{pageSize}")
@ResponseBody
public ResponseBean getList(@PathVariable Integer pageNum, @PathVariable Integer pageSize, SysFile queryParam) {
logger.debug("查询列表参数:"+queryParam+",pageNum:"+pageNum+",pageSize:"+pageSize);
IPage<SysFile> indexPage = new Page<>(pageNum, pageSize);
Map<String, Object> objectMap = ToolsUtils.convertObjToMap(queryParam);
QueryWrapper<SysFile> queryWrapper=new QueryWrapper<>();
queryWrapper.allEq(objectMap,false);
IPage<SysFile> page = fileService.page(indexPage,queryWrapper);
logger.debug("获取的列表:"+page);
Matcher m = p.matcher(tempalte);
StringBuffer content = new StringBuffer();
while (m.find()) {
System.out.println(m.group(1));
String key = m.group(2);
String value = "";
if (param.containsKey(key)) {
value = param.getString(key);
} else {
logger.debug("缺少key{}对应的值",key);
continue;
}
m.appendReplacement(content, value);
}
m.appendTail(content);
return content.toString();
}
}
/**
{
"id": "6770174400034509711",
"title": "新歌歌词被指不尊重科比,米克•米尔私下向瓦妮莎道歉",
"url": "https://ent.ifeng.com/c/847TAu2Jlst",
"skey": "dd25e3",
"source": "",
"type": "article",
"commentUrl": "ucms_847TAu2Jlst",
"thumbnails": {
"image": [
{
"width": "230",
"height": "152",
"url": "https://x0.ifengimg.com/ucms/2021_09/C6177B086368D3494B1AF436663B4BA719AF74D9_size73_w230_h152.png",
"kbs": "",
"small": {
"_proto": {
"_classname": "int32"
},
"_bValue": 0,
"value": [
],
"_classname": "List<int32>"
},
"big": {
"_proto": {
"_classname": "int32"
},
"_bValue": 0,
"value": [
* @param idList
* @return
*/
@RequestMapping("deleteBatchByIds")
@ResponseBody
public ResponseBean deleteBatchByIds(@RequestParam List<Long> idList){
logger.debug("deleteBatchByIds:"+idList);
if(idList==null||idList.isEmpty()){
return ResultUtil.error(CommonEnum.BAD_PARAM);
}
boolean delete = attentionService.removeByIds(idList);
logger.debug("批量删除结果:"+delete);
return ResultUtil.success() ;
}
@RequestMapping("deleteById")
@ResponseBody
public ResponseBean deleteById(@RequestParam Long id){
if(id==null||id<0){
return ResultUtil.error(CommonEnum.BAD_PARAM);
}
boolean delete = attentionService.removeById(id);
return ResultUtil.success() ;
}
}
/**
* 文件处理工具类
*/
public class FileUtils {
// 创建一个正则表达式,一个非空的字符串,字符是包含数字字母汉字
public static String FILENAME_PATTERN = "[a-zA-Z0-9_\\-\\|\\.\\u4e00-\\u9fa5]+";
/**
* 判断MIME类型是否是允许的MIME类型
* @param extension
* @param allowedExtension
* @return
*/
public static final boolean isAllowedExtension(String extension, String[] allowedExtension)
{
for (String str : allowedExtension)
{
if (str.equalsIgnoreCase(extension))
{
return true;
}
}
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
@ResponseBody
public ResponseBean deleteBatchByIds(@RequestParam List<Long> idList){
logger.debug("deleteBatchByIds:"+idList);
if(idList==null||idList.isEmpty()){
return ResultUtil.error(CommonEnum.BAD_PARAM);
}
boolean delete = favorService.removeByIds(idList);
logger.debug("批量删除结果:"+delete);
return ResultUtil.success() ;
}
@RequestMapping("deleteById")
@ResponseBody
public ResponseBean deleteById(@RequestParam Long id){
if(id==null||id<0){
return ResultUtil.error(CommonEnum.BAD_PARAM);
}
boolean delete = favorService.removeById(id);
return ResultUtil.success() ;
}
}
/**
* 文件处理工具类
*/
public class FileUtils {
// 创建一个正则表达式,一个非空的字符串,字符是包含数字字母汉字
public static String FILENAME_PATTERN = "[a-zA-Z0-9_\\-\\|\\.\\u4e00-\\u9fa5]+";
/**
* 判断MIME类型是否是允许的MIME类型
* @param extension
* @param allowedExtension
* @return
*/
public static final boolean isAllowedExtension(String extension, String[] allowedExtension)
String[] data = element.data().toString().split("var");
/*取得单个JS变量*/
for (String variable : data) {
/*过滤variable为空的数据*/
if (variable.contains("=")) {
/*取到满足条件的JS变量*/
if (variable.contains("allData")) {
String[] kvp = variable.split("allData");
String dataVal = kvp[1];
String trimData = dataVal.trim();
String substring = trimData.substring(2, trimData.length() - 1);
logger.debug(substring);
JSONObject parseObject = JSONObject.parseObject(substring);
JSONObject firstObj = parseObject.getJSONArray("newsstream").getJSONObject(0);
logger.debug("最新的消息为:{}",firstObj);
String id = firstObj.getString("id");
Date newsTime = firstObj.getDate("newsTime");
JSONObject object=new JSONObject();
object.put("id",id);
object.put("idTimeMills",DateUtils.getTimeMillis(newsTime));
return object;
}
}
}
}
return null;
}
//获取网络图片保存到本地
private String saveFileByUrl(String imgUrl) {
FileOutputStream out = null;
BufferedInputStream in = null;
HttpURLConnection connection = null;
byte[] buf = new byte[1024];
int len = 0;
String saveFileName= UUID.randomUUID().toString().replaceAll("-","")+".jpg";
try {
URL url = new URL(imgUrl);
connection = (HttpURLConnection)url.openConnection();
connection.connect();
in = new BufferedInputStream(connection.getInputStream());
out = new FileOutputStream(baseFilePath+ File.separator+saveFileName);
while ((len = in.read(buf)) != -1) {
out.write(buf, 0, len);
}
out.flush();
}
@RequestMapping(value = "deleteBatchByIds",method = {RequestMethod.POST,RequestMethod.GET})
@ResponseBody
public ResponseBean deleteBatchByIds(@RequestParam List<Integer> idList){
logger.debug("deleteBatchByIds:"+idList);
if(idList==null||idList.isEmpty()){
return new ResponseBean(false,CommonEnum.BAD_REQUEST);
}
boolean delete = fileService.removeByIds(idList);
logger.debug("批量删除结果:"+delete);
return ResultUtil.success() ;
}
/**
* 分页列表查询
* @param pageNum 页码
* @param pageSize 每页大小
* @param queryParam 查询参数
* @return
*/
@RequestMapping("/list/{pageNum}/{pageSize}")
@ResponseBody
public ResponseBean getList(@PathVariable Integer pageNum, @PathVariable Integer pageSize, SysFile queryParam) {
logger.debug("查询列表参数:"+queryParam+",pageNum:"+pageNum+",pageSize:"+pageSize);
IPage<SysFile> indexPage = new Page<>(pageNum, pageSize);
Map<String, Object> objectMap = ToolsUtils.convertObjToMap(queryParam);
QueryWrapper<SysFile> queryWrapper=new QueryWrapper<>();
queryWrapper.allEq(objectMap,false);
IPage<SysFile> page = fileService.page(indexPage,queryWrapper);
logger.debug("获取的列表:"+page);
Map fileList = ToolsUtils.wrapperResult(page, "fileList");
return ResultUtil.successData(fileList);
}
/**
* 文件上传后删除所属对象的原先文件
* @param sysFile
* @param file
* @return
// private
// 用于返回查询页面
@RequestMapping("/checklist")
public String checklist(){
return "checknews/checklist";
}
/**
* 新闻审核列表查询
* @param pageNum 页码
* @param pageSize 每页大小
* @param queryParam 查询参数
* @param vagueParam 模糊参数
* @return
*/
@ApiOperation("获取新闻审核列表")
@RequestMapping("/list/{pageNum}/{pageSize}")
@ResponseBody
public ResponseBean getList(@PathVariable Integer pageNum, @PathVariable Integer pageSize, CheckNews queryParam, String vagueParam) {
logger.debug("查询新闻列表参数:"+queryParam+",pageNum:"+pageNum+",pageSize:"+pageSize);
QueryWrapper<CheckNews> queryWrapper=new QueryWrapper<>();
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);
/**
* 跳转列表页面
* @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 每页大小
* @param queryParam 查询参数
* @param vagueParam 模糊参数
* @return
*/
@ApiOperation("获取新闻评论列表")
@RequestMapping("/list/{pageNum}/{pageSize}")
@ResponseBody
* @return
*/
@RequestMapping("addPage")
public String addPage(Model model){
return page_prefix+"add";
}
//新闻分类添加
@RequestMapping("add")
@ResponseBody
public ResponseBean addNews(NewsCategory category, HttpSession session){
logger.debug("addNewsCategory:"+category);
String name = category.getName();
String code = category.getCode();
QueryWrapper<NewsCategory> queryWrapper=new QueryWrapper<>();
queryWrapper.like("code",code).like("name",name);
List<NewsCategory> list = categoryService.list(queryWrapper);
if(!ToolsUtils.isEmpty(list)){
return ResultUtil.error("名称或编码已经存在!");
}
boolean i = categoryService.save(category);
logger.debug("保存后的NewsCategory:"+category);
return ResultUtil.successData(category);
}
/**
* 跳转到修改页面
* @param id
* @param model
* @return
*/
@RequestMapping("/editPage/{id}")
public String editPage(@PathVariable Long id, Model model) {
model.addAttribute("category", categoryService.getById(id));
return page_prefix+"edit";
}
/**
* 新闻分类修改
* @param category
* @return
*/
@RequestMapping("/edit")
@ResponseBody
public ResponseBean updateById(NewsCategory category,HttpSession session) {
if (category == null||category.getId()==null) {
return ResultUtil.error(CommonEnum.BAD_PARAM);
}
String name = category.getName();
String code = category.getCode();
case ActionMap.LIST_IMAGE:
case ActionMap.LIST_FILE:
conf = configManager.getConfig( actionCode );
int start = this.getStartIndex();
state = new FileManager( conf ).listFile( start );
break;
}
return state.toJSONString();
}
public int getStartIndex () {
String start = this.request.getParameter( "start" );
try {
return Integer.parseInt( start );
} catch ( Exception e ) {
return 0;
}
}
/**
* callback参数验证
*/
public boolean validCallbackName ( String name ) {
if ( name.matches( "^[a-zA-Z_]+[\\w0-9_]*$" ) ) {
return true;
}
return false;
}
}
SysUser loginUser = ToolsUtils.getLoginUser(session);
QueryWrapper<SysUser> queryWrapper=new QueryWrapper<>();
if(loginUser.getType()!=0){
//非管理员则只查看自己的用户信息
queryWrapper.eq("type",loginUser.getType());
}
logger.debug("查询用户列表参数:"+queryParam+",pageNum:"+pageNum+",pageSize:"+pageSize);
queryWrapper.eq(!StringUtils.isEmpty(queryParam.getCode()),"code",queryParam.getCode());
queryWrapper.and(e->e.like("name",vagueParam).or().like("mobile",vagueParam));
IPage<SysUser> indexPage = new Page<>(pageNum, pageSize);
IPage<SysUser> page = userService.page(indexPage, queryWrapper);
logger.debug("获取的用户列表:"+page);
//获取分页信息
Map<String, Object> pageInfo = new HashMap<String, Object>();
pageInfo.put("pageSize", page.getSize());
pageInfo.put("pageNum", page.getCurrent());
pageInfo.put("pages", page.getPages());
pageInfo.put("total", page.getTotal());
Map<String, Object> resultMap = new HashMap<String, Object>();
resultMap.put("userList", page.getRecords());
resultMap.put("pageInfo", pageInfo);
return new ResponseBean<Map<String, Object>>(true, resultMap, CommonEnum.SUCCESS_REQUEST);
}
//修改用户状态
@RequestMapping("updateState")
@ResponseBody
public ResponseBean updateState(Long id,Integer state){
SysUser user = userService.getById(id);
user.setState(state);
userService.updateById(user);
return ResultUtil.successData(user);
}
//批量删除用户
@RequestMapping("deleteBatchByIds")
@ResponseBody
public ResponseBean deleteBatchByIds(@RequestParam List<Integer> idList){
logger.debug("deleteBatchByIds:"+idList);
if(idList==null||idList.isEmpty()){
return new ResponseBean(false,CommonEnum.BAD_REQUEST);
}
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);
@ResponseBody
public ResponseBean fileUpload(SysFile sysFile, MultipartFile file){
if(sysFile==null||file==null||file.isEmpty()){
logger.debug("文件上传参数不对!");
return new ResponseBean(false, CommonEnum.BAD_REQUEST);
}
SysFile uploadFile = fileService.saveOrUpdateFile(sysFile, file);
if(uploadFile==null){
return new ResponseBean(false,CommonEnum.BAD_REQUEST);
}
return new ResponseBean(true,uploadFile,CommonEnum.SUCCESS_OPTION);
}
/**
* 只上传文件,返回保存的文件对象,并不会对原先文件进行删除
* @param sysFile
* @param file
* @return
*/
@ApiOperation(value="文件上传并返回保存的文件对象")
@RequestMapping(value = "/uploadOnly",method = {RequestMethod.POST})
@ResponseBody
public ResponseBean fileUploadOnly(SysFile sysFile, @RequestParam(value = "file",required = true) MultipartFile file){
if(sysFile==null||file==null||file.isEmpty()){
logger.debug("文件上传参数不对!");
return new ResponseBean(false, CommonEnum.BAD_REQUEST);
}
String originalFilename = file.getOriginalFilename();
String extendName = originalFilename.substring(originalFilename.lastIndexOf("."));
long size = file.getSize();
logger.debug("file.getResource:"+file.getResource());
String saveFileName= UUID.randomUUID().toString().replaceAll("-","")+extendName;
File saveFile=new File(baseFilePath+File.separator+saveFileName);
if(!saveFile.getParentFile().exists()){
saveFile.getParentFile().mkdirs();
}
try {
//保存文件到最终路径
file.transferTo(saveFile);
} catch (IOException e) {
FileItemStream fileStream = null;
boolean isAjaxUpload = request.getHeader( "X_Requested_With" ) != null;
if (!ServletFileUpload.isMultipartContent(request)) {
return new BaseState(false, AppInfo.NOT_MULTIPART_CONTENT);
}
ServletFileUpload upload = new ServletFileUpload(
new DiskFileItemFactory());
if ( isAjaxUpload ) {
upload.setHeaderEncoding( "UTF-8" );
}
try {
FileItemIterator iterator = upload.getItemIterator(request);
while (iterator.hasNext()) {
fileStream = iterator.next();
if (!fileStream.isFormField())
break;
fileStream = null;
}
if (fileStream == null) {
return new BaseState(false, AppInfo.NOTFOUND_UPLOAD_DATA);
}
String savePath = (String) conf.get("savePath");
String originFileName = fileStream.getName();
String suffix = FileType.getSuffixByFilename(originFileName);
originFileName = originFileName.substring(0,
originFileName.length() - suffix.length());
savePath = savePath + suffix;
long maxSize = ((Long) conf.get("maxSize")).longValue();
if (!validType(suffix, (String[]) conf.get("allowFiles"))) {
return new BaseState(false, AppInfo.NOT_ALLOW_FILE_TYPE);
}
savePath = PathFormat.parse(savePath, originFileName);
String physicalPath = (String) conf.get("rootPath") + savePath;
InputStream is = fileStream.openStream();
State storageState = StorageManager.saveFileByInputStream(is,
physicalPath, maxSize);
is.close();
if (storageState.isSuccess()) {
storageState.putInfo("url", PathFormat.format(savePath));