项目开发记录:个人博客(personal_blog)之框架搭建

之前对JavaWeb的学习不深,打算写一个简单的博客系统来复习一下学过的知识。


项目框架搭建:

项目基于Maven构建,IDE使用的是IDEA。

使用的框架:
- SpringMVC
- Spring
- Hibernate

持久层框架使用的是Hibernate,为什么不用流行的Mybatis,很简单,因为
我 不 会!(很快就要学,希望简单一点……)

不多BB,先给出pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>me.ethan</groupId>
    <artifactId>personal_blog</artifactId>
    <version>1.0-SNAPSHOT</version>
    <!-- 将配置包的版本信息都统一放入此处,方便管理-->
    <properties>
        <springVersion>4.3.13.RELEASE</springVersion>
        <hibernateVersion>5.2.10.Final</hibernateVersion>
        <jstlVersion>1.2</jstlVersion>
        <!--<taglibVersion>1.1.2</taglibVersion>-->
        <servletVersion>4.0.0</servletVersion>
        <jspVersion>2.2</jspVersion>
        <mysqlVersion>5.1.38</mysqlVersion>
        <c3p0Version>0.9.1.2</c3p0Version>
        <jsonVersion>1.9.13</jsonVersion>
        <jacksonVersion>2.5.0</jacksonVersion>
        <log4jVersion>1.2.17</log4jVersion>
        <fileuploadVersion>1.3.1</fileuploadVersion>
        <lombokVersion>1.16.10</lombokVersion>
    </properties>

    <dependencies>
        <!-- 单元测试 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
        <!--spring四个核心jar包 + spring-orm-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>${springVersion}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${springVersion}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${springVersion}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-expression</artifactId>
            <version>${springVersion}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>${springVersion}</version>
        </dependency>

        <!--spring-web + spring-webmvc-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${springVersion}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${springVersion}</version>
        </dependency>

        <!--hibernate-->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>${hibernateVersion}</version>
        </dependency>

        <!-- hibernate 缓存, 视情况添加-->
        <!--<dependency>-->
        <!--<groupId>org.hibernate</groupId>-->
        <!--<artifactId>hibernate-ehcache</artifactId>-->
        <!--<version>${hibernateVersion}</version>-->
        <!--</dependency>-->

        <!--servlet + jsp-->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>${servletVersion}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>${jspVersion}</version>
            <scope>provided</scope>
        </dependency>

        <!--JSTL-->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>${jstlVersion}</version>
        </dependency>

        <!--mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${mysqlVersion}</version>
        </dependency>

        <!-- c3p0数据库连接池-->
        <dependency>
            <groupId>c3p0</groupId>
            <artifactId>c3p0</artifactId>
            <version>${c3p0Version}</version>
        </dependency>

        <!-- json数据 使springMVC可以返回json值 ,视情况添加-->
        <dependency>
            <groupId>org.codehaus.jackson</groupId>
            <artifactId>jackson-mapper-asl</artifactId>
            <version>${jsonVersion}</version>
        </dependency>

        <!-- Jackson可以轻松的将Java对象转换成json对象和xml文档,同样也可以将json、xml转换成Java对象-->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>${jacksonVersion}</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>${jacksonVersion}</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>${jacksonVersion}</version>
        </dependency>

        <!-- log4j配置, 视情况添加-->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>${log4jVersion}</version>
        </dependency>

        <!--文件 上传-->
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>${fileuploadVersion}</version>
        </dependency>

        <!-- lombok插件导包-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${lombokVersion}</version>
        </dependency>

    </dependencies>

</project>

然后是配置文件:

  • DataBaseConfig.properties(里面是常用的一些数据库配置,用于在Spring的配置文件中引用)
#database connection config
jdbc.driver = com.mysql.jdbc.Driver
jdbc.url = jdbc:mysql://127.0.0.1:3306/数据库名?useUnicode=true&characterEncoding=utf-8
jdbc.username = 用户名
jdbc.password = 密码

#hibernate config
hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect
hibernate.show_sql = true
hibernate.format_sql = true
hibernate.hbm2ddl.auto = update
hibernate.connection.autocommit = true
  • applicationContext.xml(Spring的配置文件)
