论坛系统(Spring+SpringMVC+Mybatis)

论坛系统(Spring+SpringMVC+Mybatis)

接着上一篇文章介绍的论坛系统—— 基于Spring+Struts1+Hibernate实现,本文章要介绍的是基于Spring+SpringMVC+Mybatis实现的论坛系统。之所以心血来潮把框架换了,是因为刚学完SpringMVC和Mybatis,只有几个SSM的例程,得不到做一个系统的实践经验,所以就尝试换了框架,经过几天的努力,最后把功能都还原了,整个小项目从创建到完成,还是挺有点成就感的,毕竟是自己把代码一个个敲出来,把功能一步步完成。目前,很多公司都使用SSM组合框架,而SSM也得到了越来越多web开发者的追捧,所以很有必要学习。

个人觉得SpringMVC比Struts好得多,在以后的开发中,我更倾向于SpringMVC,毕竟是同一家公司的产品,SpringMVC比Struts更容易契合Spring技术;而Hibernate和Mybatis各有其优点,可以根据系统的需求而选择Hibernate还是Mybatis。对两者做一些小总结:

Hibernate对数据库结构提供了较为完整的封装,只需定义好POJO 到数据库表的映射关系,即可通过Hibernate 提供的方法完成持久层操作;而Mybatis侧重于POJO 与SQL之间的映射关系,然后通过映射配置文件,将SQL所需的参数,以及返回的结果字段映射到指定POJO。
Mybatis优势:
  • MyBatis可以进行更为细致的SQL优化,可以减少查询字段
  • MyBatis容易掌握,而Hibernate门槛较高
