天天看点

Java项目:在线博客问答系统(java+Springboot+jsp+maven+mysql)

文章目录

  • ​​前言​​
  • ​​一、框架介绍​​
  • ​​1.1、Spring​​
  • ​​1.2、SpringMVC​​
  • ​​1.3、MyBatis​​
  • ​​1.4、SSM整合​​
  • ​​二、开发环境​​
  • ​​三、系统功能​​
  • ​​3.1 文章列表​​
  • ​​3.2 点赞评论​​
  • ​​3.3 在线问答​​
  • ​​3.4 提问题​​
  • ​​3.5 后台管理员主界面​​
  • ​​3.6 文章列表管理​​
  • ​​3.7 问答列表管理​​
  • ​​3.8 全站消息发送​​
  • ​​四、部分代码展示​​
  • ​​4.1.login.jsp​​
  • ​​4.2 点赞记录​​
  • ​​4.2 .1 Controller​​
  • ​​4.2.2 Service​​
  • ​​4.2.3 ServiceImpl​​
  • ​​4.2.4 dao​​
  • ​​4.2.5 UserMapper​​
  • ​​五 、框架其他配置​​
  • ​​5.1 数据库配置​​
  • ​​5.2、配置spring-mvc.xml​​
  • ​​5.3 Log4j的配置​​
  • ​​5.4 数据库表结构​​

前言

最近正好在带徒弟做项目,也有很多网友再问,能否个共享一些框架,所以整理了下 把最近部署上线的一套学Spring+SpringMVC+MyBatis的博客问答系统框架分享给各位网友 希望给各位大学僧,网友一些帮助,我是一个乐于分享的人,大家点赞关注哈

一、框架介绍

1.1、Spring

Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,
由Rod Johnson 在其著作Expert One-On-One J2EE Development and Design中阐述的部分理念和原型衍生而来。
它是为了解决企业应用开发的复杂性而创建的。
Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅限于服务器端的开发。
从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益。
 简单来说,Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架      

1.2、SpringMVC

Spring MVC属于SpringFrameWork的后续产品,
  已经融合在Spring Web Flow里面。
  Spring MVC 分离了控制器、模型对象、分派器以及处理程序对象的角色,
  这种分离让它们更容易进行定制。      
Java项目:在线博客问答系统(java+Springboot+jsp+maven+mysql)

1.3、MyBatis

MyBatis 本是apache的一个开源项目iBatis, 
2010年这个项目由apache software foundation 迁移到了google code,
并且改名为MyBatis 。MyBatis是一个基于Java的持久层框架。
iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAO)
MyBatis 消除了几乎所有的JDBC代码和参数的手工设置以及结果集的检索。
MyBatis 使用简单的 XML或注解用于配置和原始映射,
将接口和 Java 的POJOs(Plain Old Java Objects,
普通的 Java对象)映射成数据库中的记录。      

1.4、SSM整合

这次整合我分了2个配置文件,分别是spring-mybatis.xml,
包含spring和mybatis的配置文件,还有个是spring-mvc的配置文件,
此外有2个资源文件:jdbc.propertis和log4j.properties。      

完整目录结构如下:

Java项目:在线博客问答系统(java+Springboot+jsp+maven+mysql)

二、开发环境

开发语言:Java
技术:JavaWeb【Servlet】
数据库:MySQL
架构:B/S
源码类型: Web
编译工具:Idea、Eclipse、MyEclipse (选其一)
其他:jdk1.8、Tomcat5.7 、Navicat

使用框架的版本:
Spring 3.2.12 RELEASE
Spring MVC 4.0.2 RELEASE
MyBatis 3.2.6      

三、系统功能

3.1 文章列表

Java项目:在线博客问答系统(java+Springboot+jsp+maven+mysql)

3.2 点赞评论

Java项目:在线博客问答系统(java+Springboot+jsp+maven+mysql)
Java项目:在线博客问答系统(java+Springboot+jsp+maven+mysql)

支持重复点赞过滤,防止刷点击率

Java项目:在线博客问答系统(java+Springboot+jsp+maven+mysql)

3.3 在线问答

Java项目:在线博客问答系统(java+Springboot+jsp+maven+mysql)

3.4 提问题

Java项目:在线博客问答系统(java+Springboot+jsp+maven+mysql)
Java项目:在线博客问答系统(java+Springboot+jsp+maven+mysql)

3.5 后台管理员主界面

Java项目:在线博客问答系统(java+Springboot+jsp+maven+mysql)

3.6 文章列表管理

Java项目:在线博客问答系统(java+Springboot+jsp+maven+mysql)

3.7 问答列表管理

Java项目:在线博客问答系统(java+Springboot+jsp+maven+mysql)

3.8 全站消息发送

