一、简介
- SSM是目前比较流行的Java Web框架,具体我就不多介绍了,网上一大堆。但是关于SSM的配置,网上很多教程使用的是比较老的Spring版本,总会有问题。本文的目的是帮助读者快速搭建起一套SSM的环境,而并非解析该框架或者说清楚每处配置的具体含义。
二、环境要求
- JDK 11(1.8以上应该都适用)
- Eclipse - Java EE,2019-03
- Spring Framework 5.1.6.RELEASE
- Mybatis 3.5.1
- Tomcat 9.0.x
三、配置Gradle项目
- 首先我们新建项目,在项目列表中选择Others,然后搜索“Gradle”,选择Gradle Project,如果找不到Gradle Project,请升级你的Eclipse版本。这里不对单独安装Gradle进行说明。
- 按照默认配置进行Gradle Project设置即可,可以自己定义项目名称更改项目位置,直到创建完成。这样我们便得到了一个Gradle Project项目。
四、配置Dynamic Web Module项目
- 这时候我们得到的仅仅是一个Gradle项目,如果你是做普通的Java SE开发,那么到这就可以关掉了。但是我们是要配置SSM,而SSM是基于Java EE的项目的。所以我们在项目上右击,选择最下面的Properties,然后在左侧边栏找到Project Facets,这时候Eclipse会提示我们说“This project is not configured to use project facets. Converting this project to faceted form will allow you to easily control the available technologies.”,我们直接点击下面的Convent to faceted from,就得到了一个菜单。
- 在这个菜单里我们找到Dynamic Web Module,然后勾选它,右侧可以选择版本,默认是3.0,可以选更高的版本比如3.1或者4.0,当然就需要更高的Tomcat版本来支持(例如4.0只支持Tomcat 9.x),这里我们选的是4.0。
- 这时候先不要急着点击Apply,下面会出现一个“Further configuration avaliable”的按钮,我们点击他来进行Dynamic Web Module的配置,这样可以节省一些步骤。
- 在弹出的窗口中,其他选项保持不动,然后勾选“Generate web.xml deployment descriptor”,这样Eclipse会自动为我们生成web.xml这个文件,方便我们配置Servlet等Java EE组件,然后确定退出即可。
五、配置build.gradle
- 上一个步骤我们得到了一个基于Gradle的Dynamic Web Module项目,然后我们就开始配置SSM。首先打开build.gradle配置我们需要的包,除了必须的SSM组件之外还包括一些加解密、JSON序列化、文件上传所用的包。这里将不在解释每个包是干什么用的,就先贴出来,这样的配置对于常规的Java Web应用都足够了。
/* * This build file was generated by the Gradle 'init' task. * * This generated file contains a sample Java Library project to get you started. * For more details take a look at the Java Libraries chapter in the Gradle * user guide available at https://docs.gradle.org/4.3/userguide/java_library_plugin.html */// Apply the java-library plugin to add support for Java Libraryapply plugin: 'java-library'// Apply the war plugin to add support for Java Web war packageapply plugin: 'war'// In this section you declare where to find the dependencies of your projectrepositories { // Use jcenter for resolving your dependencies. // You can declare any Maven/Ivy/file repository here. jcenter()}dependencies {// https://mvnrepository.com/artifact/mysql/mysql-connector-javacompile group: 'mysql', name: 'mysql-connector-java', version: '8.0.15'// https://mvnrepository.com/artifact/commons-codec/commons-codeccompile group: 'commons-codec', name: 'commons-codec', version: '1.12'// https://mvnrepository.com/artifact/org.apache.commons/commons-collections4compile group: 'org.apache.commons', name: 'commons-collections4', version: '4.3'// https://mvnrepository.com/artifact/commons-logging/commons-loggingcompile group: 'commons-logging', name: 'commons-logging', version: '1.2'// https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-corecompile group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.11.2'// https://mvnrepository.com/artifact/org.springframework/spring-corecompile group: 'org.springframework', name: 'spring-core', version: '5.1.6.RELEASE'// https://mvnrepository.com/artifact/org.springframework/spring-beanscompile group: 'org.springframework', name: 'spring-beans', version: '5.1.6.RELEASE'// https://mvnrepository.com/artifact/org.springframework/spring-webcompile group: 'org.springframework', name: 'spring-web', version: '5.1.6.RELEASE'// https://mvnrepository.com/artifact/org.springframework/spring-webmvccompile group: 'org.springframework', name: 'spring-webmvc', version: '5.1.6.RELEASE'// https://mvnrepository.com/artifact/org.springframework/spring-jdbccompile group: 'org.springframework', name: 'spring-jdbc', version: '5.1.6.RELEASE'// https://mvnrepository.com/artifact/org.springframework/spring-aopcompile group: 'org.springframework', name: 'spring-aop', version: '5.1.6.RELEASE'// https://mvnrepository.com/artifact/org.springframework/spring-aspectscompile group: 'org.springframework', name: 'spring-aspects', version: '5.1.6.RELEASE'// https://mvnrepository.com/artifact/org.springframework/spring-context-supportcompile group: 'org.springframework', name: 'spring-context-support', version: '5.1.6.RELEASE'// https://mvnrepository.com/artifact/org.springframework/spring-instrumentcompile group: 'org.springframework', name: 'spring-instrument', version: '5.1.6.RELEASE'// https://mvnrepository.com/artifact/org.springframework/spring-instrument-tomcatcompile group: 'org.springframework', name: 'spring-instrument-tomcat', version: '4.3.22.RELEASE'// https://mvnrepository.com/artifact/org.springframework/spring-jmscompile group: 'org.springframework', name: 'spring-jms', version: '5.1.6.RELEASE'// https://mvnrepository.com/artifact/org.springframework/spring-messagingcompile group: 'org.springframework', name: 'spring-messaging', version: '5.1.6.RELEASE'// https://mvnrepository.com/artifact/org.springframework/spring-ormcompile group: 'org.springframework', name: 'spring-orm', version: '5.1.6.RELEASE'// https://mvnrepository.com/artifact/org.springframework/spring-oxmcompile group: 'org.springframework', name: 'spring-oxm', version: '5.1.6.RELEASE'// https://mvnrepository.com/artifact/org.springframework/spring-testtestCompile group: 'org.springframework', name: 'spring-test', version: '5.1.6.RELEASE'// https://mvnrepository.com/artifact/org.springframework/spring-txcompile group: 'org.springframework', name: 'spring-tx', version: '5.1.6.RELEASE'// https://mvnrepository.com/artifact/org.springframework/spring-webmvccompile group: 'org.springframework', name: 'spring-webmvc', version: '5.1.6.RELEASE'// https://mvnrepository.com/artifact/org.springframework/spring-websocketcompile group: 'org.springframework', name: 'spring-websocket', version: '5.1.6.RELEASE'// https://mvnrepository.com/artifact/org.springframework.security/spring-security-corecompile group: 'org.springframework.security', name: 'spring-security-core', version: '5.1.5.RELEASE'// https://mvnrepository.com/artifact/org.springframework.security/spring-security-webcompile group: 'org.springframework.security', name: 'spring-security-web', version: '5.1.5.RELEASE'// https://mvnrepository.com/artifact/org.springframework.security/spring-security-configcompile group: 'org.springframework.security', name: 'spring-security-config', version: '5.1.5.RELEASE'// https://mvnrepository.com/artifact/org.apache.commons/commons-dbcp2compile group: 'org.apache.commons', name: 'commons-dbcp2', version: '2.6.0'// https://mvnrepository.com/artifact/commons-fileupload/commons-fileuploadcompile group: 'commons-fileupload', name: 'commons-fileupload', version: '1.4'// https://mvnrepository.com/artifact/commons-beanutils/commons-beanutilscompile group: 'commons-beanutils', name: 'commons-beanutils', version: '1.9.3'// https://mvnrepository.com/artifact/commons-codec/commons-codeccompile group: 'commons-codec', name: 'commons-codec', version: '1.12'// https://mvnrepository.com/artifact/org.apache.commons/commons-collections4compile group: 'org.apache.commons', name: 'commons-collections4', version: '4.3'// https://mvnrepository.com/artifact/org.apache.commons/commons-lang3compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.8.1'// https://mvnrepository.com/artifact/org.mybatis/mybatis-springcompile group: 'org.mybatis', name: 'mybatis-spring', version: '2.0.1'// https://mvnrepository.com/artifact/org.mybatis/mybatiscompile group: 'org.mybatis', name: 'mybatis', version: '3.5.1'// https://mvnrepository.com/artifact/javax.servlet/javax.servlet-apicompile group: 'javax.servlet', name: 'javax.servlet-api', version: '4.0.1'// https://mvnrepository.com/artifact/org.json/jsoncompile group: 'org.json', name: 'json', version: '20180813'// https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databindcompile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.9.8'// https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-corecompile group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.9.8'// https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15oncompile group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: '1.61'}
- 在保存build.gradle之后,右击项目,在Gradle菜单中选择Refresh Gradle Project,就可以下载依赖了,该过程需要网络连接。
六、配置web.xml
- 在web.xml里,我们要为Spring MVC配置Servlet,Spring MVC是单Servlet的结构,所以我们配置如下,同样地不过多解释每个配置的详细含义。
<?xml version="1.0" encoding="UTF-8"?><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>SecIoT</display-name><!-- 欢迎文件,设置在直接访问路径的时候默认寻找的文件名称 --><welcome-file-list> <welcome-file>index.html</welcome-file></welcome-file-list><!-- Spring的字符编码过滤器 --><filter> <filter-name>Character Encoding</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><listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener><listener> <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class></listener><!-- 配置Spring配置文件的位置 --><context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring/*.xml</param-value></context-param><!-- 配置Spring MVC的DispatcherServlet以及其配置文件的位置 --><servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring/springmvc-config.xml</param-value> </init-param> <load-on-startup>1</load-on-startup></servlet><!-- 配置Spring MVC的Servlet映射 --><servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>/</url-pattern></servlet-mapping><!-- 配置Spring Security过滤器,如不需要登录和身份认证可以去掉 --><filter> <filter-name>springSecurityFilterChain</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter> <filter-mapping> <filter-name>springSecurityFilterChain</filter-name> <url-pattern>/*</url-pattern> </filter-mapping></web-app>
七、配置Spring MVC配置文件
- 根据web.xml的配置,我们需要在对应路径创建Spring MVC配置文件,首先我们创建/WEB-INF/spring/springmvc-config.xml,先新建文件夹再新建xml文件,该文件的配置内容如下。
<?xml version="1.0" encoding="UTF-8"?><beans default-lazy-init="true" xmlns="http://www.springframework.org/schema/beans" xmlns:p="http://www.springframework.org/schema/p" 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.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <!-- 配置组件扫描的包为项目的全部包 --> <context:component-scan base-package="com.wrlus.seciot"/> <!-- 配置默认Servlet Handler --> <mvc:default-servlet-handler /> <!-- 启用注解扫描功能 --> <mvc:annotation-driven /> <!-- 启用基于commons-fileupload的文件上传功能 --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" p:defaultEncoding="UTF-8" /></beans>
- 这里说下网上一个流传较广的配置,即配置InternelRecourceViewResolver的prefix和suffix,分别为”/WEB-INF/jsp“和“.jsp”,他的功能仅仅是让你在访问某个链接的时候自动跳到对应的JSP文件执行。而这里我们完全不使用JSP,而是采用前后端分离的方式,所以不需要这样的配置。
八、配置Spring配置文件
- 配置好了Spring MVC,我们再进行Spring的配置并整合Mybatis。
<?xml version="1.0" encoding="UTF-8"?><beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xmlns:jdbc="http://www.springframework.org/schema/jdbc" 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/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <!-- 主要数据库的配置 --> <bean id="mainDataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost/seciot?serverTimezone=UTC" /> <property name="username" value="root" /> <property name="password" value="*********" /> </bean> <!-- 认证数据库的配置 --> <bean id="securityDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost/seciot?serverTimezone=UTC" /> <property name="username" value="root" /> <property name="password" value="*********" /> </bean> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="mainDataSource" /> <property name="configLocation" value="/WEB-INF/mybatis/mybatis-config.xml" /> <property name="mapperLocations" value="classpath:com/wrlus/seciot/*/dao/*.xml" /> </bean> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.wrlus.seciot" /> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" /> </bean></beans>
- 这里面有两个数据库的配置,其中第一个是为Mybatis而配置,第二个是为Spring Security而配置,如果没有用到Spring Security则可以删除第二个bean,而且如果使用的是Mybatis的注解方法而不是xml方法,还可以省略mapperLocations。而且同时如果需要在启动和关闭服务器的时候自动做一些操作,也可以再添加其他的Bean。
九、配置Mybatis配置文件
- Mybatis其实没什么需要配置的,但是配置文件好像必须得有:/WEB-INF/mybatis/mybatis-config.xml。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
</configuration>
十、配置Spring Security配置文件(可选)
- Spring Security可以根据自己的需求来配置:/WEB-INF/spring/spring-security.xml
<b:beans xmlns="http://www.springframework.org/schema/security"
xmlns:b="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd">
<!-- 无条件允许访问css路径 -->
<http pattern="/css/**" security="none" />
<!-- 无条件允许访问js路径 -->
<http pattern="/js/**" security="none" />
<!-- 配置访问权限控制 -->
<http auto-config="true" use-expressions="true">
<!-- 所有路径必须经过鉴权才可访问 -->
<intercept-url pattern="/**" access="authenticated" />
<!-- 无条件禁止访问uploads路径 -->
<intercept-url pattern="/attach/uploads/**" access="none" />
<!-- 开启XSS防护 -->
<headers>
<xss-protection />
</headers>
<!-- 配置默认目标,此处还可以配置替换默认的登录页面和自定义注销页面 -->
<form-login default-target-url="/index.html" always-use-default-target="true" />
<!-- 关闭CSRF防护,如需开启需要配置jsp文件 -->
<csrf disabled="true" />
</http>
<!-- 认证管理器 -->
<authentication-manager>
<!-- 配置认证提供者为JDBC,并指明数据源的bean和密码编码方式 -->
<authentication-provider>
<jdbc-user-service data-source-ref="securityDataSource"/>
<password-encoder ref="passwordEncoder" />
</authentication-provider>
</authentication-manager>
<!-- 配置密码为明文存储,请勿用于生产用途,如需哈希加盐存储可更换class,有SHA-1等算法可选 -->
<b:bean id="passwordEncoder"
class="org.springframework.security.crypto.password.NoOpPasswordEncoder"
factory-method="getInstance"/>
</b:beans>
- 另外数据库表需要两个,一个存储用户,一个存储角色,因为Spring Security是基于角色的权限控制。
CREATE TABLE `users` (
`username` varchar(50) NOT NULL,
`password` varchar(256) NOT NULL,
`enabled` tinyint(1) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `authorities` (
`username` varchar(50) NOT NULL,
`authority` varchar(50) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
十一、配置log4j配置文件
- 为了显示日志需要配置log4j2,在源代码目录下创建log4j2.xml,内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/2002/xmlspec/dtd/2.10/xmlspec.dtd">
<Configuration status="WARN">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout
pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
</Console>
</Appenders>
<Loggers>
<!-- 日志级别为Debug,生产系统请更改为Warn以上级别 -->
<Root level="Debug">
<AppenderRef ref="Console" />
</Root>
</Loggers>
</Configuration>
十二、请求映射实例
- 截止上面SSM的配置就完成了,但是需要代码运作还需要编写Java代码,下面给出一个请求映射的实际例子。
package com.wrlus.seciot.dashboard.controller;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.wrlus.seciot.util.Status;
@Controller
@RequestMapping("/dashboard")
public class DashboardController {
@ResponseBody
@RequestMapping("/refresh")
public Map<String, Object> refresh(HttpServletRequest request, HttpServletResponse response) {
Map<String, Object> data=new HashMap<String, Object>();
data.put("Status", Status.SUCCESS);
return data;
}
}
十三、数据库映射实例
- 除此之外再给出一个Mybatis数据库映射的实例,这种映射一般需要四个包,分别为controller,service,dao和model,其中dao这个名字是可以在Spring配置文件中配置的。
package com.wrlus.seciot.platform.model;
public class PlatformRiskDao {
private String id;
private String name;
private String description;
private String level;
private String platform;
private String payload;
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;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getLevel() {
return level;
}
public void setLevel(String level) {
this.level = level;
}
public String getPlatform() {
return platform;
}
public void setPlatform(String platform) {
this.platform = platform;
}
public String getPayload() {
return payload;
}
public void setPayload(String payload) {
this.payload = payload;
}
}
package com.wrlus.seciot.platform.service;
import java.util.List;
import com.wrlus.seciot.platform.model.PlatformRiskDao;
public interface PlatformRiskService {
public List<PlatformRiskDao> getPlatformRiskAll();
public List<PlatformRiskDao> getPlatformRiskById(String id);
public List<PlatformRiskDao> getPlatformRiskByCategory(String category);
}
package com.wrlus.seciot.platform.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.wrlus.seciot.platform.dao.PlatformRiskMapper;
import com.wrlus.seciot.platform.model.PlatformRiskDao;
@Service
public class PlatformRiskServiceImpl implements PlatformRiskService {
@Autowired
private PlatformRiskMapper dao;
@Override
public List<PlatformRiskDao> getPlatformRiskAll() {
return dao.getPlatformRiskAll();
}
@Override
public List<PlatformRiskDao> getPlatformRiskById(String id) {
return dao.getPlatformRiskById(id);
}
@Override
public List<PlatformRiskDao> getPlatformRiskByCategory(String category) {
return dao.getPlatformRiskByCategory(category);
}
}
package com.wrlus.seciot.platform.dao;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Repository;
import com.wrlus.seciot.platform.model.PlatformRiskDao;
@Repository
public interface PlatformRiskMapper {
@Select("select * from platform_risk;")
public List<PlatformRiskDao> getPlatformRiskAll();
@Select("select * from platform_risk where id = #{id};")
public List<PlatformRiskDao> getPlatformRiskById(@Param("id") String id);
@Select("select * from platform_risk where id in (select id from platform_risk_category where category = #{category});")
public List<PlatformRiskDao> getPlatformRiskByCategory(@Param("category") String category);
}
- 其中@Autowired
,@Service注解不能忘记,如果忽略了会找不到这些类,另外在Mapper中,如果需要其他语句也可直接使用@Insert,@Update和@Delete,但要注意返回值为int类型。同时如果传入参数为model对象,则不需要@Param,只需要参数名字和model中名称以及数据库中列名对应即可。如果为基本类型,就需要@Param