SSM框架搭建Web项目

SSM框架搭建Web项目

  • 1.基础概念
    • 1.1 Spring
    • 1.2 SpringMVC
    • 1.3 MyBatis
  • 2.项目搭建
    • 2.1 项目目录结构
    • 2.2 添加配置文件
      • 2.2.1 添加web.xml配置文件
      • 2.2.2 添加spring-mvc.xml配置文件
      • 2.2.3 添加applicationContext.xml配置文件
      • 2.2.4 添加jdbc.properties配置文件
      • 2.2.5 添加log4j.xml配置文件
    • 2.3配置拦截器
    • 2.4 添加Controller,Service,Dao,Mapper,Model,Jsp等文件
      • 2.4.1 新建LoginController.java
      • 2.4.2 新建LoginService.java
      • 2.4.3 新建User.java
      • 2.4.4 新建LoginDao.java
      • 2.4.5 新建LoginDao.xml
      • 2.4.5 新建login.jsp
    • 2.5 运行及结果
  • 3.可能出现的问题及解决方法
    • 3.1 问题:log4j:WARN 值为 "http://jakarta.apache.org/log4j" 的属性 "xmlns:log4j" 必须具有 "http://jakarta.apache.org/log4j/" 的值。
    • 3.2 问题:log4j:WARN No appenders could be found for logger (org.springframework.web.context.ContextLoader).

相关文章链接:

SpringMVC搭建一个Web项目

log4j.xml配置详解

logback.xml配置详解

Idea使用Maven搭建SSM框架Web项目

观前提示:

本文可在 SpringMVC搭建一个Web项目 基础上配置,Eclipse版本为Photon Release (4.8.0),Idea版本为ultimate 2019.1,JDK为1.8.0_141,Tomcat为9.0.12。

1.基础概念

SSM(Spring+SpringMVC+MyBatis)框架集由Spring、MyBatis两个开源框架整合而成(SpringMVC是Spring中的部分内容)。常作为数据源较简单的web项目的框架。

1.1 Spring

Spring就像是整个项目中装配bean的大工厂,在配置文件中可以指定使用特定的参数去调用实体类的构造方法来实例化对象。也可以称之为项目中的粘合剂。Spring的核心思想是IoC(控制反转),即不再需要程序员去显式地new一个对象,而是让Spring框架帮你来完成这一切。

1.2 SpringMVC

SpringMVC在项目中拦截用户请求,它的核心Servlet即DispatcherServlet承担中介或是前台这样的职责,将用户请求通过HandlerMapping去匹配Controller,Controller就是具体对应请求所执行的操作。SpringMVC相当于SSH框架中struts。

1.3 MyBatis

mybatis是对jdbc的封装,它让数据库底层操作变的透明。mybatis的操作都是围绕一个sqlSessionFactory实例展开的。mybatis通过配置文件关联到各实体类的Mapper文件,Mapper文件中配置了每个类对数据库所需进行的sql语句映射。在每次与数据库交互时,通过sqlSessionFactory拿到一个sqlSession,再执行sql命令。
  
页面发送请求给控制器,控制器调用业务层处理逻辑,逻辑层向持久层发送请求,持久层与数据库交互,后将结果返回给业务层,业务层将处理逻辑发送给控制器,控制器再调用视图展现数据。

2.项目搭建

2.1 项目目录结构

jar包链接地址:Jar包链接详情点我

完整目录结构
SSM框架搭建Web项目_第1张图片
所需jar包
SSM框架搭建Web项目_第2张图片

2.2 添加配置文件

按照2.1目录添加配置文件web.xmlspring-mvc.xmlapplicationContext.xmljdbc.propertieslog4j.xml。jdbc.properties为连接数据库相关数据,log4j.xml为日志配置。
部分标签解释请看上一篇文章,本文中大部分解释请看代码。

2.2.1 添加web.xml配置文件


