🛫更多ssm知识见SSM_面向CRUD编程专栏
🚕本博客总结自黑马程序员的ssm框架视频
🚒博主对于该知识尚在学习阶段
🚄如果发现存在问题请毫不吝啬的指出
🚀🚀扎哇太枣糕的博客主页🚀🚀
如果说,面试就像造航母工作就是拧螺丝的话,那么SSM框架就是一把非常适合新手打基础使用的螺丝刀。 ——鲁迅
在前面的ssm专栏知识的学习中,我们已经大致清楚了ssm框架有三个框架组合而成——spring、springMVC、MyBatis。这三个框架可已经节省了我们很多的开发时间,现在要做的就是将这三个框架整合到一起,让它们能更好的配合为我们节省更多的开发时间。
🔒案例分析
由于本篇博客主要是为了讲解ssm框架的整合知识,所以准备了一个比较简单的案例。项目需要连接数据库实现两个功能:在页面上插入数据、查询数据并在页面上显示。
🔑框架结构
ssm框架在项目src/main/java的目录下一般包含四个package,也就是我们常说的四层,从日常开发的顺序来分依次是**domain层**(也叫entity层)、**mapper层**(也叫dao层)、**service层**、**controller层**。复杂点的也会有五层,多出来一个until层,由于学习时间有限更复杂的情况就不知道了😓![](https://img-blog.csdnimg.cn/bdf115daf215494cbcd465e86cbca41d.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5omO5ZOH5aSq5p6j57OV,size_20,color_FFFFFF,t_70,g_se,x_16) 除了domain层以外,其他三层都有相应的配置文件配合spring框架代码的使用,最后要在web.xml文件中将配置文件加载进去,否则配置文件相当于白配并不会生效。除了上面这种配置文件对应方式,还有一种方式就是将spring-xxx合成一个applicationContext.xml,这样可以使配置文件的数量变得更少些,但是对应关系没有上一种清晰,当然配置文件改变了web.xml文件也会跟着改变。本次案例就采用第二种对应方式进行讲解。
🔓实现
🍖项目的层级结构
如果不会创建一个web项目的话,参考往期博客进行创建【SSM面向CRUD编程专栏 3】关于黑马程序员最全SSM框架教程视频,P37集老师跳过的模块创建以及tomcat下载安装配置和运行等诸多问题
🥩pom.xml
<dependencies>
<!--spring相关-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.7</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<!--servlet和jsp-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
</dependency>
<!--mybatis相关-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
🍕domain层
数据库中account表对应的实体类,首先需要参考下图创建一个数据库表![](https://img-blog.csdnimg.cn/3cc8a8dff9ae4fa39c0ba0a8728934b9.png) domain层下创建一个Account类对应数据库中的各个字段
public class Account { private Integer id; private String name; private Double money; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Double getMoney() { return money; } public void setMoney(Double money) { this.money = money; } }
🍔mapper层
之前学过MyBatis的代理开发模式,使用这种模式进行开发就不再需要实现类了,但是需要满足以下四个条件
- mapper标签的namespace = 接口全限名
- 接口方法 = mapper字标签的id
- 接口方法参数类型 = mapper字标签的parameterType
- 接口方法返回值类型 = mapper字标签的resultType
mapper层创建一个AccountMapper接口,定义插入和查询功能的实现方法
public interface AccountMapper { public void save(Account account); public List<Account> findAll(); }
创建AccountMapper.xml映射文件使用SQL语句对数据库进行操作
<?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.itheima.mapper.AccountMapper"> <insert id="save" parameterType="account"> insert into account values(#{id},#{name},#{money}) </insert> <select id="findAll" resultType="account"> select * from account </select> </mapper>
对数据库进行操作,要连接到数据库,在这里需要将数据库的配置抽取到jdbc.properties中方便日后修改(等于号右边的要配成自己数据库的值),又叫解耦合
jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/test jdbc.username=root jdbc.password=123456
有了数据库配置之后就需要在applicationContest.xml中配置数据源信息 ,当然需要先加载上面的数据库配置了,也就是常说的创建连接池,连接池的好处相信大家都知道了吧
<!--加载propeties文件--> <context:property-placeholder location="classpath:jdbc.properties"/> <!--配置数据源信息--> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="${jdbc.driver}"></property> <property name="jdbcUrl" value="${jdbc.url}"></property> <property name="user" value="${jdbc.username}"></property> <property name="password" value="${jdbc.password}"></property> </bean>
下面的service层需要使用到AccountMapper对象调用其中的方法,所以需要使用spring框架底层直接创建好对象之后service直接注入,这样的话就需要我们在applicationContest.xml中让spring框架知道它需要做这件事了
<!--配置sessionFactory--> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"></property> <!--加载mybatis核心文件--> <property name="configLocation" value="classpath:sqlMapConfig-spring.xml"></property> </bean> <!--扫描mapper所在的包 为mapper创建实现类--> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.itheima.mapper"></property> </bean>
数据库的操作又叫事务,既然有事务就要在applicationContest.xml对它进行声明式事务控制
<!--声明式事务控制--> <!--平台事务管理器--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <!--配置事务增强--> <tx:advice id="txAdvice"> <tx:attributes> <tx:method name="*"/> </tx:attributes> </tx:advice> <!--事务的aop织入--> <aop:config> <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.itheima.service.impl.*.*(..))"></aop:advisor> </aop:config>
🍟service层
service层有一个AccountService接口由于阐述业务需求,也就是需要完成哪些功能,一般来说它和AccountMapper接口一样
public interface AccountService { public void save(Account account); public List<Account> findAll(); }
service层下有个Implpackage,又来放所有的接口实现类,比如说这个案例的AccountServiceImpl类。之前创建好的AccountMapper的对象就可以使用注解直接注入,然后调用它的方法
@Service("accountService") public class AccountServiceImpl implements AccountService { @Autowired private AccountMapper accountMapper; public void save(Account account) { accountMapper.save(account); } public List<Account> findAll() { return accountMapper.findAll(); } }
这里使用了@Service注解,所以需要在applicationContest.xml对注解进行扫描,让框架知道应该创建相应的对象了
<!--组件扫描 扫描service和mapper--> <context:component-scan base-package="com.itheima"> <!--排除controller的扫描--> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"></context:exclude-filter> </context:component-scan>
🌭controller层
controller层是与前端进行交互的层,决定了请求和响应的具体事项,下面先放代码再进行详解
@Controller @RequestMapping("/account") public class AccountController { @Autowired private AccountService accountService; // 保存数据 @RequestMapping(value = "/save", produces = "text/html;charset=UTF-8") @ResponseBody public String save(Account account){ accountService.save(account); return "保存成功"; } //查询数据 @RequestMapping("/findAll") public ModelAndView findAll(){ List<Account> accountList = accountService.findAll(); ModelAndView modelAndView = new ModelAndView(); modelAndView.addObject("accountList",accountList); modelAndView.setViewName("accountList"); return modelAndView; } }
这里使用了@controller注解,所以需要在SpringMVC.xml配置注解驱动并对注解进行扫描,让框架知道应该创建相应的对象了
<!--组件扫描 主要扫描controller--> <context:component-scan base-package="com.itheima.controller"/> <!--配置mvc注解驱动--> <mvc:annotation-driven/>
@RequestMapping注解设置了方法的映射地址,前端访问该映射地址的时候会执行对应的方法,类上注解和方法上注解分别对应着两级不一样的映射路径,也就是说当前端发送/account/save请求时,就会调用save方法。produces属性是设置响应的编码格式以防返回给页面一个字符串的时候出现乱码
@ResponseBody注解标明返回的只是一个字符串,而不是进行页面的跳转,如果是页面跳转的话,需要开放静态资源(jsp页面)访问权限,还可以在SpringMVC.xml中配置视图解析器,给返回值加上前缀和后缀(因为开发时的前端页面都会放在一个统一的package下而且页面的后缀基本上都是jsp,于是就可以减少开发时的代码书写)
<!--开放静态资源访问权限--> <mvc:default-servlet-handler/> <!--内部资源视图解析器--> <bean id="resourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/pages/"></property> <property name="suffix" value=".jsp"></property> </bean>
存数据的jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <h1>添加账户信息表单</h1> <form name="accountForm" action="${pageContext.request.contextPath}/account/save" method="post"> 账户名称:<input type="text" name="name"><br> 账户金额:<input type="text" name="money"><br> <input type="submit" value="保存"><br> </form> </body> </html>
查询数据对应的jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <html> <head> <title>Title</title> </head> <body> <h1>展示账户数据列表</h1> <table border="1"> <tr> <th>账户id</th> <th>账户名称</th> <th>账户金额</th> </tr> <c:forEach items="${accountList}" var="account"> <tr> <td>${account.id}</td> <td>${account.name}</td> <td>${account.money}</td> </tr> </c:forEach> </table> </body> </html>
🍿web.xml文件
加载applicationContext.xml文件
<!--spring 监听器--> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
加载SpringMVC.xml文件,又叫前端控制器
<!--springmvc的前端控制器--> <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-mvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>DispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
配置全局过滤器用于解决POST请求乱码问题
<!--全局过滤器用于解决乱码问题--> <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> </filter> <filter-mapping> <filter-name>CharacterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
至此,ssm的框架整合就告一段落了,每一位大国工匠都是从基础学起,之所以能够异于常人。除了天赋以外就是在夯实基础功之外,加之时间的沉淀和经验的积累。万丈高楼平地起,这就是框架开发的第一站。
上一篇:【SSM面向CRUD编程专栏 8】一篇博客快速上手使用MyBatis进行CRUD
下一篇:未完待续……
版权归原作者 扎哇太枣糕 所有, 如有侵权,请联系我们删除。