基于javaweb和mysql的springboot博客论坛管理系统(java+springboot+jsp+layui+maven+mysql)(含设计报告)

私信源码获取及调试交流

私信源码获取及调试交流

运行环境

Java≥8、MySQL≥5.7

开发工具

eclipse/idea/myeclipse/sts等均可配置运行

适用

课程设计,大作业,毕业设计,项目练习,学习演示等

功能说明

基于javaweb的SpringBoot博客论坛管理系统(java+springboot+jsp+layui+maven+mysql)(含设计报告)

项目介绍

本系统分为管理员、游客两种角色; 管理员角色包含以下功能: 登录,用户增删改查,文章增删改查,链接增删改查,日志查看,查看近期数据,类别管理等功能。 游客角色包含以下功能:

首页,查看文章,注册账号,登录,管理自己写的文章,管理自己的文章,评论文章等功能。

环境需要

1.运行环境:最好是java jdk 1.8,我们在这个平台上运行的。其他版本理论上也可以。

2.IDE环境:IDEA,Eclipse,Myeclipse都可以。推荐IDEA;

3.硬件环境:windows 7/8/10 1G内存以上;或者 Mac OS;

4.数据库:MySql 5.7版本;

技术栈

  1. 后端:SpringBoot

  2. 前端:JSP+CSS+JavaScript+LayUI

使用说明

运行项目,在浏览器中输入http://localhost:8090/ 登录


        String figureurl = jsonObject.getString("figureurl_qq_1");

        userInfo.setAvatar(figureurl);

        return userInfo;
    }
}

@Controller
public class UserController {

    @Autowired
    private UserService userService;

    @Autowired
    private RoleService roleService;

    @Autowired
    private MailUtil mailUtil;

    @Value("${mail.href}")
    public String href;

    /**
     * 重新发送激活邮件
     * @param user
     * 微博 授权
     * @return
     */
    @RequestMapping("/authLoginCallback")