<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" id="WebApp_ID" version="4.0">
  <display-name>MyDemodisplay-name>
  
  
  <context-param>
    <param-name>log4jConfigLocationparam-name>
    <param-value>classpath:resource/config/log4j.xmlparam-value>
  context-param>
  
  <listener>
    <listener-class>org.springframework.web.util.Log4jConfigListenerlistener-class>
  listener>
  
  
  <context-param>
    <param-name>contextConfigLocationparam-name>
    <param-value>classpath:resource/spring/applicationContext.xmlparam-value>
  context-param>
  
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class>
  listener>
  
  
  <servlet>
    <servlet-name>springServletservlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
    
    <init-param>
      <param-name>contextConfigLocationparam-name>
      <param-value>/WEB-INF/spring/spring-mvc.xmlparam-value>
    init-param>
    <load-on-startup>1load-on-startup>
  servlet>
  
  <servlet-mapping>
    <servlet-name>springServletservlet-name>
    <url-pattern>/url-pattern>
  servlet-mapping>
  
  
  <filter>
    <filter-name>encodingfilter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-class>
    <init-param>
      <param-name>encodingparam-name>
      <param-value>UTF-8param-value>
    init-param>
  filter>
  <filter-mapping>
    <filter-name>encodingfilter-name>
    
    <url-pattern>/*url-pattern>
  filter-mapping>
web-app>

2.2.2 添加spring-mvc.xml配置文件


<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.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">

  
  <context:component-scan base-package="cn.com.mydemo" use-default-filters="false">
    <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
  context:component-scan>
  
  
  <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    
    <property name="prefix" value="/WEB-INF/jsp/">property>
    
    <property name="suffix" value=".jsp">property>
  bean>
  
  
  <mvc:annotation-driven/>
  
  
  <mvc:interceptors>
    <mvc:interceptor>
      <mvc:mapping path="/**"/>
      <bean class="cn.com.mydemo.interceptor.RequestMappingInterceptor">bean>
    mvc:interceptor>
  mvc:interceptors>
  
  	
  <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>
    <property name="maxInMemorySize" value="40960">property>
  bean>
  
  
  <mvc:resources mapping="/static/**" location="/WEB-INF/static/"/>
beans>
  1. <context:component-scan>:配置自动扫描的包。默认情况下,context:component-scan查找使用构造型(stereotype)注解所标注的类,如@Component(组件),@Service(服务),@Controller(控制器),@Repository(数据仓库),并这些类注册为bean。
    注1:在SpringMVC的配置中为了防止Spring重复创建同一个类的实例,一般会用到<context:component-scan>的两个子标签<context:include-filter>&&<context:exclude-filter>。
    注2:在很多配置中一般都会把application.xml和spring-mvc.xml进行分开配置,这种配置可以他们保证各司其职,在web.xml的一般配置中spring-mvc.xml实例创建初始化是以DispatchServlet为入口,而application.xml实例创建初始化是以ContextLoadListener为入口的,容器的加载顺序: listener -> filter -> servlet ,所以spring容器先初始化,springmvc容器后初始化 。
  2. <back-package>:标识了<context:component-scan>元素所扫描的包,可以使用一些通配符进行配置。
  3. <context:include-filter>:用来告知哪些类需要注册成Spring Bean,使用type和expression属性一起协作来定义组件扫描策略。
    :对于<context:include-filter>标签来讲它会扫描基包下面所有spring注解的类,而不是仅仅扫描 @Controller 。这点需要非常的注意,这一般会导致一个常见的错误,那就是事务不起作用,补救的方法是添加 use-default-filters=“false”,实现扫描<context:component-scan>的包中只包含<context:include-filter>的包。
  4. <context:exclude-filter>:用来告知哪些类不需要注册成Spring Bean。实现扫描<context:component-scan>的包中且不包含<context:exclude-filter>的包。

2.2.3 添加applicationContext.xml配置文件


<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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
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
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">

  <description>spring配置description>
  
  
  <context:component-scan base-package="cn.com.mydemo">
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
  context:component-scan>
  
  
  
  <context:property-placeholder location="/WEB-INF/config/jdbc.properties"/>
  
  <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
    <property name="driverClassName" value="${jdbc.driver}"/>
    <property name="url" value="${jdbc.url}"/>
    <property name="username" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>
    
    
    <property name="initialSize" value="${jdbc.pool.initialPoolSize}"/>
    <property name="minIdle" value="${jdbc.pool.minPoolSize}"/>
    <property name="maxActive" value="${jdbc.pool.maxPoolSize}"/>
    
    
    <property name="maxWait" value="${jdbc.pool.maxIdleTime}"/>
    
    
    <property name="timeBetweenEvictionRunsMillis" value="${jdbc.pool.checkoutTimeout}"/>
    
    
    <property name="filters" value="wall,stat,log4j"/>
  bean>
  
  
  <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    
    <property name="mapperLocations" value="classpath:cn/com/mydemo/mapper/*.xml"/>
  bean>
  
  
  <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="basePackage" value="cn.com.mydemo.dao"/>
    <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
  bean>
  
  
  <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
  bean>
  
  
  
  <tx:annotation-driven transaction-manager="transactionManager"/>
beans>

2.2.4 添加jdbc.properties配置文件

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test
jdbc.username=root
jdbc.password=root

jdbc.pool.initialPoolSize=10
jdbc.pool.minPoolSize=5
jdbc.pool.maxPoolSize=40
jdbc.pool.maxIdleTime=20
jdbc.pool.checkoutTimeout=10000

2.2.5 添加log4j.xml配置文件

log4j.xml配置详解:log4j.xml配置详解




<log4j:configuration>
  
  <appender name="console" class="org.apache.log4j.ConsoleAppender">
    
    <layout class="org.apache.log4j.TTCCLayout"/>
  appender>
  
  
  <appender name="rollingAppender" class="org.apache.log4j.RollingFileAppender">
    
    <param name="File" value="${catalina.base}/logs/demo/RollingFileAppender.log"/>
    
    <param name="Append" value="true"/>
    
    <param name="MaxBackupIndex" value="10"/>
    
    <param name="MaxFileSize" value="5120KB"/>
    
    <layout class="org.apache.log4j.PatternLayout">
      
      <param name="ConversionPattern" value="[%d{yyyy-MM-dd HH:mm:ss:SSS}] [%-5p] [method:%l]%n%m%n%n"/>
    layout>
  appender>
  
  
  <appender name="dailyRollingAppender" class="org.apache.log4j.DailyRollingFileAppender">
    
    <param name="File" value="${catalina.base}/logs/demo/DailyRollingFileAppender.log"/>
    <param name="Append" value="true"/>
    <param name="Threshold" value="DEBUG" />
    
    <param name="DatePattern" value="yyyy-MM-dd"/>
    
    <layout class="org.apache.log4j.PatternLayout">
      <param name="ConversionPattern" value="[%p][%d{HH:mm:ss SSS}][%c]-[%m]%n"/>
    layout>
  appender>
  
  
  
  <logger name="org.apache.commons" additivity="false">
    <level value="ERROR"/>
    <appender-ref ref="dailyRollingAppender"/>
  logger>
  
  <logger name="org.mybatis.spring" additivity="false">
    <level value="ERROR"/>
    <appender-ref ref="dailyRollingAppender"/>
  logger>
  <logger name="java.sql" additivity="false">
    <level value="ERROR"/>
    <appender-ref ref="dailyRollingAppender"/>
  logger>
  
  <logger name="org.apache.ibatis" additivity="false">
    <level value="ERROR"/>
    <appender-ref ref="dailyRollingAppender" /> 
  logger>
  
  <logger name="org.springframework" additivity="false">
    <level value="ERROR"/>
    <appender-ref ref="dailyRollingAppender"/>
  logger>
  <logger name="com.mchange.v2" additivity="false">
    <level value="ERROR"/>
    <appender-ref ref="dailyRollingAppender"/>
  logger>
  
  <logger name="com.alibaba.druid.filter.stat" additivity="false">
    <level value="WARN"/>
    <appender-ref ref="dailyRollingAppender"/>
  logger>
  <logger name="com.alibaba.druid.pool" additivity="false">
    <level value="WARN"/>
    <appender-ref ref="dailyRollingAppender"/>
  logger>
  <logger name="druid.sql.Connection" additivity="false">
    <level value="WARN"/>
    <appender-ref ref="dailyRollingAppender"/>
  logger>
  <logger name="druid.sql.DataSource" additivity="false">
    <level value="WARN"/>
    <appender-ref ref="dailyRollingAppender"/>
  logger>
  <logger name="druid.sql.ResultSet" additivity="false">
    <level value="WARN"/>
    <appender-ref ref="dailyRollingAppender"/>
  logger>
  <logger name="druid.sql.Statement" additivity="false">
    <level value="WARN"/>
    <appender-ref ref="dailyRollingAppender"/>
  logger>
  
  
  <root>
    <appender-ref ref="console"/>
    <appender-ref ref="rollingAppender"/>
    <appender-ref ref="dailyRollingAppender"/>
  root>
log4j:configuration>

2.3配置拦截器

配置拦截器RequestMappingInterceptor.java

package cn.com.mydemo.interceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

public class RequestMappingInterceptor extends HandlerInterceptorAdapter {

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		// TODO Auto-generated method stub
		super.afterCompletion(request, response, handler, ex);
	}

	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		// TODO Auto-generated method stub
		super.postHandle(request, response, handler, modelAndView);
	}

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		// TODO Auto-generated method stub
		return super.preHandle(request, response, handler);
	}
}
  1. preHandle在业务处理器处理请求之前被调用。预处理,可以进行编码、安全控制等处理。
  2. postHandle在业务处理器处理请求执行完成后,生成视图之前执行。后处理(调用了Service并返回ModelAndView,但未进行页面渲染),有机会修改ModelAndView。
  3. afterCompletion在DispatcherServlet完全处理完请求后被调用,可用于清理资源等。返回处理(已经渲染了页面),可以根据ex是否为null判断是否发生了异常,进行日志记录。

2.4 添加Controller,Service,Dao,Mapper,Model,Jsp等文件

2.4.1 新建LoginController.java

package cn.com.mydemo.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import cn.com.mydemo.model.User;
import cn.com.mydemo.service.LoginService;

/**
 * @Description 登录Controller
 * @author jjy
 * @Creation 2019-02-21
 */