Java项目:在线博客问答系统(java+Springboot+jsp+maven+mysql)

四、部分代码展示

4.1.login.jsp

<%@ page language="java" cnotallow="text/html; charset=UTF-8"%>
<%@ include file="/base.jsp"%>
<!DOCTYPE html>
<html>
<head>
<!-- Meta -->
<meta charset="utf-8" http-equiv="Content-Type" />
<!-- End of Meta -->
<!-- Page title -->
<title>登录 -${websitemap.web.company}-${websitemap.web.title}</title>
<!-- End of Page title -->
<meta name="author" cnotallow="${websitemap.web.author}" />
<meta name="keywords" cnotallow="${websitemap.web.keywords}" />
<meta name="description" cnotallow="${websitemap.web.description}" />
<link rel="shortcut icon" href="${ctx}/favicon.ico" type="image/x-icon">
<!-- Libraries -->
<link type="text/css" href="${ctx}/static/admin/css/login.css" rel="stylesheet" />
<script type="text/javascript">
  function enterSubmit(event) {
    var keyCode = event.keyCode ? event.keyCode : event.which ? event.which : event.charCode;
    if (keyCode == 13) {
      $("#loginForm").submit();
      return false;
    }
  }
</script>
</head>
<body>
  <div id="container">
    <div class="logo">
      <a href="javascript:void(0);" notallow="return false;" target="_blank" title="Elearning">
      </a>
    </div>
  </div>

  <div class="b-box">
    <div id="container">
      <div id="box">
        <h2>在线博客系统</h2>
        <form actinotallow="${ctx}/admin/main/login" method="POST" id="loginForm">
          <p class="main">
            <label>用户名: </label>
            <input name="sysUser.loginName" notallow="enterSubmit(event)" value="${sysUser.loginName}" placeholder="输入用户名" />
            <label>密码: </label>
            <input type="password" notallow="enterSubmit(event)" name="sysUser.loginPwd" value="${sysUser.loginPwd}" placeholder="输入密码">
          </p>
          <p class="main">
            <label>验证码: </label>
            <input name="randomCode" notallow="enterSubmit(event)" placeholder="验证码" style="width: 105px;"  maxlength="4"/>
            <span class="yzm-pic">
              <img src="${ctx}/ran/random" alt="验证码,点击图片更换" notallow="this.src='${ctx}/ran/random?random='+Math.random();" />
            </span>
          </p>
          <p class="space">
            <input type="submit" value="登录" class="login" />
            <span>${message}</span>
          </p>
        </form>
      </div>
      <div class="login-foot">
        <span>
          Powered By <a target="_blank" href="#" style="color: #666;">IT邦德</a>
        </span>
      </div>
    </div>
  </div>
</body>
</html>      

4.2 点赞记录

4.2 .1 Controller

/**
   * 添加点赞记录
   */
  @RequestMapping("/praise/ajax/add")
  @ResponseBody
  public Object addPraise(HttpServletRequest request,@ModelAttribute("praise")Praise praise){
    Map<String,Object> json = new HashMap<String,Object>();
    try{
      int userId = SingletonLoginUtils.getLoginUserId(request);
      if (userId==0) {
        json = this.setJson(false, "请先登录", "");
        return json;
      }
      //查询是否点赞 过
      praise.setUserId(Long.valueOf(userId));
      int praiseCount=praiseService.queryPraiseCount(praise);
      if(praiseCount>0){
        json = this.setJson(false, "您已赞过", "");
        return json;
      }
      
      //添加点赞记录
      praise.setAddTime(new Date());
      praiseService.addPraise(praise);//在service 中  
        根据点赞目标 type 修改相应的 点赞总数

      json = this.setJson(true, "", "");
    }catch (Exception e) {
      logger.error("PraiseController.addPraise()---error",e);
      json = this.setJson(false, "系统错误,请稍后重试", "");
    }
    return json;
  }      

4.2.2 Service

public interface PraiseService {
  /**
   * 添加点赞记录
   */
  public Long addPraise(Praise praise);
  
  /**
   * 根据条件查询点赞数
   */
  public int queryPraiseCount(Praise praise);
}      

4.2.3 ServiceImpl