    public String authLoginCallback(HttpServletRequest request){
        try {
            String state = request.getParameter("state");
            String code = request.getParameter("code");
            String api = "https://api.weibo.com/oauth2/access_token";
            Map<String, String> data = new HashMap<String, String>();
            data.put("client_id", APP_ID);
            data.put("client_secret", APP_KEY);
            data.put("code", code);
            data.put("grant_type", "authorization_code");
            data.put("redirect_uri",  loginCallback);
            String result = HttpUtil.httpPostByKeyValue(api, data, null);

            JSONObject tokenInfo = JSONObject.parseObject(result);
            result = getUserInfo(tokenInfo.getString("access_token"),tokenInfo.getString("uid"));
            System.out.println(result);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     * 微博 取消授权
     * @return
     */
    @RequestMapping("/authReduceCallback")

    public String authReduceCallback(HttpServletRequest request){
        String state = request.getParameter("state");
        String code = request.getParameter("code");
        String api = "https://graph.qq.com/oauth2.0/token";
        Map<String, String> data = new HashMap<String, String>();
        data.put("client_id", APP_ID);
        data.put("client_secret", APP_KEY);
        data.put("code", code);
        data.put("grant_type", "authorization_code");
        data.put("redirect_uri", loginCallback);
        String result = null;
        try {
	    	if (str != null){
	    		try {
					return str.getBytes(CHARSET_NAME);
				} catch (UnsupportedEncodingException e) {
					return null;
				}
	    	}else{
	    		return null;
	    	}
	    }
	    
	    /**
	     * 转换为字节数组
	     */
	    public static String toString(byte[] bytes){
	    	try {
				return new String(bytes, CHARSET_NAME);
			} catch (UnsupportedEncodingException e) {
				return EMPTY;
			}
	    }
	    
	    /**
	     * 是否包含字符串
	     * @param str 验证字符串
	     * @param strs 字符串组
	     * @return 包含返回true
	     */
	    public static boolean inString(String str, String... strs){
	    	if (str != null){
	        	for (String s : strs){
	        		if (str.equals(trim(s))){
	        			return true;
	        		}
	        	}
	    	}
	    	return false;
	    }
	    
		/**
		 * 替换掉HTML标签方法
		 */
		public static String replaceHtml(String html) {
			if (isBlank(html)){
				return "";
			}
			String regEx = "<.+?>";
			Pattern p = Pattern.compile(regEx);
			Matcher m = p.matcher(html);
			String s = m.replaceAll("");
			return s;
		}

@Controller
@RequestMapping("/link")
public class LinkController {

    @Autowired
    private LinkService linkService;

    /**
     * 跳转到友情链接列表页
     * @return
     */
    @GetMapping("/list")
    @RequiresPermissions("base:link:views")
    public String list(){
        return Views.LINK_LIST;
    }

    /**
     * 友情链接搜索
     * @param page
     * @param link
     * @return
     */
    @PostMapping("/search")
    @RequiresPermissions("base:link:views")
    @ResponseBody
    public Page<Link> search(Page<Link> page,Link link){
        return linkService.findPageList(page,link);
    }

    /**
     * 删除友情链接
     * @param link
     * @return
     */
    @PostMapping("/delete")
    @RequiresPermissions("base:link:edit")
    @ResponseBody
    public String delete(Link link){
        link.setStatus("1");
        linkService.save(link);
        return "success";
    }

    /**
     * 批量删除
     * @param ids
     * @return
			}

			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));
				storageState.putInfo("type", suffix);
				storageState.putInfo("original", originFileName + suffix);
			}

			return storageState;
		} catch (FileUploadException e) {
			return new BaseState(false, AppInfo.PARSE_REQUEST_ERROR);
		} catch (IOException e) {
		}
		return new BaseState(false, AppInfo.IO_ERROR);
	}

	private static boolean validType(String type, String[] allowTypes) {
		List<String> list = Arrays.asList(allowTypes);

		return list.contains(type);
	}
}
	
	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;
				
			case ActionMap.CATCH_IMAGE:
				conf = configManager.getConfig( actionCode );
				String[] list = this.request.getParameterValues( (String)conf.get( "fieldName" ) );
				state = new ImageHunter( conf ).capture( list );
				break;
				
			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 class LogUtils {

	private static LogDao logDao = SpringContextHolder.getBean(LogDao.class);
	private static MenuDao menuDao = SpringContextHolder.getBean(MenuDao.class);

	/**
	 * 保存日志
	 */
	public static void saveLog(HttpServletRequest request, String title) {
		saveLog(request, null, null, title);
	}

	/**
	 * 保存日志
	 */
	public static void saveLog(HttpServletRequest request, Object handler, Exception ex, String title) {
		User Userinfo = UserUtils.getUser();
		if (Userinfo.getId() != 0) {
			Log log = new Log();
			log.setTitle(title);
			log.setType(ex == null ? Log.TYPE_ACCESS : Log.TYPE_EXCEPTION);
			log.setRemoteAddr(StringUtils.getRemoteAddr(request));
			log.setUserAgent(request.getHeader("user-agent"));
			log.setRequestUrl(request.getRequestURI());
			log.setParams(request.getParameterMap());
			log.setMethod(request.getMethod());
			// 异步保存日志
			new SaveLogThread(log, handler, ex).start();
		}
	}

	/**
	 * 保存日志线程
	 */
	public static class SaveLogThread extends Thread {

		private Log log;
		private Object handler;
		private Exception ex;

		public SaveLogThread(Log log, Object handler, Exception ex) {
     */
    @PostMapping("/search")
    @RequiresPermissions("base:link:views")
    @ResponseBody
    public Page<Link> search(Page<Link> page,Link link){
        return linkService.findPageList(page,link);
    }

    /**
     * 删除友情链接
     * @param link
     * @return
     */
    @PostMapping("/delete")
    @RequiresPermissions("base:link:edit")
    @ResponseBody
    public String delete(Link link){
        link.setStatus("1");
        linkService.save(link);
        return "success";
    }

    /**
     * 批量删除
     * @param ids
     * @return
     */
    @PostMapping("/bathDelete")
    @RequiresPermissions("base:link:del")
    @ResponseBody
    public String bathDelete(@RequestParam("ids[]") String[] ids){
        linkService.bathDelete(ids);
        return "success";
    }

    /**
     * 更新链接
     */
    @RequiresPermissions("base:link:edit")
    @PostMapping("/update")
    @ResponseBody
    public String update(Link link){
        linkService.save(link);
        return "success";
    }

    /**
     * 添加链接
     * @param link
     */
    private String getRequestUrl(ServletRequest request) {
        HttpServletRequest req = (HttpServletRequest)request;
        String queryString = req.getQueryString();
        queryString = StringUtils.isBlank(queryString)?"": "?"+queryString;
        return req.getRequestURI()+queryString;
    }
}

@Controller
public class UploadController {

    @PostMapping("/file/upload")
    @ResponseBody
    public JSONObject uploadImg(@RequestParam("file") MultipartFile file,
                                HttpServletRequest request) {
        String filePath = request.getSession().getServletContext().getRealPath("upload/");
        String date=new SimpleDateFormat("yyyyMMdd").format(new Date());
        String reName=date+"/"+UUID.randomUUID()+".jpg";
        String str="";
        try {
            File targetFile = new File(filePath+date);
            if(!targetFile.exists()){
                targetFile.mkdirs();
            }
            FileOutputStream out = new FileOutputStream(filePath+reName);
            out.write(file.getBytes());
            out.flush();
            out.close();
            str=String.format("{code:0,msg:'success',data:{src:'/upload/%s'}}",reName);
        } catch (Exception e) {
            str="{msg:'接口调用异常'}";
            e.printStackTrace();
        }
        return JSON.parseObject(str);
    }
		/**
		 * 替换为手机识别的HTML,去掉样式及属性,保留回车。
		 * @param html
		 * @return
		 */
		public static String replaceMobileHtml(String html){
			if (html == null){
				return "";
			}
			return html.replaceAll("<([a-z]+?)\\s+?.*?>", "<$1>");
		}
		
		/**
		 * 替换为手机识别的HTML,去掉样式及属性,保留回车。
		 * @param txt
		 * @return
		 */
	/*	public static String toHtml(String txt){
			if (txt == null){
				return "";
			}
			return replace(replace(Encodes.escapeHtml(txt), "\n", "<br/>"), "\t", "&nbsp; &nbsp; ");
		}*/

		/**
		 * 缩略字符串(不区分中英文字符)
		 * @param str 目标字符串
		 * @param length 截取长度
		 * @return
		 */
		public static String abbr(String str, int length) {
			if (str == null) {
				return "";
			}
			try {
				StringBuilder sb = new StringBuilder();
				int currentLength = 0;
				for (char c : replaceHtml(StringEscapeUtils.unescapeHtml4(str)).toCharArray()) {
					currentLength += String.valueOf(c).getBytes("GBK").length;
					if (currentLength <= length - 3) {
						sb.append(c);
					} else {
						sb.append("...");
						break;
					}
				}
				return sb.toString();
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
			return "";
		}
		
		public static String abbr2(String param, int length) {
			// 保存日志信息
			log.preInsert();
			logDao.insert(log);
		}
	}

	/**
	 * 获取菜单名称路径(如:系统设置-机构用户-用户管理-编辑)
	 */
	public static String getMenuinfoNamePath(String requestUrl, String permission) {
		String title=(String) CacheUtils.get(CacheNames.MENU_CACHE,requestUrl+permission);
		if (title==null){
			Menu menu=new Menu();
			menu.setPermission(permission);
			menu.setUrl(requestUrl);
			title=menuDao.getMenuinfoNamePath(menu);
			CacheUtils.put(CacheNames.MENU_CACHE,requestUrl+permission,title);
		}
		return title;
	}
}

/**
 * 登录管理页
 */
@Controller
public class LoginController {

    @Autowired
    private UserService userService;

    /**
     * 跳转到登录页
     */
				
			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;
		
	}
	
}

						}else{
							break;
						}
					}
					projectPath = file.toString();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
			return projectPath;
	    }
	    
	    /**
	     * 如果不为空,则设置值
	     * @param target
	     * @param source
	     */
	    public static void setValueIfNotBlank(String target, String source) {
			if (isNotBlank(source)){
				target = source;
			}
		}
	 
	    /**
	     * 转换为JS获取对象值,生成三目运算返回结果
	     * @param objectString 对象串
	     *   例如:row.user.id
	     *   返回:!row?'':!row.user?'':!row.user.id?'':row.user.id
	     */
	    public static String jsGetVal(String objectString){
	    	StringBuilder result = new StringBuilder();
	    	StringBuilder val = new StringBuilder();
	    	String[] vals = split(objectString, ".");
	    	for (int i=0; i<vals.length; i++){
	    		val.append("." + vals[i]);
	    		result.append("!"+(val.substring(1))+"?'':");
	    	}
	    	result.append(val.substring(1));
	    	return result.toString();
	    }
	    
	
}