@Controller
public class LoginController {
	
	@Autowired
	private LoginService loginService;
	
	private static Logger log = LoggerFactory.getLogger(LoginController.class);
	
	/**
	 * @Description 初始化登录页面
	 * @param model
	 * @return
	 * @Creation 2019-02-21 by jjy
	 */
	@RequestMapping(value = "/")
	public String init(Model model) {
		User us = new User("1");
		log.debug("搜索用户id为1的用户信息");
		User user = loginService.selectByID(us);
		model.addAttribute("id", user.getId());
		model.addAttribute("name", user.getName());
		return "login";
	}
}

@Autowired自动装配,其作用是为了消除代码Java代码里面的getter/setter与bean属性中的property,当Spring发现@Autowired注解时,将自动在代码上下文中找到和其匹配(默认是类型匹配)的Bean,并自动注入到相应的地方去。在application.xml配置为

2.4.2 新建LoginService.java

package cn.com.mydemo.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import cn.com.mydemo.dao.LoginDao;
import cn.com.mydemo.model.User;

/**
 * @Description 登录Service
 * @author jjy
 * @Creation 2019-02-21
 */
@Service
@Transactional(readOnly = true)
public class LoginService {

	@Autowired
	private LoginDao loginDao;
	
	/**
	 * @Description 根据用户ID搜索用户
	 * @param user
	 * @return
	 * @Creation 2019-02-21 by jjy
	 */
	public User selectByID(User user) {
		return loginDao.selectByID(user);
	}
}
  1. @Service:业务层的类注解。
  2. @Transactional:声明式事务管理 编程中使用的注解