<?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:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation=
               "http://www.springframework.org/schema/beans
                http://www.springframework.org/schema/beans/spring-beans.xsd
                http://www.springframework.org/schema/context
                http://www.springframework.org/schema/context/spring-context.xsd
                http://www.springframework.org/schema/tx
                http://www.springframework.org/schema/tx/spring-tx.xsd">
    <!--********************************************配置Spring***************************************-->
    <!--自动扫描-->
    <context:component-scan base-package="me.ethan">
        <!--扫描时跳过 @Controller 注解的JAVA类(控制器)-->
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

    <!--********************************************配置hibernate********************************************-->
    <!--扫描配置文件(这里指向的是之前配置的那个DataBaseConfig.properties)-->
    <context:property-placeholder location="classpath:hibernate/DataBaseConfig.properties"/>

    <!--配置数据源-->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
        <property name="driverClass" value="${jdbc.driver}"/>  <!--数据库连接驱动-->
        <property name="jdbcUrl" value="${jdbc.url}"/>     <!--数据库地址-->
        <property name="user" value="${jdbc.username}"/>   <!--用户名-->
        <property name="password" value="${jdbc.password}"/>   <!--密码-->
        <property name="maxPoolSize" value="40"/>      <!--最大连接数-->
        <property name="minPoolSize" value="1"/>       <!--最小连接数-->
        <property name="initialPoolSize" value="10"/>      <!--初始化连接池内的数据库连接-->
        <property name="maxIdleTime" value="20"/>  <!--最大空闲时间-->
    </bean>

    <!--配置session工厂,注意hibernate的版本-->
    <bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="packagesToScan" value="me.ethan.entity"/>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop> <!--hibernate根据实体自动生成数据库表-->
                <prop key="hibernate.dialect">${hibernate.dialect}</prop>   <!--指定数据库方言-->
                <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>     <!--在控制台显示执行的数据库操作语句-->
                <prop key="hibernate.format_sql">${hibernate.format_sql}</prop>     <!--在控制台显示执行的数据哭操作语句(格式)-->
                <prop key="hibernate.current_session_context_class">
                    org.springframework.orm.hibernate5.SpringSessionContext
                </prop>
                <prop key="hibernate.connection.autocommit">${hibernate.connection.autocommit}</prop> <!--自动提交,配合getCurrentSession一起使用-->
            </props>
        </property>
    </bean>

    <!-- 事物管理器配置,注意hibernate的版本 -->
    <bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>

    <!--启用事务注解-->
    <tx:annotation-driven proxy-target-class="true" transaction-manager="transactionManager"/>
</beans>
  • dispatcher-servlet.xml(SpringMVC的配置文件)
<?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:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 启动注解驱动的spring MVC功能,注册请求url和注解POJO类方法的映射-->
    <mvc:annotation-driven/>

    <!--配置注解扫描的包-->
    <context:component-scan base-package="me.ethan.controller"/>

    <!--配置视图解析器-->
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
        <property name="prefix" value="views/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

    <!--静态资源映射-->
    <mvc:resources mapping="/js/**" location="/resources/js/" />
    <mvc:resources mapping="/css/**" location="/resources/css/" />
    <mvc:resources mapping="/img/**" location="/resources/img/" />
</beans>
  • web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
    <welcome-file-list>
        <welcome-file>/index.jsp</welcome-file>
    </welcome-file-list>

    <!--加载spring配置文件到上下文中-->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring/applicationContext.xml</param-value>
    </context-param>

    <!--配置监听器-->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!--配置字符集过滤器-->
    <filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!--配置DispatcherServlet-->
    <servlet>
        <servlet-name>DispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring/dispatcher-servlet.xml</param-value>
        </init-param>
        <!--配置容器在启动的时候就加载这个servlet并实例化-->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>DispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

</web-app>
  • 补充:项目目录及结构

补充:项目目录结构


遇到的问题及解决方案:

搭建SSH框架的过程中,遇到了不少棘手的问题。写这篇博文的初衷就是为了记录开发中的问题,与大家一起分享。一些拙见,抛砖引玉:

  • IDEA中在web.xml中配置了ContextLoaderListener报异常:ClassNotFound