	 * @return
	 */
	@GetMapping("/register")
	public String register(){
		return Views.REGISTER;
	}

	/**
	 * 注册
	 * @param user
	 * @param model
	 * @return
	 */
	@PostMapping("/register")
	public String addUser(User user, Model model){
		User user1 = userService.findByAccount(user.getUsername());
		User user2 = userService.findByAccount(user.getEmail());
		if(user1==null&&user2==null){
			//设置Gravatar图片链接
			String gravatarImg = "/static/images/qqtouxiang.jpg";
			//设置激活码code
			String code = UUID.randomUUID().toString();
			user.setAvatar(gravatarImg);
			user.setCode(code);
			user.setPassword(MD5.md5(user.getUsername(),user.getPassword()));
			//            user.setStatus(User.STATUS_AUDIT);
			//            userService.save(user);
			//            mailUtil.sendHtmlMail(new String[]{user.getEmail()},"hblog账户激活邮件","<h1>请点击<a href='"+href+"activate/"+code+"'>此链接</a>以激活账号</h1>");
			//            model.addAttribute("msg","٩(๑❛ᴗ❛๑)۶注册成功,激活邮件已经发送到您的邮箱请及时激活!");
			user.setStatus(User.STATUS_NORMAL);
			userService.save(user);
			String[] roleIds={"1","5"};
			roleService.insertUserRole(user.getId(),roleIds);
			model.addAttribute("msg","٩(๑❛ᴗ❛๑)۶注册成功");
			return Views.SUCCESS;
		}else{
			model.addAttribute("msg","o(╥﹏╥)o用户名或邮箱存在,注册失败");
			return Views.REGISTER;
		}
	}