:@Transactional注解配置需在applicationContext.xml中配置

 
  <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
  bean>
  
  
  
  <tx:annotation-driven transaction-manager="transactionManager"/>

@Transactional 可以作用于接口、接口方法、类以及类方法上。当作用于类上时,该类的所有 public 方法将都具有该类型的事务属性,同时,我们也可以在方法级别使用该标注来覆盖类级别的定义。

虽然 @Transactional 注解可以作用于接口、接口方法、类以及类方法上,但是 Spring 建议不要在接口或者接口方法上使用该注解,因为这只有在使用基于接口的代理时它才会生效。另外, @Transactional 注解应该只被应用到 public 方法上,这是由 Spring AOP 的本质决定的。如果你在 protected、private 或者默认可见性的方法上使用 @Transactional 注解,这将被忽略,也不会抛出任何异常。

@Transactional属性

属性 类型 描述
value String 可选的限定描述符,指定使用的事务管理器
propagation enum: Propagation 可选的事务传播行为设置
isolation enum: Isolation 可选的事务隔离级别设置
readOnly boolean 读写或只读事务,默认读写
timeout int (in seconds granularity) 事务超时时间设置
rollbackFor Class对象数组,必须继承自Throwable 导致事务回滚的异常类数组
rollbackForClassName 类名数组,必须继承自Throwable 导致事务回滚的异常类名字数组
noRollbackFor Class对象数组,必须继承自Throwable 不会导致事务回滚的异常类数组
noRollbackForClassName 类名数组,必须继承自Throwable 不会导致事务回滚的异常类名字数组