Hibernate优势:
  • Hibernate的DAO层开发比MyBatis简单,Mybatis需要维护SQL和结果映射
  • Hibernate对对象的维护和缓存要比MyBatis好,对增删改查的对象的维护要方便。(我最大的感悟是Mybatis只提供级联查询,而不能级联插入、更新
  • Hibernate数据库移植性很好,MyBatis的数据库移植性不好,不同的数据库需要写不同SQL。
  • Hibernate有更好的二级缓存机制,可以使用第三方缓存。MyBatis本身提供的缓存机制不佳,更新操作不能指定刷新指定记录,会清空整个表,但是也可以使用第三方缓存。
当然,Hibernate的缺点也很明显,如果涉及到多张关联表的调用时:
  • 多表关联等比较复杂,使用的成本并不低
  • 效率比较低,在大型项目中很少使用,因为sql都是自动生成,不太好人工优化。

说点闲话,开始有点喜欢写一下博客,记录一下自己所学的知识还是挺好的,嗯,得坚持!!!! 奋斗

回到正事!该基于SSM的系统直接用的是上一篇文章的数据库,懒得创建了。 整个工程目录以及数据表如下:
         

就贴一张效果图,界面跟上一篇贴出来的都一样,我只是把框架给换了,在JSP中把所有Struts的标签都换成spring提供的form标签!

1、使用Mybatis-Generator自动生成DAO、Model、Mapping相关文件

Mybatis属于半自动ORM,在使用这个框架中,工作量最大的就是书写Mapping的映射文件,由于手动书写很容易出错,我们可以利用Mybatis-Generator来帮我们自动生成文件。(说到底是自己懒,哈哈)尽管是这样,确实是会减少一点额外的工作。但我通常都会把生成的xxExample.java文件删掉,并对xxMapper.java、xxMapper.xml文件进行适当的删减,留下几个有用的,在此基础上再添加自己的操作语句。
generatorConfig.xml:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd" >
<generatorConfiguration>
	<classPathEntry
		location="D:/software/mysql-connector/mysql-connector-java-5.1.39-bin.jar" />
		
	<context id="context">
		<!-- 为了防止生成的代码中有很多注释,比较难看,加入下面的配置控制 -->
		<commentGenerator>
			<property name="suppressAllComments" value="true" />
			<property name="suppressDate" value="true" />
		</commentGenerator>
		
		<jdbcConnection driverClass="com.mysql.jdbc.Driver"
			connectionURL="jdbc:mysql://localhost:3306/forum" userId="root"
			password="5845201314" />
		<!-- 生成模型的包名和位置 --> 
		<javaModelGenerator targetPackage="model" targetProject="Forum_SSM" />
		<!-- 生成的映射文件包名和位置 -->
		<sqlMapGenerator targetPackage="mapper" targetProject="Forum_SSM" />
		<!-- 生成DAO的包名和位置 --> 
		<javaClientGenerator targetPackage="mapper" targetProject="Forum_SSM" type="XMLMAPPER" />
		<!-- 数据库名以及对应的表 -->
		<table schema="forum" tableName="person">
		</table>
	</context>
</generatorConfiguration>

2、相关配置文件

2.1、web.xml

这里主要配置了Spring的DispatcherServlet,让它拦截所有以.do结尾的请求,还配置了一个字符过滤器,防止乱码问题(个人习惯了,不管有没有用,加上去再说)
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
	version="3.0">
	<display-name>Forum_SSM</display-name>
	<!-- spring配置文件加载 -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:applicationContext.xml</param-value>
	</context-param>
	<!-- mvc控制器 -->
	<servlet>
		<servlet-name>spring</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>classpath:mvc-config.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>spring</servlet-name>
		<url-pattern>*.do</url-pattern>
	</servlet-mapping>
	<!-- 字符编码过滤器 -->
	<filter>
		<filter-name>CharacterEncodingFilter</filter-name>
		<filter-class>filter.CharacterEncodingFilter</filter-class>
		<init-param>
			<param-name>characterEncoding</param-name>
			<param-value>UTF-8</param-value>
		</init-param>
		<init-param>
			<param-name>enabled</param-name>
			<param-value>true</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>CharacterEncodingFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
</web-app>

2.2、applicationContext.xml

component-scan标签默认情况下自动扫描指定路径下的包(含所有子包),将带有@Component、@Repository、@Service、@Controller标签的类自动注册到spring容器。对标记了@Required、@Autowired等注解的类进行对应的操作使注解生效。

<?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:p="http://www.springframework.org/schema/p"
	xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
	http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
	http://www.springframework.org/schema/tx   
    http://www.springframework.org/schema/tx/spring-tx-3.1.xsd 
	http://www.springframework.org/schema/aop
	http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
	http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context-3.1.xsd">


	<bean id="exceptionHandler" class="exception.ForumExceptionHandler" />

	<!-- 扫描DAO和SERVICE包,controller包在springmvc中扫描 -->
	<context:component-scan base-package="ServiceImpl,DAOImpl" />

	<bean id="dataSource"
		class="org.springframework.jdbc.datasource.DriverManagerDataSource">	<!-- 定义数据源 -->
		<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
		<property name="url"
			value="jdbc:mysql://localhost:3306/forum?characterEncoding=UTF-8"></property>
		<property name="username" value="root"></property>
		<property name="password" value="5845201314"></property>
	</bean>

	<!-- 会话工厂 :session 工厂可以使用 SqlSessionFactoryBuilder 来创建。而在 MyBatis-spring 
		中,则使用 SqlSessionFactoryBean 来替代 -->
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="dataSource" ref="dataSource" />
		<!-- 当SqlSessionFactoryBean提供的配置不能满足使用时,你可以使用mybatis-config.xml配置文件配置其他属性 -->
		<property name="configLocation" value="classpath:mybatis-config.xml"></property>
		<property name="mapperLocations" value="classpath:mapper/*.xml"></property>
	</bean>

	<!-- 事务管理器 -->
	<bean id="transactionManager"
		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource" />
	</bean>

	<!-- 配置事务的传播特性 -->
	<tx:advice id="transactionAdvice" transaction-manager="transactionManager">
		<!-- 指定具体需要拦截的方法 -->
		<tx:attributes>
			<tx:method name="insert*" propagation="REQUIRED"></tx:method>
			<tx:method name="delete*" propagation="REQUIRED"></tx:method>
			<tx:method name="update*" propagation="REQUIRED"></tx:method>
			<tx:method name="select*" propagation="SUPPORTS"></tx:method>
		</tx:attributes>
	</tx:advice>
	<!-- 配置哪些类的哪些方法参与事务 -->
	<aop:config>
		<aop:pointcut id="serviceCut" expression="execution(public * Service.*.*(..))" />
		<aop:advisor pointcut-ref="serviceCut" advice-ref="transactionAdvice" />
	</aop:config>

	<!-- spring和mybatis的整合 -->
	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
		<property name="basePackage" value="mapper" />
	</bean>
</beans>

2.3、SpringMVC配置文件——mvc-config.xml

该配置文件主要服务于SpringMVC流程。 在mvc-config.xml中,最重要的工作是控制转发,这个配置文件中做了最简单的转发操作,只能转发页面,如果想要通过ajax实现转发数据,那么需要重写ViewResolver来实现这个功能。把jsp文件放在WEB-INF下,这样就只能通过Controller进行访问。
<?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"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
	http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
	http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context-3.1.xsd
    http://www.springframework.org/schema/mvc
    http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd">

	<!-- 扫描controller包 -->
    <context:component-scan base-package="Controller"></context:component-scan>
    
    <!-- 完成请求和注解POJO的映射 -->
    <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>

	<!-- 配置JSP前缀后缀 -->
	<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix">
			<value>/WEB-INF/jsp/</value>
		</property>
		<property name="suffix">
			<value>.jsp</value>
		</property>
	</bean>
	
	<!--拦截器 -->
    <mvc:interceptors>
    <!--多个拦截器,顺序执行 -->
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <bean class="Interceptor.LoginInterceptor"></bean>
        </mvc:interceptor>
    </mvc:interceptors>
	
	<!-- 支持文件上传 -->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    </bean>
</beans>

2.4、mybatis-config.xml

在mybatis-config.xml中不需要额外的配置,它只是个空文件。

3、用户模块

3.1、Person.java

mybatis的实体类和hibernate实体类的不同是mybatis的实体类不需要加载到spring的beanFactory中,而是通过操作数据库的mapper来持久化数据。
package model;

public class Person {
    private Integer id;
    private Date datecreated;
    private Boolean deleted;
    private Integer version;
    private String account;
    private String birthday;
    private Date datelastactived;
    private String email;
    private String ipcreated;
    private String iplastactived;
    private String name;
    private String password;
    private String sex;
	//省略setter和getter方法
}

3.2、PersonMapper映射接口

对Mybatis-Generator生成的personMapper.java进行删减,只留下在该系统中可能用到的,并添加需要用到的操作方法。
package mapper;

public interface PersonMapper {
	Person getPerson(Person person);
	Person selectByAccount(String account);
	List<Board> selectBoardByPersonId(int id);
	List<Person> selectAll();
	int deleteByBoardId(Integer id);
	int insertBoardAdministrator(@Param("boardId") int boardId, @Param("personId") int personId);
	/*以上为自己实现的方法,保留了下面可能用到的方法*/
	int deleteByPrimaryKey(Integer id);
	int insert(Person record);
	int insertSelective(Person record);
	Person selectByPrimaryKey(Integer id);
	int updateByPrimaryKeySelective(Person record);
	int updateByPrimaryKey(Person record);
}

3.3、PersonMapper.xml映射文件

<?xml version="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="mapper.PersonMapper" >
  <resultMap id="BaseResultMap" type="model.Person" >
    <id column="id" property="id" jdbcType="INTEGER" />
    <result column="dateCreated" property="datecreated" jdbcType="TIMESTAMP" />
    <result column="deleted" property="deleted" jdbcType="BIT" />
    <result column="version" property="version" jdbcType="INTEGER" />
    <result column="account" property="account" jdbcType="VARCHAR" />
    <result column="birthday" property="birthday" jdbcType="VARCHAR" />
    <result column="dateLastActived" property="datelastactived" jdbcType="TIMESTAMP" />
    <result column="email" property="email" jdbcType="VARCHAR" />
    <result column="ipCreated" property="ipcreated" jdbcType="VARCHAR" />
    <result column="ipLastActived" property="iplastactived" jdbcType="VARCHAR" />
    <result column="name" property="name" jdbcType="VARCHAR" />
    <result column="password" property="password" jdbcType="VARCHAR" />
    <result column="sex" property="sex" jdbcType="VARCHAR" />
  </resultMap>
  <resultMap id="BoardResultMap" type="model.Board" extends="mapper.BoardMapper.BaseResultMap">
  </resultMap>
  
  <sql id="Base_Column_List" >
    id, dateCreated, deleted, version, account, birthday, dateLastActived, email, ipCreated, 
    ipLastActived, name, password, sex
  </sql>
  <sql id="Board_Column_List" >
    id, dateCreated, deleted, version, description, name, replyCount, threadCount, category_id, 
    last_reply_id, last_thread_id
  </sql>
  
  <select id="getPerson" resultMap="BaseResultMap" parameterType="model.Person" >
    select 
    <include refid="Base_Column_List" />
    from person
    where account=#{account,jdbcType=VARCHAR} and password=#{password,jdbcType=VARCHAR}
  </select>
  
  <select id="selectByAccount" resultMap="BaseResultMap" parameterType="String" >
    select 
    <include refid="Base_Column_List" />
    from person
    where account = #{account,jdbcType=VARCHAR}
  </select>
  
  <select id="selectBoardByPersonId" resultMap="BoardResultMap" parameterType="java.lang.Integer" >
    select 
    <include refid="Board_Column_List" />
    from board
    where id in (select board_id from board_administrator where person_id = #{person_id,jdbcType=INTEGER})
  </select>
  
  <select id="findPersonByBoardId" resultMap="BaseResultMap" parameterType="java.lang.Integer" >
    select 
    <include refid="Base_Column_List" />
    from person
    where id in (select person_id from board_administrator where board_id = #{board_id,jdbcType=INTEGER})
  </select>
  
  <select id="selectAll" resultMap="BaseResultMap" >
    select 
    <include refid="Base_Column_List" />
    from person
    where deleted=false
  </select>
  
  <delete id="deleteByBoardId" parameterType="java.lang.Integer" >
	delete from board_administrator
	where board_id = #{boardId,jdbcType=INTEGER}
  </delete>
  
  <insert id="insertBoardAdministrator">
  	insert into board_administrator
  	values (#{boardId}, #{personId})
  </insert>
  
  <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer" >
    select 
    <include refid="Base_Column_List" />
    from person
    where id = #{id,jdbcType=INTEGER}
  </select>
  <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer" >
    delete from person
    where id = #{id,jdbcType=INTEGER}
  </delete>

  <insert id="insert" parameterType="model.Person" >
    insert into person (id, dateCreated, deleted, 
      version, account, birthday, 
      dateLastActived, email, ipCreated, 
      ipLastActived, name, password, 
      sex)
    values (#{id,jdbcType=INTEGER}, #{datecreated,jdbcType=TIMESTAMP}, #{deleted,jdbcType=BIT}, 
      #{version,jdbcType=INTEGER}, #{account,jdbcType=VARCHAR}, #{birthday,jdbcType=VARCHAR}, 
      #{datelastactived,jdbcType=TIMESTAMP}, #{email,jdbcType=VARCHAR}, #{ipcreated,jdbcType=VARCHAR}, 
      #{iplastactived,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, #{password,jdbcType=VARCHAR}, 
      #{sex,jdbcType=VARCHAR})
  </insert>
  <insert id="insertSelective" parameterType="model.Person" >
    insert into person
    <trim prefix="(" suffix=")" suffixOverrides="," >
      <if test="id != null" >
        id,
      </if>
      <if test="datecreated != null" >
        dateCreated,
      </if>
      <if test="deleted != null" >
        deleted,
      </if>
      <if test="version != null" >
        version,
      </if>
      <if test="account != null" >
        account,
      </if>
      <if test="birthday != null" >
        birthday,
      </if>
      <if test="datelastactived != null" >
        dateLastActived,
      </if>
      <if test="email != null" >
        email,
      </if>
      <if test="ipcreated != null" >
        ipCreated,
      </if>
      <if test="iplastactived != null" >
        ipLastActived,
      </if>
      <if test="name != null" >
        name,
      </if>
      <if test="password != null" >
        password,
      </if>
      <if test="sex != null" >
        sex,
      </if>
    </trim>
    <trim prefix="values (" suffix=")" suffixOverrides="," >
      <if test="id != null" >
        #{id,jdbcType=INTEGER},
      </if>
      <if test="datecreated != null" >
        #{datecreated,jdbcType=TIMESTAMP},
      </if>
      <if test="deleted != null" >
        #{deleted,jdbcType=BIT},
      </if>
      <if test="version != null" >
        #{version,jdbcType=INTEGER},
      </if>
      <if test="account != null" >
        #{account,jdbcType=VARCHAR},
      </if>
      <if test="birthday != null" >
        #{birthday,jdbcType=VARCHAR},
      </if>
      <if test="datelastactived != null" >
        #{datelastactived,jdbcType=TIMESTAMP},
      </if>
      <if test="email != null" >
        #{email,jdbcType=VARCHAR},
      </if>
      <if test="ipcreated != null" >
        #{ipcreated,jdbcType=VARCHAR},
      </if>
      <if test="iplastactived != null" >
        #{iplastactived,jdbcType=VARCHAR},
      </if>
      <if test="name != null" >
        #{name,jdbcType=VARCHAR},
      </if>
      <if test="password != null" >
        #{password,jdbcType=VARCHAR},
      </if>
      <if test="sex != null" >
        #{sex,jdbcType=VARCHAR},
      </if>
    </trim>
  </insert>

  <update id="updateByPrimaryKeySelective" parameterType="model.Person" >
    update person
    <set >
      <if test="datecreated != null" >
        dateCreated = #{datecreated,jdbcType=TIMESTAMP},
      </if>
      <if test="deleted != null" >
        deleted = #{deleted,jdbcType=BIT},
      </if>
      <if test="version != null" >
        version = #{version,jdbcType=INTEGER},
      </if>
      <if test="account != null" >
        account = #{account,jdbcType=VARCHAR},
      </if>
      <if test="birthday != null" >
        birthday = #{birthday,jdbcType=VARCHAR},
      </if>
      <if test="datelastactived != null" >
        dateLastActived = #{datelastactived,jdbcType=TIMESTAMP},
      </if>
      <if test="email != null" >
        email = #{email,jdbcType=VARCHAR},
      </if>
      <if test="ipcreated != null" >
        ipCreated = #{ipcreated,jdbcType=VARCHAR},
      </if>
      <if test="iplastactived != null" >
        ipLastActived = #{iplastactived,jdbcType=VARCHAR},
      </if>
      <if test="name != null" >
        name = #{name,jdbcType=VARCHAR},
      </if>
      <if test="password != null" >
        password = #{password,jdbcType=VARCHAR},
      </if>
      <if test="sex != null" >
        sex = #{sex,jdbcType=VARCHAR},
      </if>
    </set>
    where id = #{id,jdbcType=INTEGER}
  </update>
  <update id="updateByPrimaryKey" parameterType="model.Person" >
    update person
    set dateCreated = #{datecreated,jdbcType=TIMESTAMP},
      deleted = #{deleted,jdbcType=BIT},
      version = #{version,jdbcType=INTEGER},
      account = #{account,jdbcType=VARCHAR},
      birthday = #{birthday,jdbcType=VARCHAR},
      dateLastActived = #{datelastactived,jdbcType=TIMESTAMP},
      email = #{email,jdbcType=VARCHAR},
      ipCreated = #{ipcreated,jdbcType=VARCHAR},
      ipLastActived = #{iplastactived,jdbcType=VARCHAR},
      name = #{name,jdbcType=VARCHAR},
      password = #{password,jdbcType=VARCHAR},
      sex = #{sex,jdbcType=VARCHAR}
    where id = #{id,jdbcType=INTEGER}
  </update>
</mapper>

3.4、PersonDAO层及其实现

本系统继续沿用了DAO层和Service层的编程习惯。
package DAO;

public interface PersonDAO {
	public void save(Person person);
	public int insert(Person person);
	public Person selectById(int id);
	public List<Board> selectBoardByPersonId(int id);
	public List<Person> selectAll();
	public Person findPersonByAccount(String account);
	public Person getPerson(Person person);
	public int deleteByBoardId(int id);
	public int insertBoardAdministrator(int boardId, int personId);
}

package DAOImpl;

@Repository
public class PersonDAOImpl implements PersonDAO{

	@Autowired
	private PersonMapper personMapper;

	@Override
	public Person findPersonByAccount(String account) {
		return personMapper.selectByAccount(account);
	}
	@Override
	public Person getPerson(Person person) {
		return personMapper.getPerson(person);
	}
	@Override
	public void save(Person person) {
		personMapper.updateByPrimaryKeySelective(person);
	}
	@Override
	public int insert(Person person) {
		return personMapper.insertSelective(person);
	}
	@Override
	public Person selectById(int id) {
		return personMapper.selectByPrimaryKey(id);
	}
	@Override
	public List<Board> selectBoardByPersonId(int id) {
		return personMapper.selectBoardByPersonId(id);
	}
	@Override
	public List<Person> selectAll() {
		return personMapper.selectAll();
	}
	@Override
	public int deleteByBoardId(int id) {
		return personMapper.deleteByBoardId(id);
	}
	@Override
	public int insertBoardAdministrator(int boardId, int personId) {
		return personMapper.insertBoardAdministrator(boardId, personId);
	}
}

3.5、PersonService层及其实现

package Service;

public interface PersonService {
	
	public void save(Person person);
	public int insert(Person person);
	public Person selectById(int id);
	public List<Person> selectAll();
	public List<Board> selectBoardByPersonId(int id);
	public Person findPersonByAccount(String account);
	public Person getPerson(Person person);
	public int deleteByBoardId(int id);
	public int insertBoardAdministrator(int boardId, int personId);
}

package ServiceImpl;

@Service
public class PersonServiceImpl implements PersonService{

	@Autowired
	private PersonDAO personDAO;

	@Override
	public Person findPersonByAccount(String account) {
		return personDAO.findPersonByAccount(account);
	}

	@Override
	public Person getPerson(Person person) {
		Person newper=new Person();
		newper.setAccount(person.getAccount());
		newper.setPassword(MD5Util.calc(person.getPassword()));
		return personDAO.getPerson(newper);
	}

	@Override
	public void save(Person person) {
		personDAO.save(person);
	}

	@Override
	public int insert(Person person) {
		if(findPersonByAccount(person.getAccount())!=null)
			throw new RuntimeException("帐号 " + person.getAccount() + " 已经存在。");
		person.setPassword(MD5Util.calc(person.getPassword()));
		return personDAO.insert(person);
	}

	@Override
	public Person selectById(int id) {
		return personDAO.selectById(id);
	}

	@Override
	public List<Board> selectBoardByPersonId(int id) {
		return personDAO.selectBoardByPersonId(id);
	}

	@Override
	public List<Person> selectAll() {
		return personDAO.selectAll();
	}

	@Override
	public int deleteByBoardId(int id) {
		return personDAO.deleteByBoardId(id);
	}

	@Override
	public int insertBoardAdministrator(int boardId, int personId) {
		return personDAO.insertBoardAdministrator(boardId, personId);
	} 

}

3.6、Person控制器

package Controller;

@Controller
public class PersonController {

	@Autowired
	private PersonService personService;
	
	@RequestMapping("person_initAdd.do")
	public ModelAndView initAdd(HttpServletRequest request){
		request.setAttribute("title", "用户注册");
		request.setAttribute("person", new Person());
		return new ModelAndView("person/addPerson");
	}
	
	
	@RequestMapping("person_add.do")
	public ModelAndView add(@ModelAttribute Person person, HttpServletRequest request, HttpServletResponse response){
		request.setAttribute("title", "用户注册");
		person.setIpcreated(request.getRemoteAddr());
		person.setIplastactived(request.getRemoteAddr());
		person.setDatecreated(new Date());
		person.setDatelastactived(new Date());
		person.setDeleted(false);
		if (person.getAccount() == null|| person.getAccount().trim().length() == 0) {
			request.setAttribute("message", "请输入帐号");
			return initAdd(request);
		}
		if (person.getPassword() == null|| person.getPassword().trim().length() == 0|| !person.getPassword().equals(request.getParameter("password1"))) {
			request.setAttribute("message", "密码不一致");
			return initAdd(request);
		}
		try {
			personService.insert(person);//保存到数据库,此时没有id
			PersonUtil.setPersonInf(request, response, personService.findPersonByAccount(person.getAccount()));
			request.setAttribute("message", "注册成功");
			return new ModelAndView("person/success");
		} catch (Exception e) {
			request.setAttribute("message", "注册失败,原因:" + e.getMessage());
			return initAdd(request);
		}
	}
	
	@RequestMapping("person_initLogin.do")
	public ModelAndView initLogin(HttpServletRequest request){
		request.setAttribute("person", new Person());
		request.setAttribute("title", "用户登录");
		return new ModelAndView("person/login");
	}
	
	@RequestMapping("person_login.do")
	public ModelAndView login(@ModelAttribute Person person,HttpServletRequest request, HttpServletResponse response) throws Exception{
		request.setAttribute("title", "用户登录");
		Person person1=personService.getPerson(person);
		if (person1 == null)
			throw new AccountException("用户名密码错误");
		PersonUtil.setPersonInf(request, response, person1);
		person1.setIplastactived(request.getRemoteAddr());
		person1.setDatelastactived(new Date());
		personService.save(person1);
		request.setAttribute("message", "欢迎回来");
		return new ModelAndView("person/success");
	}
	
	@RequestMapping("person_logout.do")
	public ModelAndView logout(HttpServletRequest request){
		request.setAttribute("title", "用户注销");
		request.getSession(true).setAttribute(PersonUtil.PERSON_INFO, null);
		request.setAttribute("person", new Person());
		return new ModelAndView("person/login");
	}
	
	@RequestMapping("person_view.do")
	public ModelAndView view(HttpServletRequest request){
		request.setAttribute("title", "查看用户资料");
		int id=Integer.parseInt(request.getParameter("id"));
		Person person=personService.selectById(id);
		request.setAttribute("person", person);
		List<Board> boardList=personService.selectBoardByPersonId(id);
		request.setAttribute("boardList", boardList);
		return new ModelAndView("person/viewPerson");
	}
}

4、版面类型模块

4.1、Category.java

boardList需要自己手动,因为它并不属于表中的字段,级联查询时需要用到
package model;

public class Category {
	private Integer id;

	private Date datecreated;

	private Boolean deleted;

	private Integer version;

	private String name;

	private List<Board> boardList; //省略setter、getter方法
}

4.2、CategoryMapper映射接口

package mapper;

public interface CategoryMapper {

	List<Category> getList();

	Category selectByName(String name);

	List<Category> getAll();

	/*以上为自己实现的方法,保留了下面可能用到的方法*/

	int deleteByPrimaryKey(Integer id);

	int insert(Category record);

	int insertSelective(Category record);

	Category selectByPrimaryKey(Integer id);

	int updateByPrimaryKeySelective(Category record);

	int updateByPrimaryKey(Category record);
}

4.3、CategoryMapper.xml映射文件

<?xml version="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="mapper.CategoryMapper" >
  <resultMap id="BaseResultMap" type="model.Category" >
    <id column="id" property="id" jdbcType="INTEGER" />
    <result column="dateCreated" property="datecreated" jdbcType="TIMESTAMP" />
    <result column="deleted" property="deleted" jdbcType="BIT" />
    <result column="version" property="version" jdbcType="INTEGER" />
    <result column="name" property="name" jdbcType="VARCHAR" />
  </resultMap>
  <resultMap id="Cate_BoardResultMap" type="model.Category" extends="BaseResultMap">
    <collection property="boardList" column="id" select="mapper.BoardMapper.findBoardByCategoryId"></collection>
  </resultMap>
  
  <sql id="Base_Column_List" >
    id, dateCreated, deleted, version, name
  </sql>
  <select id="getList" resultMap="Cate_BoardResultMap" >
    select 
    <include refid="Base_Column_List" />
    from category
    where deleted = false
  </select>
  
  <select id="selectByName" resultMap="BaseResultMap" parameterType="String" >
    select 
    <include refid="Base_Column_List" />
    from category
    where name = #{name,jdbcType=VARCHAR}
  </select>
  
  <select id="getAll" resultMap="BaseResultMap" >
    select 
    <include refid="Base_Column_List" />
    from category
    where deleted = false
  </select>
  
  <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer" >
    select 
    <include refid="Base_Column_List" />
    from category
    where id = #{id,jdbcType=INTEGER}
  </select>
  <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer" >
    delete from category
    where id = #{id,jdbcType=INTEGER}
  </delete>
  <insert id="insert" parameterType="model.Category" >
    insert into category (id, dateCreated, deleted, 
      version, name)
    values (#{id,jdbcType=INTEGER}, #{datecreated,jdbcType=TIMESTAMP}, #{deleted,jdbcType=BIT}, 
      #{version,jdbcType=INTEGER}, #{name,jdbcType=VARCHAR})
  </insert>
  <insert id="insertSelective" parameterType="model.Category" >
    insert into category
    <trim prefix="(" suffix=")" suffixOverrides="," >
      <if test="id != null" >
        id,
      </if>
      <if test="datecreated != null" >
        dateCreated,
      </if>
      <if test="deleted != null" >
        deleted,
      </if>
      <if test="version != null" >
        version,
      </if>
      <if test="name != null" >
        name,
      </if>
    </trim>
    <trim prefix="values (" suffix=")" suffixOverrides="," >
      <if test="id != null" >
        #{id,jdbcType=INTEGER},
      </if>
      <if test="datecreated != null" >
        #{datecreated,jdbcType=TIMESTAMP},
      </if>
      <if test="deleted != null" >
        #{deleted,jdbcType=BIT},
      </if>
      <if test="version != null" >
        #{version,jdbcType=INTEGER},
      </if>
      <if test="name != null" >
        #{name,jdbcType=VARCHAR},
      </if>
    </trim>
  </insert>

  <update id="updateByPrimaryKeySelective" parameterType="model.Category" >
    update category
    <set >
      <if test="datecreated != null" >
        dateCreated = #{datecreated,jdbcType=TIMESTAMP},
      </if>
      <if test="deleted != null" >
        deleted = #{deleted,jdbcType=BIT},
      </if>
      <if test="version != null" >
        version = #{version,jdbcType=INTEGER},
      </if>
      <if test="name != null" >
        name = #{name,jdbcType=VARCHAR},
      </if>
    </set>
    where id = #{id,jdbcType=INTEGER}
  </update>
  <update id="updateByPrimaryKey" parameterType="model.Category" >
    update category
    set dateCreated = #{datecreated,jdbcType=TIMESTAMP},
      deleted = #{deleted,jdbcType=BIT},
      version = #{version,jdbcType=INTEGER},
      name = #{name,jdbcType=VARCHAR}
    where id = #{id,jdbcType=INTEGER}
  </update>
</mapper>

4.4、CategoryDAO层及其实现

package DAO;

public interface CategoryDAO {

	public List<Category> getList();

	public int create(Category category);
	
	public Category selectByName(String name);
	
	public List<Category> getAll();
}

package DAOImpl;

@Repository
public class CategoryDAOImpl implements CategoryDAO{

	@Autowired
	private CategoryMapper categoryMapper;

	@Override
	public List<Category> getList() {
		return categoryMapper.getList();
	}

	@Override
	public int create(Category category) {
		return categoryMapper.insertSelective(category);
	}

	@Override
	public Category selectByName(String name) {
		return categoryMapper.selectByName(name);
	}

	@Override
	public List<Category> getAll() {
		return categoryMapper.getAll();
	}
}

4.5、CategoryService层及其实现

package Service;

public interface CategoryService {

	public List<Category> getList();
	
	public int create(Category category);
	
	public List<Category> getAll();
}

package ServiceImpl;

@Service
public class CategoryServiceImpl implements CategoryService{

	@Autowired
	private CategoryDAO categoryDAO;

	@Override
	public List<Category> getList() {
		return categoryDAO.getList();
	}

	@Override
	public int create(Category category) {
		if(categoryDAO.selectByName(category.getName())!=null)
			throw new RuntimeException("类别 " + category.getName() + " 已经存在。");
		return categoryDAO.create(category);
	}

	@Override
	public List<Category> getAll() {
		return categoryDAO.getAll();
	}
}

4.6、Category控制层

package Controller;

@Controller
public class CategoryController {
	
	@Autowired
	private CategoryService categoryService;
	
	@RequestMapping("category_list.do")
	public ModelAndView list(HttpServletRequest request){
		request.setAttribute("title", "轻量级 Java EE 论坛程序");
		List<Category> categoryList = categoryService.getList();
		request.setAttribute("categoryList", categoryList);
		return new ModelAndView("category/listCategory");
	}
	
	@RequestMapping("category_initAdd.do")
	public ModelAndView initAdd(HttpServletRequest request){
		request.setAttribute("title", "添加类别");
		request.setAttribute("category", new Category());
		return new ModelAndView("category/addCategory");
	}
	
	@RequestMapping("category_add.do")
	public ModelAndView add(@ModelAttribute Category category, HttpServletRequest request){
		request.setAttribute("title", "添加类别");
		category.setDatecreated(new Date());
		category.setDeleted(false);
		categoryService.create(category);
		return new ModelAndView("category/success");
	}

}

好吧!我承认老是贴代码,毫无营养!版面模块、帖子模块和回帖模块的代码就不贴出来了。如果是我也没耐心看完,直接下载源码学来得更实际一些。

下载源码

数据库脚本:
create database forum character set utf8 ;

use forum;

CREATE TABLE if not exists person (
  id int(11) NOT NULL AUTO_INCREMENT,
  dateCreated datetime DEFAULT NULL,
  deleted bit(1) NOT NULL,
  version int(11) DEFAULT NULL,
  account varchar(255) DEFAULT NULL,
  birthday varchar(255) DEFAULT NULL,
  dateLastActived datetime DEFAULT NULL,
  email varchar(255) DEFAULT NULL,
  ipCreated varchar(255) DEFAULT NULL,
  ipLastActived varchar(255) DEFAULT NULL,
  name varchar(255) DEFAULT NULL,
  password varchar(255) DEFAULT NULL,
  sex varchar(255) DEFAULT NULL,
  PRIMARY KEY (id)
);

CREATE TABLE category (
  id int(11) NOT NULL AUTO_INCREMENT,
  dateCreated datetime DEFAULT NULL,
  deleted bit(1) NOT NULL,
  version int(11) DEFAULT NULL,
  name varchar(255) DEFAULT NULL,
  PRIMARY KEY (id)
);


CREATE TABLE thread (
  id int(11) NOT NULL AUTO_INCREMENT,
  dateCreated datetime DEFAULT NULL,
  deleted bit(1) NOT NULL,
  version int(11) DEFAULT NULL,
  content longtext,
  dateLastReplied datetime DEFAULT NULL,
  hit int(11) NOT NULL,
  ipCreated varchar(255) DEFAULT NULL,
  readonly bit(1) NOT NULL,
  replyCount int(11) NOT NULL,
  title varchar(255) DEFAULT NULL,
  topped bit(1) NOT NULL,
  author_id int(11) DEFAULT NULL,
  author_last_replied_id int(11) DEFAULT NULL,
  board_id int(11) DEFAULT NULL,
  PRIMARY KEY (id),
  FOREIGN KEY (author_last_replied_id) REFERENCES person (id),
  FOREIGN KEY (author_id) REFERENCES person (id)
);
alter table thread add FOREIGN KEY (board_id) REFERENCES board (id);

CREATE TABLE reply (
  id int(11) NOT NULL AUTO_INCREMENT,
  dateCreated datetime DEFAULT NULL,
  deleted bit(1) NOT NULL,
  version int(11) DEFAULT NULL,
  content varchar(255) DEFAULT NULL,
  floor int(11) NOT NULL,
  ipCreated varchar(255) DEFAULT NULL,
  title varchar(255) DEFAULT NULL,
  author_id int(11) DEFAULT NULL,
  thread_id int(11) DEFAULT NULL,
  PRIMARY KEY (id),
  FOREIGN KEY (author_id) REFERENCES person (id),
  FOREIGN KEY (thread_id) REFERENCES thread (id)
);

CREATE TABLE board(
  id int(11) NOT NULL AUTO_INCREMENT,
  dateCreated datetime DEFAULT NULL,
  deleted bit(1) NOT NULL,
  version int(11) DEFAULT NULL,
  description varchar(255) DEFAULT NULL,
  name varchar(255) DEFAULT NULL,
  replyCount int(11) NOT NULL,
  threadCount int(11) NOT NULL,
  category_id int(11) DEFAULT NULL,
  last_reply_id int(11) DEFAULT NULL,
  last_thread_id int(11) DEFAULT NULL,
  PRIMARY KEY (id),
  FOREIGN KEY (last_thread_id) REFERENCES thread (id),
  FOREIGN KEY (last_reply_id) REFERENCES reply (id),
  FOREIGN KEY (category_id) REFERENCES category (id)
);


CREATE TABLE board_administrator (
  board_id int(11) NOT NULL,
  person_id int(11) NOT NULL,
  PRIMARY KEY (board_id,person_id),
  FOREIGN KEY (person_id) REFERENCES person (id),
  FOREIGN KEY (board_id) REFERENCES board (id)
);



评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值