SSM整合,快速新建javaWeb项目
整合前需要了解:
spring和springmvc包扫描的注意事项
Spring applicationContext.xml (父容器),SpringMVC springmvc-servlet.xml (子容器)
-
DispatcherServlet 启动的springMVC工厂==负责生产C及springMVC自己的系统组件(Servlet)
-
ContextLoaderListener 启动的spring工厂==负责生产其他所有组件(Listener)
-
springMVC的工厂会被设置为spring工厂的子工厂,可以随意获取spring工厂中的组件
-
两个工厂不能有彼此侵入,即,生产的组件不能有重合。
- mvc.xml中只扫描controller包, 其他不管, 其他包交给spring框架
<!-- 告知SpringMVC 哪些包中 存在 被注解的类 use-default-filters=true 凡是被 @Controller @Service @Repository注解的类,都会被扫描 use-default-filters=false 默认不扫描包内的任何类, 只扫描include-filter中指定的类 只扫描被@Controller注解的类 --> <context:component-scan base-package="com.xx" use-default-filters="false"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan>
-
<!-- 告知Spring 唯独不扫描@Controller注解的类 --> <context:component-scan base-package="com.xx" use-default-filters="true"> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan>
正式开始整合
一、准备测试用的数据库
CREATE TABLE `t_user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(255) DEFAULT NULL, `password` varchar(255) DEFAULT NULL, `gender` tinyint(255) DEFAULT NULL, `regist_time` datetime DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of t_user -- ---------------------------- INSERT INTO `t_user` VALUES ('1', '青龙', '123', '1', '2021-03-07 09:08:39'); INSERT INTO `t_user` VALUES ('2', '白虎', '123', '0', '2021-03-01 09:08:56'); INSERT INTO `t_user` VALUES ('3', '朱雀', '123', '0', '2021-03-01 09:09:10'); INSERT INTO `t_user` VALUES ('4', '玄武', '123', '1', '2021-03-07 09:09:24');
二、创建项目, 项目名为ssmDemo, 选择骨架为 maven-archetype-webapp, 创建后pom文件内容如下:
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<!-- springMVC -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.6.RELEASE</version>
</dependency>
<dependency>
<!-- jstl 支持 -->
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<!-- servlet编译环境 -->
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<!-- jsp编译环境 -->
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
<!-- FastJson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.54</version>
</dependency>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.1.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.1.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.1.6.RELEASE</version>
</dependency>
<!-- Spring整合mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.1</version>
</dependency>
<!-- MyBatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<!-- mysql驱动 依赖 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.25</version>
<scope>runtime</scope>
</dependency>
<!-- 连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.12</version>
</dependency>
<!-- Junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<!-- 分页插件 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.10</version>
</dependency>
</dependencies>
三、检查或创建项目结构
-
-
java目录下创建包com.xx.controller 放控制层代码
-
java目录下创建包com.xx.dao 放持久层代码
-
java目录下创建包com.xx.service放业务层代码
-
java目录下创建包com.xx.pojo放实体类代码
-
java目录下创建包com.xx.utils 放工具类代码
-
java目录下创建包com.xx.config放初始化类代码
-
java目录下创建包com.xx.interceptor放拦截器代码
-
-
main目录下创建resources目录放配置文件
-
resources目录下创建com/xx/dao用于放置mybatis中对应的dao映射文件
-
-
webapp/WEB-INF/目录下创建 jsp目录放页面
-
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_4_0.xsd" version="4.0"> <!-- SpringMVC前端(核心)控制器 1. 前端,接收所有请求 2. 启动SpringMVC工厂 mvc.xml 3. springMVC流程调度 --> <servlet> <servlet-name>mvc_shine</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:mvc.xml</param-value> </init-param> <!-- 懒 饿 可选--> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>mvc_shine</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <!-- 此过滤器会进行:request.setCharactorEncoding("utf-8"); --> <filter> <filter-name>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> <filter-mapping> <filter-name>encoding</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 启动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> </web-app>
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" 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.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- DataSource --> <context:property-placeholder location="classpath:jdbc.properties"/> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> <!--基本配置--> <property name="driverClassName" value="${jdbc.driverClass}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> <!-- 配置初始化大小、最小、最大 --> <property name="initialSize" value="${jdbc.init}"/> <property name="minIdle" value="${jdbc.minIdle}"/> <property name="maxActive" value="${jdbc.maxActive}"/> <!-- 配置获取连接等待超时的时间 ms--> <property name="maxWait" value="60000"/> <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 --> <property name="timeBetweenEvictionRunsMillis" value="60000"/> <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 --> <property name="minEvictableIdleTimeMillis" value="300000"/> </bean> <!-- SqlSessionFactory --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <!-- 注入连接池 --> <property name="dataSource" ref="dataSource"></property> <!-- 注入dao-mapper文件信息 ,如果映射文件和dao接口 同包且同名,则此配置可省略--> <property name="mapperLocations"> <list> <value>classpath:com/xx/dao/*.xml</value> </list> </property> <!-- 为 dao-mapper文件中的实体 定义缺省包路径 如:<select id="queryAll" resultType="User"> 中 User类可以不定义包 --> <property name="typeAliasesPackage" value="com.xx.pojo"></property> <property name="plugins"> <array> <bean class="com.github.pagehelper.PageInterceptor"> <property name="properties"> <props> <!-- 页号 调整到合理的值 0 max --> <prop key="reasonable">true</prop> </props> </property> </bean> </array> </property> </bean> <!-- DAO MapperScannerConfigurer --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <!-- dao接口所在的包 如果有多个包,可以用逗号或分号分隔 <property name="basePackage" value="com.a.dao,com.b.dao"></property> --> <property name="basePackage" value="com.xx.dao"></property> <!-- 如果工厂中只有一个SqlSessionFactory的bean,此配置可省略 --> <!--<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>--> </bean> <!-- 扫描包,并排除Controller --> <context:component-scan base-package="com.xx" use-default-filters="true"> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan> <!-- 引入一个事务管理器,其中依赖DataSource,借以获得连接,进而控制事务逻辑 --> <bean id="tx" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- @Transactional --> <tx:annotation-driven transaction-manager="tx"/> </beans>
mvc.xml配置
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" 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/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <!-- 注解扫描 --> <context:component-scan base-package="com.xx" use-default-filters="false"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"></context:include-filter> </context:component-scan> <!-- 注解驱动 --> <mvc:annotation-driven> <!-- 安装FastJson,转换器 --> <mvc:message-converters> <bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter"> <!-- 声明转换类型:json --> <property name="supportedMediaTypes"> <list> <value>application/json</value> </list> </property> </bean> </mvc:message-converters> </mvc:annotation-driven> <!-- 视图解析器 作用:1.捕获后端控制器的返回值="hello" 2.解析: 在返回值的前后 拼接 ==> "/hello.jsp" --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!-- 前缀 --> <property name="prefix" value="/WEB-INF/jsp/"></property> <!-- 后缀 --> <property name="suffix" value=".jsp"></property> </bean> <!-- 额外的增加一个handler,且其requestMapping: "/**" 可以匹配所有请求,但是优先级最低 所以如果其他所有的handler都匹配不上,请求会转向 "/**" ,恰好,这个handler就是处理静态资源的 处理方式:将请求转会到tomcat中名为default的Servlet RequestMapping /* /a /b /c /dxxxx /a/b /** --> <mvc:default-servlet-handler/> </beans>
jdbc.properties配置
jdbc.driverClass=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/mydb2?useUnicode=true&characterEncoding=UTF-8 jdbc.username=root jdbc.password=123456 jdbc.init=1 jdbc.minIdle=1 jdbc.maxActive=3
---测试用的页面---
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> <html lang="en"> <head> <title>Hello, world!</title> </head> <body> <table width="500px" align="center" border="1px"> <thead> <tr> <th>id</th> <th>username</th> <th>password</th> <th>gender</th> <th>registTime</th> </tr> </thead> <tbody> <c:forEach items="${requestScope.users}" var="user"> <tr> <td>${user.id}</td> <td>${user.username}</td> <td>${user.password}</td> <td>${user.gender}</td> <td> <fmt:formatDate value="${user.registTime}" pattern="yyyy-MM-dd"/> </td> </tr> </c:forEach> </tbody> </table> </body> </html>
/WEB-INF/jsp/ 目录下页面userPro.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> <!doctype html> <html lang="en"> <head> <title>Hello, world!</title> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <!-- Bootstrap CSS --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.4.1/dist/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous"> <!-- jQuery first, then Popper.js, then Bootstrap JS --> <script src="https://cdn.jsdelivr.net/npm/jquery@3.4.1/dist/jquery.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.4.1/dist/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1ixxktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script> </head> <body> <table class="table table-bordered table-striped table-dark"> <thead> <tr> <th>id</th> <th>username</th> <th>password</th> <th>gender</th> <th>registTime</th> </tr> </thead> <tbody> <c:forEach items="${requestScope.data.list}" var="user"> <tr> <td>${user.id}</td> <td>${user.username}</td> <td>${user.password}</td> <td>${user.gender}</td> <td> <fmt:formatDate value="${user.registTime}" pattern="yyyy-MM-dd"/> </td> </tr> </c:forEach> </tbody> </table> <nav aria-label="..."> <ul class="pagination justify-content-center" > <c:if test="${requestScope.data.hasPreviousPage}"> <li class="page-item"> <a class="page-link" href="${pageContext.request.contextPath}/users?pageNum=${requestScope.data.prePage}" tabindex="-1" aria-disabled="true">Previous</a> </li> </c:if> <c:if test="${!requestScope.data.hasPreviousPage}"> <li class="page-item disabled"> <a class="page-link" href="${pageContext.request.contextPath}/users?pageNum=${requestScope.data.prePage}" tabindex="-1" aria-disabled="true">Previous</a> </li> </c:if> <%--<li class="page-item"><a class="page-link" href="#">1</a></li> <li class="page-item active" aria-current="page"> <a class="page-link" href="#">2 <span class="sr-only">(current)</span></a> </li> <li class="page-item"><a class="page-link" href="#">3</a></li>--%> <c:forEach begin="1" end="${requestScope.data.pages}" var="pageNum"> <c:if test="${pageNum==requestScope.data.pageNum}"> <li class="page-item active"><a class="page-link" href="${pageContext.request.contextPath}/users?pageNum=${pageNum}">${pageNum}</a></li> </c:if> <c:if test="${pageNum!=requestScope.data.pageNum}"> <li class="page-item"><a class="page-link" href="${pageContext.request.contextPath}/users?pageNum=${pageNum}">${pageNum}</a></li> </c:if> </c:forEach> <c:if test="${requestScope.data.hasNextPage}"> <li class="page-item"> <a class="page-link" href="${pageContext.request.contextPath}/users?pageNum=${requestScope.data.nextPage}">Next</a> </li> </c:if> <c:if test="${!requestScope.data.hasNextPage}"> <li class="page-item disabled"> <a class="page-link" href="${pageContext.request.contextPath}/users?pageNum=${requestScope.data.nextPage}">Next</a> </li> </c:if> </ul> </nav> </body> </html>
准备实体类pojo
package com.xx.pojo; import java.util.Date; public class User { private Integer id; private String username; private String password; private Boolean gender; private Date registTime; public User(){} public User(Integer id, String username, String password, Boolean gender, Date registTime) { this.id = id; this.username = username; this.password = password; this.gender = gender; this.registTime = registTime; } @Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\'' + ", password='" + password + '\'' + ", gender=" + gender + ", registTime=" + registTime + '}'; } // ....... get 和 set 方法...... }
package com.xx.pojo; public class Page { private Integer pageNum; private Integer pageSize=3; public Page(){} public Page(Integer pageNum, Integer pageSize) { this.pageNum = pageNum; this.pageSize = pageSize; } @Override public String toString() { return "Page{" + "pageNum=" + pageNum + ", pageSize=" + pageSize + '}'; } // ....... get 和 set 方法...... }
dao接口
package com.xx.dao; import com.xx.pojo.User; import java.util.List; public interface UserDao { List<User> queryUsers(); }
dao映射文件
dao映射文件放在resources/com/xx/dao目录下必须叫做 UserDao.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="com.xx.dao.UserDao">
<select id="queryUsers" resultType="User">
select id,username,password,gender,regist_time registTime
from t_user
</select>
</mapper>
service接口
public interface UserService { PageInfo<User> queryUsers(Page page); }
service实现类
@Service // userServiceImpl public class UserServiceImpl implements UserService { @Autowired private UserDao userDAO; @Override @Transactional(propagation = Propagation.SUPPORTS) public PageInfo<User> queryUsers(Page page) { PageHelper.startPage(page.getPageNum(),page.getPageSize()); List<User> users = userDAO.queryUsers(); return new PageInfo<User>(users); } }
controller类
@Controller public class UserController { @Autowired @Qualifier("userServiceImpl") private UserService userService; @GetMapping("/users") public String queryUsers(Model model, Page page){ System.out.println("queryUsers"); PageInfo<User> pageInfo = userService.queryUsers(page); model.addAttribute("data",pageInfo); return "userPro"; } @RequestMapping("/users/{id}") public String queryOne(@PathVariable Integer id){ System.out.println("query user id:"+id); return "index"; } @PostMapping(value = "/users") public String updateUser(User user){ System.out.println("update User:"+user); return "index"; } }
测试整合结果
启动tomcat, 访问地址如下:
http://localhost:8081/users?pageNum=1


浙公网安备 33010602011771号