分析原因:与maven的依赖导入有关……
解决方法一:打开project structure,在Aritifacts下,右边的依赖目录的上方,右击项目名称,选择Put Into Output Root
解决方法二:自行在左边的WEB-INF应用目录下,新建一个Directory,名为lib,在右边 右击所有 有关spring的jar包(包括spring mvc的有关依赖),选择put into WEB-INF/lib
  • 运行报错 : org.hibernate.MappingException: Could not get constructor for
    org.hibernate.persister.entity.SingleTableEntityPersister
分析原因:
1.实体类的属性对象没有设置setter或者getter,或者是设置setter或者getter时没有按照Hibernate规范。
2.没有导入javassist的jar文件。(加入lib目录下才可以)
3.实体类中的属性对象名和映射文件的property name不一致。 
  • 启动项目的时候一直出现如下的提示:Causedby:org.springframework.beans.factory.NoSuchBeanDefinitionException:
    No qualifying bean of type
    [com.chainmobile.test.service.LoginService] found for dependency:
    expected at least 1 bean which qualifies as autowire candidate for
    this dependency. Dependency annotations:即注入类型未找到的异常
分析原因:把service注解到interface上面了 
解决方法:需要把这个放到service的实现类上。
  • Error executing DDL via JDBC Statement导致的建表失败
分析原因:
1.数据库方言配置错误,如我的配置原来是    hibernate.dialect = org.hibernate.dialect.MySQLInnoDBDialect  修改为   hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect  即可。
2.依赖导入错误,需要引入相关的依赖
这里提一句:MySQL5.5以后默认使用InnoDB存储引擎,其中InnoDB和BDB提供事务安全表,其它存储引擎都是非事务安全表。
  • Could not obtain transaction-synchronized Session for current thread
    提示无法获取当前线程的事务同步session
分析原因:
getCurrentSession方法与事务有关,分析一下getCurrentSession和openSession的区别:
1.openSession每次打开都是新的Session,所以多次获取的Session实例是不同的,并且需要人为的调用close方法进行Session关闭
2.getCurrentSession是从当前上下文中获取Session并且会绑定到当前线程,第一次调用时会创建一个Session实例,如果该Session未关闭,后续多次获取的是同一个Session实例;事务提交或者回滚时会自动关闭Sesison,无需人工关闭
解决方法:可以使用openSession获取session实例;最好的方法是使用事务管理,仍然使用getCurrentSession
  • spring的schema约束的添加
需要注意:在添加schema约束时除了添加约束头部,还要添加相应的两个约束文件所在URL。
Spring推荐我们使用不带版本号的schema
  • Hibernate注解开发:如何生成UUID的主键策略?
//配置uuid,本来jpa是不支持uuid的,但借用hibernate的方法可以实现。
@GenericGenerator(name = "uuid", strategy = "uuid")
@GeneratedValue(generator = "uuid")
  • Spring @Transactional事务配置无效原因
分析原因:
1.如使用mysql且引擎是MyISAM,则事务会不起作用,原因是MyISAM不支持事务,可以改成InnoDB
2.如果使用了spring+springmvc,则context:component-scan重复扫描问题可能会引起事务失败。(也是本次配置事务管理却失效的原因)
3.@Transactional 注解开启配置,必须放到listener里加载,如果放到DispatcherServlet的配置里,事务也是不起作用的。
4.@Transactional 注解只能应用到 public 可见度的方法上。 如果你在 protectedprivate 或者 package-visible 的方法上使用 @Transactional 注解,它也不会报错,事务也会失效。
5. Spring团队建议在具体的类(或类的方法)上使用 @Transactional 注解,而不要使用在类所要实现的任何接口上。在接口上使用 @Transactional注解,只能当你设置了基于接口的代理时它才生效。因为注解是不能继承的,这就意味着如果正在使用基于类的代理时,那么事务的设置将不能被基于类的代理所识别,而且对象也将不会被事务代理所包装。
解决方法:修改配置文件,applicationContext.xml中扫描过的包,在dispatcher-servlet.xml中不能重复扫描。

enmmm……开发暂时遇到了一些难题,由于自己前端学的不好,尝试了layui和easyui两个框架后都失败了,因此决定先把JavaScript和JQuery好好看看,打好基础,前端页面开发完成再写逻辑吧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值