@Override
  public Long addPraise(Praise praise) {
    //根据点赞目标 type 修改相应的 点赞总数
    //点赞类型 1问答点赞 2问答评论点赞
    int type=praise.getType();
    if(type==1){
      Questions questinotallow=questionsService.getQuestionsById(praise.getTargetId());
      questions.setPraiseCount(questions.getPraiseCount()+1);
      questionsService.updateQuestions(questions);
    }else if (type==2) {
      QuestionsComment questinotallow=questionsCommentService.getQuestionsCommentById(praise.getTargetId());
      questionsComment.setPraiseCount(questionsComment.getPraiseCount()+1);
      questionsCommentService.updateQuestionsComment(questionsComment);
    }
    //点赞类型为3的是文章点赞
    if(type==3){
      Map<String,String> map = new HashMap<String,String>();
      map.put("num","+1");
      map.put("type", "praiseCount");
      map.put("articleId", praise.getTargetId()+"");
      articleService.updateArticleNum(map);
    }
    //点赞类型为4的是评论点赞
    if(type==4){
      Map<String,String> map = new HashMap<String,String>();
      map.put("num","+1");
      map.put("type", "praiseCount");
      map.put("commentId", praise.getTargetId()+"");
      commentService.updateCommentNum(map);
    }
    return praiseDao.addPraise(praise);
  }      

4.2.4 dao

public interface CommentService {
  /**
   * 分页查询评论
   */
  public List<Comment> getCommentByPage(Comment comment,PageEntity page);
  /**
   * 添加评论
   */
  public void addComment(Comment comment);
  /**
   * 更新评论
   */
  public void updateComment(Comment comment);
  /**
   * 查询评论
   */
  public Comment queryComment(Comment comment);
  /**
   * 查询评论互动
   */
  public List<Comment> queryCommentInteraction(Comment comment);
  /**
   * 更新评论点赞数,回复数等
   */
  public void updateCommentNum(Map<String,String> map);
  /**
   * 删除评论
   */
  public void delComment(int commentId);
  /**
   * 查询评论 list
   */
  public List<Comment> queryCommentList(Comment comment);
}      

4.2.5 UserMapper

<?xml versinotallow="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="PraiseMapper">
  <resultMap type="Praise" id="PraiseResult">
    <result property="id" column="ID"/>
    <result property="ip" column="USER_ID"/>
    <result property="articleId" column="TARGET_ID"/>
    <result property="type" column="TYPE"/>
    <result property="addTime" column="ADD_TIME"/>
  </resultMap>
  
  <sql id="edu_praise_column">
    edu_praise.ID,
    edu_praise.USER_ID,
    edu_praise.TARGET_ID,
    edu_praise.TYPE,
    edu_praise.ADD_TIME
  </sql>
  <sql id="edu_praise_property">
    #{id},
    #{userId},
    #{targetId},
    #{type},
    #{addTime}
  </sql>
  
  <!-- 添加 -->
  <insert id="addPraise" parameterType="Praise" useGeneratedKeys="true" keyProperty="id" keyColumn="ID">
    INSERT INTO edu_praise(<include refid="edu_praise_column"/>) VALUE(<include refid="edu_praise_property"/>)
  </insert>
  
  <!-- 查询 -->
  <select id="queryPraiseCount" parameterType="Praise" resultType="int">
    select IFNULL(count(1),0)
    from edu_praise 
    <where>
      <if test="userId!=null and userId!=0">
        and edu_praise.USER_ID=#{userId}
      </if>
      <if test="targetId!=null and targetId!=0">
        and edu_praise.TARGET_ID=#{targetId}
      </if>
      <if test="type!=0">
        and edu_praise.TYPE=#{type}
      </if>
    </where>
  </select>
  
</mapper>      

五 、框架其他配置

5.1 数据库配置

project.properties

#数据库主机地址
jdbc.host=localhost
#数据库名
jdbc.database=learn
#用户名
jdbc.username=root
#密码
jdbc.password=root

#项目路径
cnotallow=http://localhost:80      

5.2、配置spring-mvc.xml

配置里面的注释也很详细,主要是自动扫描控制器,视图模式,注解的启动这三个。