2.4.3 新建User.java

package cn.com.mydemo.model;

/**
 * @Description 用户实体
 * @author jjy
 * @Creation 2019-02-21
 */
public class User {

	private String id;
	private String name;
	
	public User() {
	}
	
	public User(String id) {
		this.id = id;
	}
	
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}

2.4.4 新建LoginDao.java

package cn.com.mydemo.dao;

import cn.com.mydemo.model.User;

/**
 * @Description 登录Dao
 * @author jjy
 * @Creation 2019-02-21
 */
public interface LoginDao {

	User selectByID(User user);
}

2.4.5 新建LoginDao.xml



<mapper namespace="cn.com.mydemo.dao.LoginDao">
  
  <select id="selectByID" parameterType="cn.com.mydemo.model.User" resultType="cn.com.mydemo.model.User">
    SELECT ID,NAME FROM USER WHERE ID = #{id}
  select>
mapper>

2.4.5 新建login.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>




Login


	

2.5 运行及结果

数据库数据
在这里插入图片描述
页面
SSM框架搭建Web项目_第3张图片
控制台日志信息
在这里插入图片描述

3.可能出现的问题及解决方法

具体问题请根据实际原因解决,以下问题为我部署项目时的问题及解决方法,仅供参考。

3.1 问题:log4j:WARN 值为 “http://jakarta.apache.org/log4j” 的属性 “xmlns:log4j” 必须具有 “http://jakarta.apache.org/log4j/” 的值。

在配置完log4j.xml文件后启动eclipse,出现了以下所示WARN:
在这里插入图片描述

查看了下我最开始的log4j.xml部分配置如下




<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j">

修改后如下所示




<log4j:configuration>

3.2 问题:log4j:WARN No appenders could be found for logger (org.springframework.web.context.ContextLoader).

启动eclipse,发现log4j出现以下所示WARN:
在这里插入图片描述

查看了下我最开始的web.xml部分配置如下


  <context-param>
    <param-name>contextConfigLocationparam-name>
    <param-value>/WEB-INF/spring/applicationContext.xmlparam-value>
  context-param>
  
  <context-param>
    <param-name>log4jConfigLocationparam-name>
    <param-value>/WEB-INF/config/log4j.xmlparam-value>
  context-param>
  
  
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class>
  listener>
  
  <listener>
    <listener-class>org.springframework.web.util.Log4jConfigListenerlistener-class>
  listener>

修改后如下所示

  
  <context-param>
    <param-name>log4jConfigLocationparam-name>
    <param-value>/WEB-INF/config/log4j.xmlparam-value>
  context-param>
  
  <listener>
    <listener-class>org.springframework.web.util.Log4jConfigListenerlistener-class>
  listener>
  
  
  <context-param>
    <param-name>contextConfigLocationparam-name>
    <param-value>/WEB-INF/spring/applicationContext.xmlparam-value>
  context-param>
  
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class>
  listener>

注意:请严格按照修改后的配置顺序。

你可能感兴趣的:(Java,Web)