	/**
	 * 用户账号激活
        Map<String, String> data = new HashMap<String, String>();
        data.put("client_id", APP_ID);
        data.put("client_secret", APP_KEY);
        data.put("code", code);
        data.put("grant_type", "authorization_code");
        data.put("redirect_uri", loginCallback);
        String result = null;
        try {
            result = HttpUtil.httpPostByKeyValue(api, data, null);
            System.out.println(result);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     * 获取用户信息
     * @param accessToken
     * @param uid
     * @return
     * @throws IOException
     */
    private String getUserInfo(String accessToken,String uid) throws IOException {
        String api = "https://api.weibo.com/2/users/show.json";
        Map<String, String> data = new HashMap<String, String>();
        data.put("access_token", accessToken);
        data.put("uid", uid);
        String result = HttpUtil.httpGet(api, data, null);
        return result;
    }
}

	
	private HttpServletRequest request = null;
	
	private String rootPath = null;
	private String contextPath = null;
	
	private String actionType = null;
	
	private ConfigManager configManager = null;

	public ActionEnter ( HttpServletRequest request, String rootPath ) {
		
		this.request = request;
		this.rootPath = rootPath;
		this.actionType = request.getParameter( "action" );
		this.contextPath = request.getContextPath();
		this.configManager = ConfigManager.getInstance( this.rootPath, this.contextPath, request.getRequestURI() );
		
	}
	
	public String exec () {
		
		String callbackName = this.request.getParameter("callback");
		
		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();
				}
				log.setTitle(getMenuinfoNamePath(log.getRequestUrl(), permission));
			}
			// 如果有异常,设置异常信息
			if (ex == null) {
				log.setException("");
			} else {
				StringWriter stringWriter = new StringWriter();
				ex.printStackTrace(new PrintWriter(stringWriter));
				log.setException(stringWriter.toString());
			}
			// 如果无标题并无异常日志,则不保存信息
			if (StringUtils.isBlank(log.getTitle()) && StringUtils.isBlank(log.getException())) {
				return;
			}
			// 保存日志信息
			log.preInsert();
			logDao.insert(log);
		}
	}

	/**
	 * 获取菜单名称路径(如:系统设置-机构用户-用户管理-编辑)
	 */
	public static String getMenuinfoNamePath(String requestUrl, String permission) {
		String title=(String) CacheUtils.get(CacheNames.MENU_CACHE,requestUrl+permission);
		if (title==null){
			Menu menu=new Menu();
			menu.setPermission(permission);
			menu.setUrl(requestUrl);
			title=menuDao.getMenuinfoNamePath(menu);
			CacheUtils.put(CacheNames.MENU_CACHE,requestUrl+permission,title);
		}
		return title;
	}
}

请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述

更多推荐