准备数据库 我这里就用一个表来做查询跟新增操作就可以了。
CREATE TABLE `account` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(32) NOT NULL,
`money` decimal(10,2) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
创建一个maven工程,在模版(专业叫法骨架)中选择maven-webapp模版(骨架),并设置一个属性archetypeCatalog值为internal (设置这个是为了加快创建速度,如果不加整个属性创建非常慢!)
![](https://img.haomeiwen.com/i3078076/fdffc6bc81c98666.jpg)
![](https://img.haomeiwen.com/i3078076/4190709e9493f1aa.jpg)
在pom.xml导入坐标(这里有一些坑,千万不要把groupId搞出来,不然找个半天的原因,还是要在mvnrepository.com里面找这些坐标,不要随便复制别人的坐标,很有可能那个娃没写全。mysql-connector版本不要选高,选高了就会说com.mysql.jdbc.Driver这个已经被遗弃了,要用另一个,万一出现莫名其妙的错误。链接池的选择可以用c3p0或者druid)
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.8</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.37</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.4</version>
</dependency>
这么多jar包如何记住呢? springmvc.jar 这个jar包就已经包含了很多了,数据库的驱动包 ,连接池的包,事务的包,测试的包,mybatis的包,以及mybatis与spring结合的包 ,还有一个jstl语法的包,基本上就是这几个,其他哪几个暂时还用不到,可以不用引入。
编写实体类
这里为啥要实现Serializable接口?不实现Serializable 接口也不会错。
- 首先第一个问题,实现序列化的两个原因:
将对象的状态保存在存储媒体中以便可以在以后重新创建出完全相同的副本;
按值将对象从一个应用程序域发送至另一个应用程序域。实现 serializabel接口 的作用是就是可以把对象存到字节流,然后可以恢复,所以你想如果你的对象没实现序列化怎么才能进行持久化和网络传输呢,要持久化和网络传输就得转为字节流,所以在分布式应用中及设计数据持久化的场景中,你就得实现序列化。
- 第二个问题,是不是每个实体bean都要实现序列化:
答案其实还要回归到第一个问题,那就是你的 bean 是否需要持久化存储媒体中以及是否需要传输给另一个应用,没有的话就不需要,例如我们利用 fastjson 将实体类转化成 json 字符串时,并不涉及到转化为字节流,所以其实跟序列化没有关系。
- 第三个问题,有的时候并没有实现序列化,依然可以持久化到数据库:
这个其实我们可以看看实体类中常用的数据类型,例如 Date、String 等等,它们已经实现了序列化,而一些基本类型,数据库里面有与之对应的数据结构,从我们的类声明来看,我们没有实现 serializabel接口 ,其实是在声明的各个不同变量的时候,由具体的数据类型帮助我们实现了序列化操作。
另外需要注意的是,在 NoSql数据库 中,并没有与我们 java基本类型 对应的数据结构,所以在往 nosql数据库 中存储时,我们就必须将对象进行序列化,同时在网络传输中我们要注意到两个应用中 javabean 的 serialVersionUID 要保持一致,不然就不能正常的进行反序列化。
public class Account implements Serializable {
private int id;
private String name;
private Float money;
@Override
public String toString() {
return "Account{" +
"id=" + id +
", name='" + name + '\'' +
", money=" + money +
'}';
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Float getMoney() {
return money;
}
public void setMoney(Float money) {
this.money = money;
}
}
编写持久层接口 (有些持久层写的是AccountDao 每个人的习惯不一样,个人觉得叫mapper比较直观,很多函数也用的mapper命名)
public interface AccountMapper {
void save(Account account);
List<Account> findAll();
}
编写业务层接口
这里为什么要先搞个接口在弄一个实现,为什么不直接弄一个实现类多方便快捷?
这里就涉及到面向接口编程的好处:
- 1 降低程序的耦合性。其能够最大限度的解耦,所谓解耦既是解耦合的意思,它和耦合相对。耦合就是联系
,耦合越强,联系越紧密。在程序中紧密的联系并不是一件好的事情,因为两种事物之间联系越紧密,你更换
其中之一的难度就越大,扩展功能和debug的难度也就越大。 - 2 易于程序的扩展;
- 3 有利于程序的维护;
public interface AccountService {
void saveAccount(Account account);
List<Account> findAllAccount();
}
编写业务层实现
@Service("accountService")
public class AccountServiceImpl implements AccountService {
@Autowired
private AccountMapper accountMapper;
@Override
public void saveAccount(Account account) {
accountMapper.save(account);
}
@Override
public List<Account> findAllAccount() {
return accountMapper.findAll();
}
}
配置spring 用容器管理beans (application.xml)
这里要注意一个坑 我们这里是从其他配置文件取值过来的,如果直接写值的话,jdbcUrl的值中如果有&符号一定要写成
&
这里里面用到了事务,事务这一块比较重要我得写一篇记录一下,免得忘记!
<?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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
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/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 配置 spring 创建容器时要扫描的包 除了注解为@controller不需要扫描 -->
<context:component-scan base-package="com.haoisou">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!-- 载入jdbc的配置文件 -->
<context:property-placeholder location="classpath:jdbcConfig.properties"></context:property-placeholder>
<!-- 这个是mybatis-spring jar包提供的创建sqlsession的工厂类,就是为了整合spring与mybatis -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 注入databaseSource信息以及把mybatis.xml的主配置信息载入进来 -->
<property name="dataSource" ref="dataSource"></property>
<property name="configLocation" value="classpath:mybatis.xml"></property>
</bean>
<!-- 用c3p0连接池来创建datasource数据源 -->
<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>
<!-- 配置扫描mapper -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.haoisou.mapper"></property>
</bean>
<!-- 配置事务 增删改都需要用到事务 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 配置事务通知 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*" propagation="REQUIRED" read-only="false"/>
<tx:method name="find*" propagation="SUPPORTS" read-only="true"/>
</tx:attributes>
</tx:advice>
<!-- 配置 aop -->
<aop:config>
<!-- 配置切入点表达式 -->
<aop:pointcut id="pt" expression="execution(* com.haoisou.service.impl.*.*(..))"/>
<!-- 建立通知和切入点表达式的关系 -->
<aop:advisor advice-ref="txAdvice" pointcut-ref="pt"></aop:advisor>
</aop:config>
</beans>
从上面的配置文件中可以看出还需要三个配置信息一个是jdbc.properties 一个是mybatis.xml的主配置信息 还有一个是mapper的配置信息
编写jdbc.properties jdbc.url最完整的版本 jdbc:mysql://localhost:3306/ssm?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&zeroDateTimeBehavior=convertToNull&useAffectedRows=true
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssm
jdbc.username=root
jdbc.password=root
编写mybatis.xml的主配置信息 (由于mybatis的主要配置都在application.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>
接下来就是编写mapper.xml的配置信息 (注意一定要创建跟AccountMapper同名同路径 那这个mapper的配置路径就是resources/com/haoisou/mapper/AccountMapper.xml)
坑点:这里注意路径,千万不要用idea这么创建文件夹
![](https://img.haomeiwen.com/i3078076/7fbd3e06a4a244bf.jpg)
这么弄其实就是一个文件夹,不是三层的文件夹。所以得一个个的创建出来才行!
<?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.haoisou.mapper.AccountMapper">
<select id="findAll" resultType="com.haoisou.domain.Account">
select * from account
</select>
<insert id="save" parameterType="com.haoisou.domain.Account">
insert into account (name,money) values (#{name},#{money})
</insert>
</mapper>
以上就是spring和mybatis的结合,接下来就是spring与springMvc的结合
在web.xml中配置一下(特别注意web-app标签的一大坨属性记得要写,初始化的是是木有的)
<!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 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<display-name>ssm_web</display-name>
<!-- 配置 spring mvc 的核心控制器 -->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 配置初始化参数,用于读取 springmvc 的配置文件 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<!-- 配置 servlet 的对象的创建时间点:应用加载时创建。取值只能是非 0 正整数,表示启动顺序 -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- 配置 springMVC 编码过滤器 -->
<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>
<!-- 配置 spring 提供的监听器,用于启动服务时加载容器 。该间监听器只能加载 WEB-INF 目录中名称为 application.xml 的配置文件 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 所以我们需要手动指定 spring 配置文件位置 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:application.xml</param-value>
</context-param>
</web-app>
接下来编写springmvc.xml (写expression属性值的时候居然直接写注解名称没有提示!艹...)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
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/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 配置创建 spring 容器要扫描的包 -->
<context:component-scan base-package="com.haoisou">
<!-- 制定扫包规则 ,只扫描使用@Controller 注解的 JAVA 类 -->
<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/pages/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<!-- 开启注解扫描 -->
<mvc:annotation-driven></mvc:annotation-driven>
</beans>
接下来编写controller
@Controller
@RequestMapping("/account")
public class AccountController {
@Autowired
private AccountService accountService;
@RequestMapping("/getAccountList")
public String getAccountList(Model model){
System.out.println("index controller hello method");
List<Account> accounts = accountService.findAllAccount();
model.addAttribute("accounts",accounts);
for (Account account : accounts) {
System.out.println(account);
}
return "success";
}
@RequestMapping("saveAccount")
public String saveAccount(Account account){
accountService.saveAccount(account);
return "success";
}
}
还有两个jsp文件 一个success.jsp 一个index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="UTF-8" %>
<html>
<body>
<h2>Hello World!</h2>
<form method="post" action="account/saveAccount">
姓名:<input type="text" name="name"><br/>
金额:<input type="text" name="money"><br/>
<input type="submit" value="提交">
</form>
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="UTF-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>list account page</h1>
<ul>
<c:forEach items="${accounts}" var="item" varStatus="vs">
<li>
${vs.count} : ${item.name} -- ${item.money}
</li>
</c:forEach>
</ul>
</body>
</html>
以上就大功告成!
配置tomcat 启动tomcat 这里就不说了
这个整合配置文件真的是多得很,如何才能记住这一系列的配置信息呢? 我们可以通过联想方法。我们用idea编辑器创建一个从maven模块库中的webapp工程之后,就有一个默认的web.xml配置文件。那一个web工程本来就分三层(表现层springmvc来搞,业务层spring来搞,持久层就是mybatis来搞)。
- 表现层springmvc来搞 现在就只有一个web.xml 他就需要配置一个DispacherServlet 没有这个如何获得请求,因此咱就的先把DispacherServlet 配置起来,这个玩意儿得让他有开机启动的意思,还需要把springmvc.xml的配置信息给读进去,然后就配置一个过滤器解决编码问题,再搞一个监听器ContextLoaderListener把spring给搞进来。
- 从上面来看,接下来就是搞springmvc.xml的配置 mvc主要就是controller嘛,所以先扫包 扫那种带有@Controller注解的包。接着controller里面一般都会有视图,所以我们就会联想到配置视图处理器。controller类中有很多方法都有什么@RequestMapping这些注解,所以需要开启注解扫描。
- 接着咱来配置spring的配置信息。spring主要就是管理beans和aop编程的,所以一开始呢咱就先扫包 来这些服务层的类都让spring的IOC来管理。搞完了服务层就只剩持久层,都是服务层调持久层,服务层还得开启事务。mybatis需要结合spring就需要借助一个mybatis-spring的包 把数据库的配置 事务管理 mapper扫描 事务跟切入点关联起来 基本上就把整个ssm整合完毕了。
网友评论