SSM项目整合一:
为什么要整合
企业要求使用框架进行开发, 通过框架让开发过程高效/快速/安全可靠/性能稳定
为什么是这三个框架
Spring: 行业龙头,对于bean的操作
SpringMVC: 和Spring是同一体系,兼容性非常好,作为MVC框架非常好用
MyBatis: 持久化(DB JPA)
它们的分工
SpringMVC (MVC): 解决各个层次之间通信的桥梁
M:Model 模型(数据 封装对象)
V: View 视图(html jsp 模板 ftl excel)
C: Controller 控制器(大脑, 接收用户请求,并分析业务,执行操作)
MyBatis: 持久化
目录
Spring: 必不可少, bean的容器(bean的创建和声明周期的管理)
UserMapper mapper = null; mapper就是bean
有了spring 就没有new 了
整合步骤
- 引入依赖
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!—springMVC核心包-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.20.RELEASE</version>
</dependency>
<!—对servlet的支持-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<!—使用jstl表达式所需的依赖-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!—对jsp的支持-->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
</dependency>
<!--mybatis核心包-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.3.0</version>
</dependency>
<!-- mysql驱动包 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.48</version>
</dependency>
<!-- druid数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.9</version>
</dependency>
<!--mybatis-spring整合包 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.0</version>
</dependency>
<!-- spring-jdbc依赖包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.3.20.RELEASE</version>
</dependency>
<dependency>
<!—jackson包,用于解析mvc传递给前端的json数据 -->
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.5.4</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.5.4</version>
</dependency>
<!-- freemarker 模板引擎工具 jsp-->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.23</version>
</dependency>
<!—spring为freemarker提供的支持-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>4.3.20.RELEASE</version>
</dependency>
</dependencies>
生成后的依赖项 :
- 更新pom文件
在build标签中添加热resources声明 , 将java包中的mapper xml文件作为资源被加载
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
- 声明资源文件
要实现的目标 :
-
- 设计SqlMapConfig.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>
<!--设置控制台日志,显示sql语句-->
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<!--设置pojo包中的实体类自动解析别名-->
<typeAliases>
<package name="com.gxa.p2p.pojo"/>
</typeAliases>
</configuration>
-
- 设计applicationContext-aop.xml
<?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:tx="http://www.springframework.org/schema/tx"
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">
<!--配置事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 开启事务控制的注解支持 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
-
- 设计applicationContext-dao.xml
<?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: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/context http://www.springframework.org/schema/context/spring-context.xsd">
<!--加载db.properties配置文件-->
<context:property-placeholder location="classpath:properties/db.properties"/>
<!--配置数据源、数据库连接池-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${druid.driverClassName}"></property>
<property name="url" value="${druid.url}" ></property>
<property name="username" value="${druid.username}"></property>
<property name="password" value="${druid.password}"></property>
</bean>
<!--配置SqlSessionFactory,添加mybatis和spring的整合包之后即可使用-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!--加载mybatis的全局配置文件-->
<property name="configLocation" value="classpath:config/mybatis/SqlMapConfig.xml"/>
</bean>
<!--mapper扫描器-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.gxa.p2p.mapper"/>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
</bean>
</beans>
-
- 设计dispatcher-servlet.xml
<?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:mvc="http://www.springframework.org/schema/mvc"
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/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">
<!--配置自动扫描的包-->
<context:component-scan base-package="com.gxa.p2p"/>
<!--注解驱动:-->
<mvc:annotation-driven />
<!--放行静态资源-->
<mvc:default-servlet-handler/>
<!--配置全局异常处理器:实现了HandlerExceptionResolver接口的就是全局异常处理器-->
<bean class="com.gxa.p2p.exception.CustomExceptionResolver"/>
<!--为了简化视图的访问,在视图解析器中添加访问前缀和后缀-->
<!--
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
-->
<!-- 设置freeMarker的配置文件路径 -->
<bean id="freemarkerConfiguration" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="location" value="classpath:properties/freemaker.properties"/>
</bean>
<!-- 配置freeMarker的模板路径 -->
<bean class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<property name="freemarkerSettings" ref="freemarkerConfiguration"/>
<property name="templateLoaderPath">
<value>/WEB-INF/views/</value>
</property>
</bean>
<!--freemarker视图解析器 -->
<bean id="viewResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
<!-- 是否在model自动把session中的attribute导入进去; -->
<property name="exposeSessionAttributes" value="true" />
<!-- 配置逻辑视图自动添加的后缀名 -->
<property name="suffix" value=".ftl" />
<!-- 配置视图的输出HTML的contentType -->
<property name="contentType" value="text/html;charset=UTF-8" />
</bean>
</beans>
-
- 设计applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="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">
<import resource="classpath:config/spring/applicationContext-dao.xml"></import>
<import resource="classpath:config/springmvc/dispatcher-servlet.xml"></import>
<import resource="classpath:config/spring/applicationContext-aop.xml"></import>
</beans>
-
- 设计db.properties
druid.driverClassName=com.mysql.jdbc.Driver
druid.url=jdbc:mysql://localhost:3306/eloan2?characterEncoding=UTF-8&useSSL=false
druid.username=root
druid.password=root
-
- 设计freemaker.properties
#设置标签类型:square_bracket:[] auto_detect:[]<>
tag_syntax=auto_detect
#模版缓存时间,单位:秒
template_update_delay=0
default_encoding=UTF-8
output_encoding=UTF-8
locale=zh_CN
#设置数字格式 ,防止出现 000.00
number_format=\#
#变量为空时,不会报错
classic_compatible=true
#这个表示每个freemarker的视图页面都会自动引入这个ftl文件。里面定议的就是一些宏,如text文本框,各种form元素
#auto_import="WEB-INF/views/index.ftl" as do
- 搭建java基础脚手架
-
- 设计pojo
package com.gxa.p2p.pojo;
import java.io.Serializable;
// 实体类创建的规范
//1. 实体类命名采用数据表对应的单数形式
// 2. 实体类要实现序列化接口(方便类对象的持久化保存到文件中)
public class User implements Serializable {
//3. 属性和数据表中的字段建立对应关系
// 使用private封装
// 数据类型要使用基本类型的封装类型
// 字段(field)和属性(property)?
private Integer uid;
private String username;
private String pwd;
private Boolean state;
// alt+insert 调出代码工具
public Integer getUid() {
return uid;
}
public void setUid(Integer uid) {
this.uid = uid;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
public Boolean getState() {
return state;
}
public void setState(Boolean state) {
this.state = state;
}
public User(Integer uid) {
this.uid = uid;
}
public User() { // 为反射 newInstance服务的
}
// 用于调试的toString , 企业项目中不要使用
@Override
public String toString() {
return "User{" +
"uid=" + uid +
", username='" + username + '\'' +
", pwd='" + pwd + '\'' +
", state=" + state +
'}';
}
}
-
- 设计UserMapper.java
package com.gxa.p2p.mapper;
import com.gxa.p2p.pojo.User;
import java.util.List;
//和Dao类似, 完成持久化的相关操作: CRUD
public interface UserMapper {
// 声明一个用于查询所有用户,生成一个List的方法
List<User> selectAll();
// 声明一个用id查询User对象的方法
User selectById(Integer id);
/**
* 添加用户的方法
* @param user 要添加的用户对象
* @return 返回影响的行数
*/
Integer insertUser(User user);
/**
* 修改用户信息的方法
* @param user 要修改的目标用户对象
* @return 返回特征修改后的User对象
*/
User updateUser(User user);
/**
* 根据用户uid删除的操作
* @param uid
* @return 影响的行数
*/
Integer deleteUser(Integer uid);
}
-
- 设计UserMapper.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.gxa.p2p.mapper.UserMapper">
<!--结果集的映射关系,建立起实体类和数据表之间的字段对应关系
id: 表示当前的结果集映射的代号
type: 和哪一个实体类对应 , 设定别名之后,就可以简写
com.gxa.p2p.pojo.User -> User
-->
<resultMap id="userMap" type="com.gxa.p2p.pojo.User">
<!--id属性表示数据表中代表增长列(主键) 的字段-->
<id property="uid" column="uid" />
<!--result表示表中除了主键列之外,其他的字段-->
<result property="username" column="username" />
<result property="pwd" column="pwd" />
<result property="state" column="state" />
</resultMap>
<select id="selectAll" resultMap="userMap" >
SELECT uid,username,pwd,state from users
</select>
<select id="selectById" resultMap="userMap" parameterType="Integer" >
select uid,username,pwd,state from users where uid=#{id}
</select>
<insert id="insertUser" parameterType="User" keyColumn="uid" useGeneratedKeys="true">
<!--当操作中要从对象参数中获取特征值,必须通过属性名的方式 #{propName}
如果要给Mapper添加返回值, 它表示该sql影响的行数
keyProperty : 指定实体类中的属性,该属性映射为数据表中的id字段,作为自动增长的获取条件之一
useGeneratedKeys: 使用自动增长策略,传入的字段列表就可以不带id: #{uid} , 其对象在执行完后也能获取id值
insert into Users(username,pwd,state) values(#{username},#{pwd},1) 主动添加id,数据库中会采用该值作为id
#{} : 表示能够预编译成功的数据,varchar就会自己带''
${} : 表示需要注入的字符串值自身, 会导致注入,一般sql不用(模糊查询)
-->
insert into users(username,pwd,state) values(#{username},#{pwd},1)
</insert>
<delete id="deleteUser" parameterType="Integer">
delete from users where uid=#{uid}
</delete>
<update id="updateUser" parameterType="User">
update users set username=#{username},pwd=#{pwd},state=#{state} where uid=#{uid}
</update>
</mapper>
-
- 设计UserService接口
package com.gxa.p2p.service;
import com.gxa.p2p.pojo.User;
import java.util.List;
public interface UserService {
int insertUser(User user);
User selectUserById(Integer uid);
int deleteUser(Integer uid);
void updateUser(User user);
List<User> selectAllUser();
}
-
- 设计UserServiceImpl实现类
package com.gxa.p2p.service.impl;
import com.gxa.p2p.exception.CustomException;
import com.gxa.p2p.mapper.UserMapper;
import com.gxa.p2p.pojo.User;
import com.gxa.p2p.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service("userService")
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper ;
@Override
@Transactional
public List<User> selectAllUser() {
return userMapper.selectAll();
}
@Override
public int insertUser(User user) {
return userMapper.insertUser(user);
}
@Override
public User selectUserById(Integer userId) {
User user = null;
try{
user= userMapper.selectById(userId);
if(user == null)
throw new CustomException("查找的用户不存在");
}catch(CustomException e){
throw new RuntimeException(e);
}
return user;
}
@Override
public int deleteUser(Integer uid) {
return userMapper.deleteUser(uid);
}
@Override
public void updateUser(User user) {
userMapper.updateUser(user);
}
}
-
- 设计UserController
package com.gxa.p2p.controller;
import com.gxa.p2p.pojo.User;
import com.gxa.p2p.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
//和 @Service作用一样, 把bean的创建交给Spring管理
@Controller
public class UserController {
@Autowired
UserService userService;
/*@RequestMapping 表示浏览器请求地址时的映射,访问的位置
* http://localhost:8080/login.do 当请求该地址的时候,springMVC就会去
* controller中找 哪一个方法声明@RequestMapping("/login"),则执行该方法
* 返回字符串, 这个login的返回值就表示要去访问
* */
@RequestMapping("/login")
public String login() {
return "login";
}
@RequestMapping("/userList3")
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("userList",userService.selectAllUser());
modelAndView.setViewName("user/userList");
return modelAndView;
}
@RequestMapping("/userList")
@ResponseBody
/*@ResponseBody 表示响应体,就是给用户的反馈内容,支持json*/
public List<User> list(){
//request.setAttribute("userList",userService.findAllUser());
// return "forward:/message"; // "forward:message" 效果等同
return userService.selectAllUser();
}
}
-
- 设计MD5工具类MD5Creater
package com.gxa.p2p.util;
import java.math.BigInteger;
import java.security.MessageDigest;
public class MD5Creater {
public static String MD5Parse(String str) {
try {
// 生成一个MD5加密计算摘要
MessageDigest md = MessageDigest.getInstance("MD5");
// 计算md5函数
md.update(str.getBytes());
// digest()最后确定返回md5 hash值,返回值为8为字符串。因为md5 hash值是16位的hex值,实际上就是8位的字符
// BigInteger函数则将8位的字符串转换成16位hex值,用字符串来表示;得到字符串形式的hash值
return new BigInteger(1, md.digest()).toString(16);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 对字符串md5加密(大写+数字)
*
* @return MD5加密后的字符串
* @paramstr 传入要加密的字符串
*/
public static String MD5(String s) {
char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
try {
byte[] btInput = s.getBytes();
// 获得MD5摘要算法的 MessageDigest 对象
MessageDigest mdInst = MessageDigest.getInstance("MD5");
// 使用指定的字节更新摘要
mdInst.update(btInput);
// 获得密文
byte[] md = mdInst.digest();
// 把密文转换成十六进制的字符串形式
int j = md.length;
char str[] = new char[j * 2];
int k = 0;
for (int i = 0; i < j; i++) {
byte byte0 = md[i];
str[k++] = hexDigits[byte0 >>> 4 & 0xf];
str[k++] = hexDigits[byte0 & 0xf];
}
return new String(str);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
-
- 设计异常处理类
设计CustomException
package com.gxa.p2p.exception;
public class CustomException extends Exception {
//异常信息
public String message;
public CustomException(String message){
super(message);
this.message = message;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
设计CustomExceptionResolver
package com.gxa.p2p.exception;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class CustomExceptionResolver implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
//自定义异常对象,将异常信息统一交由该对象处理
CustomException customException = null;
if(e instanceof CustomException){
customException = (CustomException)e;
}else{
customException = new CustomException(e.getMessage());
}
//异常信息
String message = customException.getMessage();
ModelAndView modelAndView = new ModelAndView();
//将异常信息绑定到数据中
modelAndView.addObject("message", message);
//指向错误页面
modelAndView.setViewName("error");
return modelAndView;
}
}
- 搭建静态资源脚手架(按下图示例)
- 配置web.xml
内容:
<!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>
<!--配置一个过滤器,将所有的请求的字符编码设置为UTF-8-->
<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>
<!--SpringMVC的核心机制是通过Servlet实现的,在这里配置一下Servlet-->
<!--servlet-name 表示Servlet的名字, 可以自定义,在这里定义为dispatcher,表示分发器-->
<!--对应的Servlet 配置为SpringMVC的核心: DispatcherServlet-->
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--init-param表示初始化参数 , 这里我们就是让tomcat加载了最核心的那个配置文件applicationContext.xml-->
<init-param>
<param-name>ContextConfigLocation</param-name>
<param-value>classpath:config/applicationContext.xml</param-value>
</init-param>
<!--load-on-startup表示启动顺序-->
<load-on-startup>1</load-on-startup>
</servlet>
<!--servlet-mapping表示serlvet的映射地址,它会拦截所有以.do为后缀的请求,接下来就会分配给对应的Controller去执行业务-->
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<servlet-mapping>
<!--除了.do , 我还配置了一个/ , 表示根路径的访问,即localhost:8080/ , 当访问跟的时候对应Controller中的 @RequestMapping("/")-->
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
- 配置tomcat服务器
- 访问流程图解: