最近在學習ssm框架,由於不知名的緣由,一個小小的框架居然花了我四五天的時間,期間遇到了近百個各類各樣的錯誤,也正是因爲這些錯誤,讓我對ssm框架有了進一步的認識,謹做略記,但願利於他人,僅供和我同樣剛入門的新手參考,一塊兒學習。理論的東西就很少少了,直接上配置吧。css
這個就很少說了,直接百度,各類博客有不少,寫得都很詳細,可是要注意版本的問題,我懷疑以前我遇到的各類問題都和引入的spring之類的版本衝突有關,最好找發佈時間不長的教程。
html
先看看整個項目的目錄吧,目錄結構以下圖:
java
須要注意的就是:建立出來以後,目錄結構裏的main>java,test>java,test>resources都須要本身建立,能夠直接在相應的文件夾上右鍵建立,也能夠在file>project structure下建立,建立完directory以後須要右鍵mark as相應的文件夾。mysql
還有就是會遇到在src>main>java下建立同級包的時候會默認合併路徑,沒法在一個包下建立同級包,按下圖操做,取消勾選Hide Empty Middle Packages便可。web
引入maven依賴須要注意的就是版本的統一管理,相關的包引入的版本最好能一致,保證兼容,將版本寫在<properties></properties>裏,而後再統一引用,既方便管理,又能避免不少問題,有點封裝的意思。我折騰了好久極可能就是版本是隨便選擇的,因此致使各類問題。引入的依賴以下:spring
<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/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>demon</groupId> <artifactId>demon</artifactId> <packaging>war</packaging> <version>1.0-SNAPSHOT</version> <name>demon Maven Webapp</name> <url>http://maven.apache.org</url> <properties> <spring.version>4.0.2.RELEASE</spring.version> <mybatis.version>3.2.6</mybatis.version> <slf4j.version>1.7.7</slf4j.version> <log4j.version>1.2.17</log4j.version> </properties> <dependencies> <!--junit單元測試--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <!--spring相關的包--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-oxm</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${spring.version}</version> </dependency> <!--mybatis相關的包--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>${mybatis.version}</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>1.2.3</version> </dependency> <!--java ee--> <dependency> <groupId>javax</groupId> <artifactId>javaee-api</artifactId> <version>7.0</version> </dependency> <!--mysql--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.39</version> </dependency> <dependency> <groupId>commons-dbcp</groupId> <artifactId>commons-dbcp</artifactId> <version>1.2.2</version> </dependency> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <!--日誌管理的包--> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>${log4j.version}</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.1.41</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>org.codehaus.jackson</groupId> <artifactId>jackson-mapper-asl</artifactId> <version>1.9.13</version> </dependency> <!--文件上傳組件--> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.1</version> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.4</version> </dependency> <dependency> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> <version>1.9</version> </dependency> <dependency> <groupId>com.esotericsoftware.reflectasm</groupId> <artifactId>reflectasm</artifactId> <version>1.09</version> </dependency> <!--hibernate驗證框架--> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>5.2.4.Final</version> </dependency> </dependencies> <build> <finalName>demon</finalName> <resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.xml</include> </includes> </resource> <resource> <directory>src/main/resources</directory> <includes> <include>*.xml</include> <include>*.properties</include> </includes> </resource> </resources> </build> </project>
以上就是maven依賴的包,<build></build>標籤裏的內容是將resources目錄和java目錄下的文件也加到項目路徑,由於我啓動項目出現了mapper.xml,spring-mvc.xml文件沒法加載的狀況。sql
create table `test`.`user`( `username` varchar(25) NOT NULL COMMENT `用戶名`, `password` varchar(25) NOT NULL COMMENT `密碼`, PRIMARYKEY(`username`) )ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT `用戶信息表`;
在po包下建立UserPo.java文件,記得加上構造方法,以及默認的構造方法,代碼以下:
數據庫
package com.demon.user.po; /** * @author zhulongkun20@163.com * @date 2018/3/21 14:22 */ public class UserPo { private String username; private String password; public UserPo(String username, String password) { this.username = username; this.password = password; } public UserPo() { } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String toString() { return "===== UserPo : [ username : " + username + ", password : " + password + " ] ====="; } }
建立UserDao.java接口,是接口,不是類!放與數據庫操做相關的方法:apache
package com.demon.user.dao; import com.demon.user.po.UserPo; import org.apache.ibatis.annotations.Param; import org.springframework.stereotype.Repository; /** * @author zhulongkun20@163.com * @date 2018/3/21 14:23 */ @Repository public interface UserDao { UserPo selectUserByUsername(@Param("username") String username); }
記得給接口加上@Repository註解。json
建立UserService.java,這個也是接口,不是方法,裏面放與業務邏輯。
package com.demon.user.service; import com.demon.user.po.UserPo; /** * @author zhulongkun20@163.com * @date 2018/3/21 14:26 */ public interface UserService { public UserPo selectUserByUsername(String username); }
建立UserServiceImpl類,實現UserService接口,記得加上@Service註解,否則spring配置文件不能建立bean。
package com.demon.user.service; import com.demon.user.dao.UserDao; import com.demon.user.po.UserPo; import org.springframework.stereotype.Service; import javax.annotation.Resource; /** * @author zhulongkun20@163.com * @date 2018/3/21 14:27 */ @Service public class UserSeviceImpl implements UserService { @Resource private UserDao userDao; public UserPo selectUserByUsername(String username) { return userDao.selectUserByUsername(username); } }
記得給類加上@Controller註解,還有@RequestMapping("")註解,否則會報錯,找不到controller。
package com.demon.user.controller; import com.demon.user.po.UserPo; import com.demon.user.service.UserService; import org.apache.log4j.Logger; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; /** * @author zhulongkun20@163.com * @date 2018/3/21 15:34 */ @Controller @RequestMapping("/user") public class UserController { private static Logger logger = Logger.getLogger(UserController.class); @Resource private UserService userService; @RequestMapping("/showUser.do") public ModelAndView showUser(HttpServletRequest request) { String username = request.getParameter("username"); UserPo userPo = userService.selectUserByUsername(username); if (userPo != null) { logger.info("====== request success."); request.setAttribute("username", username); return new ModelAndView("success", "message", username); } else { logger.info("====== request failed."); return new ModelAndView("failed", "message", "request failed, try again!"); } } }
<?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="com.demon.user.dao.UserDao"> <resultMap id="BaseResultMap" type="com.demon.user.po.UserPo"> <result column="username" property="username" jdbcType="VARCHAR"/> <result column="password" property="password" jdbcType="VARCHAR"/> </resultMap> <select id="selectUserByUsername" resultMap="BaseResultMap" parameterType="java.lang.String"> SELECT username, password FROM user WHERE username = #{username, jdbcType=VARCHAR} </select> </mapper>
注意命名空間namespace的指向的包。
在src>main>resources下建立log4j.properties文件,主要是log4j的配置,記得建立一個存放日誌的file,更改日誌輸出的目標文件。
# 配置 log4j.rootLogger=debug,stdout,D,E ### 輸出信息到控制擡 ### log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target=System.out log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=[%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n ### 輸出DEBUG 級別以上的日誌到文件F://logs/debug.log ### log4j.appender.D=org.apache.log4j.FileAppender log4j.appender.D.File=F:/coquetry-demon/logs/debug.log log4j.appender.D.Append=true log4j.appender.D.Threshold=DEBUG log4j.appender.D.layout=org.apache.log4j.PatternLayout log4j.appender.D.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n ### 輸出ERROR 級別以上的日誌到文件F://logs/error.log ### log4j.appender.E=org.apache.log4j.FileAppender log4j.appender.E.File=F:/coquetry-demon/logs/error.log log4j.appender.E.Append=true log4j.appender.E.Threshold=ERROR log4j.appender.E.layout=org.apache.log4j.PatternLayout log4j.appender.E.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%
將數據庫的用戶名,密碼等單獨放到jdbc.properties文件中,方便項目的移植和管理。
database.driver=com.mysql.jdbc.Driver database.url=jdbc:mysql://localhost:3306/你的數據庫名 database.username=你的數據庫用戶名 database.password=你的數據庫密碼
建立spring-mybatis.xml配置文件:
<?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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <context:component-scan base-package="com.demon.user"/> <context:property-placeholder location="classpath:/jdbc.properties"/> <!--connect to database--> <bean id="jdbcDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="${database.driver}"/> <property name="url" value="${database.url}"/> <property name="username" value="${database.username}"/> <property name="password" value="${database.password}"/> </bean> <!--spring and mybatis configuration here--> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="jdbcDataSource"/> <property name="mapperLocations" value="classpath:com/demon/user/mapper/*.xml"/> </bean> <!--the package name where contains dao, enable auto scan--> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.demon.user.dao"/> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/> </bean> <!--transaction manager--> <!-- <tx:annotation-driven transaction-manager="transactionManager"/> --> <!--add transaction operation--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="jdbcDataSource"/> </bean> </beans>
建立spring-mvc.xml文件,配置spring mvc:
<?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-4.0.xsd"> <context:component-scan base-package="com.demon.user.controller"/> <mvc:annotation-driven/> <bean id="mappingJacksonHttpMessageConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"> <property name="supportedMediaTypes"> <list> <value>text/html;charset=UTF-8</value> </list> </property> </bean> <!-- 啓動SpringMVC的註解功能,完成請求和註解POJO的映射 --> <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"> <property name="messageConverters"> <list> <ref bean="mappingJacksonHttpMessageConverter"/> <!-- JSON轉換器 --> </list> </property> </bean> <!-- 定義跳轉的文件的先後綴 ,視圖模式配置--> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/> <property name="prefix" value="/WEB-INF/jsp/"/> <property name="suffix" value=".jsp"/> </bean> <!--使用默認的Servlet來響應靜態文件--> <mvc:default-servlet-handler/> <!-- 配置文件上傳,若是沒有使用文件上傳能夠不用配置,固然若是不配,那麼配置文件中也沒必要引入上傳組件包 --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!-- 默認編碼 --> <property name="defaultEncoding" value="utf-8"/> <!-- 文件大小最大值 --> <property name="maxUploadSize" value="10485760000"/> <!-- 內存中的最大值 --> <property name="maxInMemorySize" value="40960"/> </bean> </beans>
這個就是要注意<servlet-mapping></servlet-mapping>攔截器的配置,這裏會產生不少錯誤。
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" > <web-app> <display-name>Archetype Created Web Application</display-name> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <session-config> <session-timeout>60</session-timeout> </session-config> <filter> <filter-name>encode</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> </filter> <filter-mapping> <filter-name>encode</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <context-param> <param-name>log4jConfigLocation</param-name> <param-value>classpath:log4j.properties</param-value> </context-param> <listener> <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class> </listener> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring-mybatis.xml</param-value> </context-param> <!-- Spring監聽器 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- 防止Spring內存溢出監聽器 --> <listener> <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class> </listener> <!--RequestContextListener將Spring容器與Web容器結合的更加密切。這是可選配置--> <listener> <listener-class> org.springframework.web.context.request.RequestContextListener </listener-class> </listener> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring-mvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> </web-app>
到這裏三大框架整合完畢了,主要是配置文件容易出錯。
在test>java下建一個包,而後創建一個MybatisTest.java的測試類,測試一下能不能從數據庫裏讀出信息。
package com.demon.test; import com.demon.user.po.UserPo; import com.demon.user.service.UserService; import org.apache.log4j.Logger; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import javax.annotation.Resource; /** * @author zhulongkun20@163.com * @date 2018/3/21 15:00 */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = {"classpath:spring-mvc.xml", "classpath:spring-mybatis.xml"}) public class MybatisTest { private static Logger logger = Logger.getLogger(MybatisTest.class); @Resource private UserService userService; @Test public void selectUserByUsernameTest() { String username = "admin1"; UserPo userPo = userService.selectUserByUsername(username); if (userPo != null) { logger.info("======= Test Result =======\n"); logger.info(userPo.toString()); logger.info("======= Result End =======\n"); } } }
若是能在日誌裏找到輸出信息,那恭喜,mybatis沒問題,若是有錯,那就查日誌,而後去各類百度吧,好事多磨,放平心態。。
簡單的測試頁面:
index.jsp:
<%-- Created by IntelliJ IDEA. User: zhulongkun Date: 2018/3/21 Time: 13:25 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>歡迎訪問</title> </head> <body> <% String path = request.getContextPath(); %> <div align="center"> <form action="<%=path%>/user/showUser.do" method="post"> <p>歡迎你的訪問, 請輸入我的信息</p> <hr/> <p> <label> <input type="text" name="username" width="300px" height="45px"/> </label> </p> <p> <input type="submit" value="提交" width="100px" height="45px"/></p> </form> </div> </body> </html>
請求成功則跳轉到success.jsp:
<%@ page import="com.demon.user.po.UserPo" %><%-- Created by IntelliJ IDEA. User: zhulongkun Date: 2018/3/21 Time: 15:44 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>request success</title> </head> <body> <% String username = (String) request.getAttribute("username"); %> <div align="center"> <p> <h1>welcome <%=username%> !</h1 </div> </body> </html>
若是請求失敗,則跳轉到failed.jsp:
<%-- Created by IntelliJ IDEA. User: zhulongkun Date: 2018/3/21 Time: 15:45 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>request failed</title> </head> <body> <div align="center"> <h1>request failed, try again, please.</h1> </div> </body> </html>
看似簡單,卻折騰了幾天,不少次感到絕望,可是不修bug,人生還有什麼意義?要不斷的找緣由,不斷地改錯,才能不斷地進步,也算是一點心得吧!
以上です!