<?xml versinotallow="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cnotallow="http://www.springframework.org/schema/context"
  xmlns:mvc="http://www.springframework.org/schema/mvc"
  xsi:schemaLocatinotallow="http://www.springframework.org/schema/mvc 
    http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
    http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context-3.2.xsd
    ">

  <!-- ①:对web包中的所有类进行扫描,以完成Bean创建和自动依赖注入的功能 -->
  <context:component-scan base-package="com.inxedu.os"
    use-default-filters="false">
    <context:include-filter type="annotation"
      expressinotallow="org.springframework.stereotype.Controller" />
    <context:include-filter type="annotation"
      expressinotallow="org.springframework.web.bind.annotation.ControllerAdvice" />
  </context:component-scan>

  <mvc:annotation-driven
    content-negotiation-manager="contentNegotiationManager">
    <mvc:message-converters register-defaults="true">
      <!-- 将StringHttpMessageConverter的默认编码设为UTF-8 -->
      <bean class="org.springframework.http.converter.StringHttpMessageConverter">
        <constructor-arg value="UTF-8" />
      </bean>
    </mvc:message-converters>
  </mvc:annotation-driven>
  <mvc:default-servlet-handler />
  <!-- ②:拦截器的配置 -->
  <mvc:interceptors>
    <!-- 后台登录和权限的拦截器配置 -->
    <mvc:interceptor>
      <mvc:mapping path="/admin/*" />
      <mvc:mapping path="/admin/**/*" />
      <mvc:exclude-mapping path="/admin/main/login" />
      <bean class="com.inxedu.os.common.intercepter.IntercepterAdmin"></bean>
    </mvc:interceptor>
    <!-- 前台网站配置拦截器配置 -->
    <mvc:interceptor>
      <mvc:mapping path="/**/*" />
      <mvc:exclude-mapping path="/static/**/*" />
      <mvc:exclude-mapping path="/*/ajax/**" />
      <mvc:exclude-mapping path="/kindeditor/**/*" />
      <bean class="com.inxedu.os.common.intercepter.LimitIntercepterForWebsite">
      </bean>
    </mvc:interceptor>
    <!-- 前台用户登录拦截器配置 -->
    <mvc:interceptor>
      <mvc:mapping path="/uc/*" />
      <mvc:mapping path="/uc/**/*" />
      <mvc:exclude-mapping path="/uc/tologin" />
      <mvc:exclude-mapping path="/uc/getloginUser" />
      <mvc:exclude-mapping path="/uc/register" />
      <mvc:exclude-mapping path="/uc/createuser" />
      <mvc:exclude-mapping path="/uc/login" />
      <mvc:exclude-mapping path="/uc/passwordRecovery" />
      <mvc:exclude-mapping path="/uc/sendEmail" />
      <bean class="com.inxedu.os.common.intercepter.IntercepterWebLogin">
      </bean>
    </mvc:interceptor>

  </mvc:interceptors>
  <!-- ③:对模型视图名称的解析,即在模型视图名称添加前后缀 -->
  <bean
    class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/view/" />
    <property name="suffix" value=".jsp" />
    <property name="viewClass"
      value="org.springframework.web.servlet.view.JstlView" />
  </bean>

  <!-- <mvc:view-controller path="/" view-name="redirect:/index"/> -->
  <!-- REST中根据URL后缀自动判定Content-Type及相应的View -->
  <bean id="contentNegotiationManager"
    class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
    <property name="mediaTypes">
      <value>
        jsnotallow=application/json
        xml=application/xml
      </value>
    </property>
  </bean>

  <!-- 文件上传限制大小 -->
  <bean id="multipartResolver"
    class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <!-- set the max upload size 10MB -->
    <property name="maxUploadSize">
      <value>5048576000</value>
    </property>
    <property name="maxInMemorySize">
      <value>4096</value>
    </property>
  </bean>

  <!-- Spring MVC 内置处理json配置 添加jackson-mapper-asl-1.*.*.jar jackson-core-asl-1.*.*.jar这两个包实现 -->
  <bean
    class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
    <property name="messageConverters">
      <list>
        <bean
          class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" />
      </list>
    </property>
  </bean>
  <!-- 将Controller抛出的异常转到特定View, 保持SiteMesh的装饰效果 -->
  <bean
    class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
    <property name="exceptionMappings">
      <props>
        <prop key="org.apache.shiro.authz.UnauthorizedException">/WEB-INF/view/common/403</prop>
        <prop key="java.lang.Throwable">/common/error</prop>
      </props>
    </property>
  </bean>
</beans>      

5.3 Log4j的配置

为了方便调试,一般都会使用日志来输出信息,Log4j是Apache的一个开放源代码项目,
通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件,
甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等;
我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程      
log4j.rootLogger=INFO,Console,File  
#定义日志输出目的地为控制台  
log4j.appender.Cnotallow=org.apache.log4j.ConsoleAppender  
log4j.appender.Console.Target=System.out  
#可以灵活地指定日志输出格式,下面一行是指定具体的格式  
log4j.appender.Console.layout = org.apache.log4j.PatternLayout  
log4j.appender.Console.layout.Cnotallow=[%c] - %m%n  
  
#文件大小到达指定尺寸的时候产生一个新的文件  
log4j.appender.File = org.apache.log4j.RollingFileAppender  
#指定输出目录  
log4j.appender.File.File = logs/ssm.log  
#定义文件最大大小  
log4j.appender.File.MaxFileSize = 10MB  
# 输出所以日志,如果换成DEBUG表示输出DEBUG以上级别日志  
log4j.appender.File.Threshold = ALL  
log4j.appender.File.layout = org.apache.log4j.PatternLayout  
log4j.appender.File.layout.ConversionPattern =[%p] [%d{yyyy-MM-dd HH\:mm\:ss}][%c]%m%n      

5.4 数据库表结构