目录
1、创建maven项目
2、导入所有相关pom依赖
3、开始整合
项目结构:
①Mybaties+SSM逆向工程
a、导入pom依赖
b、创建配置文件
c、一键生成代码配置
②spring
a、创建配置文件
c、我们配置的为注解开发的相关配置。
③redis
a、创建配置文件
b、创建工具类
c.开启缓存
d、详细缓存使用
④SpringMVC
a、创建配置文件
b、配置web.xml
c、配置Tomcat+部署
4、测试
准备:
component包:
model包:
mapper包:
service包:
impl包:
controller包:
util
运行:
注解总结:
5、结尾:
jdk1.8 tomcat8.0
替换版本请考虑冲突问题
该pom是一次将该环境搭建所需的所有依赖导入!!!
4.0.0
org.zwf
SSM_YL
1.0-SNAPSHOT
war
SSM_YL Maven Webapp
http://www.example.com
UTF-8
1.8
1.8
3.7.0
5.0.2.RELEASE
3.4.5
2.9.0
1.7.1.RELEASE
2.9.3
5.1.44
5.1.2
1.3.1
2.1.1
2.4.3
2.9.1
3.2.0
1.7.13
4.12
4.0.0
1.18.2
org.springframework
spring-context
${spring.version}
org.springframework
spring-orm
${spring.version}
org.springframework
spring-tx
${spring.version}
org.springframework
spring-aspects
${spring.version}
org.springframework
spring-web
${spring.version}
org.springframework
spring-test
${spring.version}
org.springframework
spring-webmvc
${spring.version}
org.mybatis
mybatis
${mybatis.version}
mysql
mysql-connector-java
${mysql.version}
com.github.pagehelper
pagehelper
${pagehelper.version}
org.mybatis
mybatis-spring
${mybatis.spring.version}
org.apache.commons
commons-dbcp2
${commons.dbcp2.version}
org.apache.commons
commons-pool2
${commons.pool2.version}
org.slf4j
slf4j-api
${slf4j.version}
org.slf4j
jcl-over-slf4j
${slf4j.version}
runtime
org.apache.logging.log4j
log4j-api
${log4j2.version}
org.apache.logging.log4j
log4j-core
${log4j2.version}
org.apache.logging.log4j
log4j-slf4j-impl
${log4j2.version}
redis.clients
jedis
${redis.version}
org.springframework.data
spring-data-redis
${redis.spring.version}
com.fasterxml.jackson.core
jackson-databind
${jackson.version}
com.fasterxml.jackson.core
jackson-core
${jackson.version}
com.fasterxml.jackson.core
jackson-annotations
${jackson.version}
org.apache.logging.log4j
log4j-web
${log4j2.version}
jstl
jstl
1.2
taglibs
standard
1.1.2
junit
junit
${junit.version}
test
javax.servlet
javax.servlet-api
${servlet.version}
provided
org.projectlombok
lombok
${lombok.version}
provided
SSM_YL
src/main/java
**/*.xml
src/main/resources
*.properties
*.xml
org.mybatis.generator
mybatis-generator-maven-plugin
1.3.2
mysql
mysql-connector-java
5.1.44
true
SSM逆向工程:dao层一键生成
在第二步已经将所有pom导入了!!所有后面都会省略该步骤!
jdbc.properties
连接数据库相关参数
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/study(对应的库)?useUnicode=true&characterEncoding=UTF-8
jdbc.username=root (数据库账号名)
jdbc.password=root123(数据库账号密码)
mybatis.cfg
mybatis核心配置文件
注意:分页插件要配置在environment标签前面,否则会报错
generatorConfig.xml
逆向生成代码核心配置文件!
注意事项:
①需要修改jdbc驱动jar包位置
②修改model以及Mapper生成位置
③配置指定的表(生成相关到层,一张表对应一个实体类)
注意:配置好之后运行成功后请将配置选项切走,以免粗心导致运行二次造成其他bug...
命令行:mybatis-generator:generate -e
然后在pom文件中右键运行即可
Spring-Mybatis.xml
spring整合mybatis文件
注意事项:
①注册jdbc.properties文件的那行代码被注释了,导致下面需要调用该文件相关参数的代码报红,可忽略。
在整合redis时会提到为什么!
②修改spring注入bean的扫描范围com.zwf
③将所有指定了报名的代码改为自己的包名com.zwf
helperDialect=mysql
true
false
true
spring.xml
spring核心配置文件(总文件)
注意:
多数据源导入配置,因为spring只能识别一个context:property-placeholder标签,在配置redis时也会产生一个,可能会导致识别覆盖之类的问题,因此在spring的总配置文件中进行配置,用逗号隔开!也就是spring-Mybatis.xml和spring-redis.xml文件中该标签被注释的原因!
spring提供注解,可便利开发,提高开发效率,相比SSH项目,我们的dao层,service(biz)层,controller(web)层,不需要再创建相关的spring配置文件来配置相关的Bean再交给spring管理了,写注解就好!
下面是SSH项目配置的案例:每写完一个模块都要配置一个相关文件!繁琐,且易出错!
这里spring可以通过注解对各层进行bean注册然后再加以管理!
分别有哪些注解,在最后测试会写出!
redis.properties
redis也是数据库(非关系数据库),需要相关连接参数
redis.hostName=192.168.102.128 #redis服务器ip
redis.port=6379 #端口号
redis.password=123456 #连接redis密码,在redis.config中设置
redis.timeout=10000
redis.maxIdle=300
redis.maxTotal=1000
redis.maxWaitMillis=1000
redis.minEvictableIdleTimeMillis=300000
redis.numTestsPerEvictionRun=1024
redis.timeBetweenEvictionRunsMillis=30000
redis.testOnBorrow=true
redis.testWhileIdle=true
spring-redis.xml
RedisCache.java
package com.zwf.util;
import org.apache.ibatis.cache.Cache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class RedisCache implements Cache //实现类
{
private static final Logger logger = LoggerFactory.getLogger(RedisCache.class);
private static RedisTemplate redisTemplate;
private final String id;
/**
* The {@code ReadWriteLock}.
*/
private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
@Override
public ReadWriteLock getReadWriteLock()
{
return this.readWriteLock;
}
public static void setRedisTemplate(RedisTemplate redisTemplate) {
RedisCache.redisTemplate = redisTemplate;
}
public RedisCache(final String id) {
if (id == null) {
throw new IllegalArgumentException("Cache instances require an ID");
}
logger.debug("MybatisRedisCache:id=" + id);
this.id = id;
}
@Override
public String getId() {
return this.id;
}
@Override
public void putObject(Object key, Object value) {
try{
logger.info(">>>>>>>>>>>>>>>>>>>>>>>>putObject: key="+key+",value="+value);
if(null!=value) {
redisTemplate.opsForValue().set(key.toString(), value, 60, TimeUnit.SECONDS);
}
}catch (Exception e){
e.printStackTrace();
logger.error("redis保存数据异常!");
}
}
@Override
public Object getObject(Object key) {
try{
logger.info(">>>>>>>>>>>>>>>>>>>>>>>>getObject: key="+key);
if(null!=key) {
return redisTemplate.opsForValue().get(key.toString());
}
}catch (Exception e){
e.printStackTrace();
logger.error("redis获取数据异常!");
}
return null;
}
@Override
public Object removeObject(Object key) {
try{
if(null!=key) {
return redisTemplate.expire(key.toString(), 1, TimeUnit.DAYS);
}
}catch (Exception e){
e.printStackTrace();
logger.error("redis获取数据异常!");
}
return null;
}
@Override
public void clear() {
Long size=redisTemplate.execute(new RedisCallback() {
@Override
public Long doInRedis(RedisConnection redisConnection) throws DataAccessException {
Long size = redisConnection.dbSize();
//连接清除数据
redisConnection.flushDb();
redisConnection.flushAll();
return size;
}
});
logger.info(">>>>>>>>>>>>>>>>>>>>>>>>clear: 清除了" + size + "个对象");
}
@Override
public int getSize() {
Long size = redisTemplate.execute(new RedisCallback() {
@Override
public Long doInRedis(RedisConnection connection)
throws DataAccessException {
return connection.dbSize();
}
});
return size.intValue();
}
}
RedisCacheTransfer.java
package com.zwf.util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
public class RedisCacheTransfer {
@Autowired
public void setRedisTemplate(RedisTemplate redisTemplate) {
RedisCache.setRedisTemplate(redisTemplate);
}
}
顺便创建分页需要的PageBean工具类
PageBean.java(分页)
package com.zwf.util;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
/**
* 分页工具类
*
*/
public class PageBean {
private int page = 1;// 页码
private int rows = 10;// 页大小
private int total = 0;// 总记录数
private boolean pagination = true;// 是否分页
private String URL;//上一次请求的URL
private Map m=new HashMap();//存放上一次请求携带的参数
public String getURL() {
return URL;
}
public void setURL(String uRL) {
URL = uRL;
}
public Map getM() {
return m;
}
public void setM(Map m) {
this.m = m;
}
public PageBean() {
super();
}
public int getPage() {
return page;
}
public void setPage(int page) {
this.page = page;
}
public int getRows() {
return rows;
}
public void setRows(int rows) {
this.rows = rows;
}
public int getTotal() {
return total;
}
public void setTotal(int total) {
this.total = total;
}
public boolean isPagination() {
return pagination;
}
public void setPagination(boolean pagination) {
this.pagination = pagination;
}
public void setPage(String page) {
if(page!=null)this.page = Integer.parseInt(page);
}
public void setRows(String rows) {
if(rows!=null)
this.rows = Integer.parseInt(rows);
}
public void setTotal(String total) {
if(total!=null)
this.total = Integer.parseInt(total);
}
public void setPagination(String pagination) {
if(pagination != null)
this.pagination = Boolean.getBoolean(pagination);
}
/**
* pageBean的初始化
* @param req
*/
public void init(HttpServletRequest req) {
//初始化jsp界面传递过来的当前页
this.setPage(req.getParameter("page"));
//初始化jsp界面传递过来的页大小
this.setRows(req.getParameter("rows"));
//初始化jsp界面传递过来的是否分页参数
this.setPagination(req.getParameter("pagination"));
//初始化上一次请求路径
this.setURL(req.getRequestURL().toString());
//初始化上一次请求参数
this.setM(req.getParameterMap());
}
/**
* 获得起始记录的下标
*
* @return
*/
public int getStartIndex() {
return (this.page - 1) * this.rows;
}
/**
* 返回最大页数
* @return
*/
public int getMaxPage() {
return this.total % this.rows == 0 ? this.total / this.rows : this.total / this.rows+1;
}
/**
* 获得上一页页码 最小页码为1
* @return
*/
public int backPage() {
return this.page - 1 == 0 ? 1 : this.page-1;
}
/**
* 获得下一页页码 最大页码为 this.page
* @return
*/
public int nextPage() {
return this.page + 1 > this.getMaxPage() ? this.getMaxPage() : this.page+1;
}
@Override
public String toString() {
return "PageBean [page=" + page + ", rows=" + rows + ", total=" + total + ", pagination=" + pagination
+ ", URL=" + URL + ", m=" + m + "]";
}
}
该标签添加到对应的Mapper.xml文件中(配置在Mapper标签中的最上一行),添加到BookMapper.xml,那么调用BookMapper.java的查询方法会缓存查出来的数据!
请看相关文章,之后再做补充!
spring-mvc.xml
注意该修改的地方都修改了
Archetype Created Web Application
contextConfigLocation
classpath:spring.xml
org.springframework.web.context.ContextLoaderListener
SpringMVC
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
classpath:spring-mvc.xml
1
true
SpringMVC
/
注意:
一定要将你要运行的项目进行部署,否则运行成功之后(没问题的条件下)浏览器输入路径调用方法根本不会进入到后台调用controller层调用方法(别问我怎么知道的!)!!!
如果没有就点+号添加,请选择后缀有exploded的选项!
到这了就都整合完成了,接下来进行测试!!!
上面有提到过分页插件,在查询方法前后都需要进行处理来组成分页方法,因此写一个切面类,所有需要分页的方法不用再定义前后了。
PagerAspect.java
分页切面类,所有service包下的xxPager方法都将会被切面类进行增强,达到分页效果!
package com.zwf.component;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.zwf.util.PageBean;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* @author zwf
* @site www.zwf.com
* @company
* @create
*/
@Component
@Aspect
public class PagerAspect {
@Around("execution(* *..*Service.*Pager(..))")
public Object invoke(ProceedingJoinPoint args) throws Throwable {
Object[] params = args.getArgs();
PageBean pageBean = null;
for (Object param : params) {
if(param instanceof PageBean){
pageBean = (PageBean)param;
break;
}
}
if(pageBean != null && pageBean.isPagination()) {
PageHelper.startPage(pageBean.getPage(), pageBean.getRows());
}
Object list = args.proceed(params);
if(null != pageBean && pageBean.isPagination()){
PageInfo pageInfo = new PageInfo((List) list);
pageBean.setTotal(pageInfo.getTotal()+"");
}
return list;
}
}
通过逆向工程已经生成Dao层相关代码。
Book.java
package com.zwf.model;
public class Book {
private Integer bid;
private String bname;
private Float price;
public Book(Integer bid, String bname, Float price) {
this.bid = bid;
this.bname = bname;
this.price = price;
}
public Book() {
super();
}
public Integer getBid() {
return bid;
}
public void setBid(Integer bid) {
this.bid = bid;
}
public String getBname() {
return bname;
}
public void setBname(String bname) {
this.bname = bname;
}
public Float getPrice() {
return price;
}
public void setPrice(Float price) {
this.price = price;
}
}
BookMapper.java
package com.zwf.mapper;
import com.zwf.model.Book;
import org.springframework.stereotype.Component;
import java.util.List;
@Repository
public interface BookMapper {
int deleteByPrimaryKey(Integer bid);
int insert(Book record);
int insertSelective(Book record);
Book selectByPrimaryKey(Integer bid);
int updateByPrimaryKeySelective(Book record);
int updateByPrimaryKey(Book record);
/**
* 书籍模糊查询(带分页)
* @param book 根据前端条件创建的书籍类,用来进行模糊查询
* @return 符合条件的书籍集合
*/
List listPager2(Book book);
}
BookMapper.xml
bid, bname, price
delete from t_mvc_book
where bid = #{bid,jdbcType=INTEGER}
insert into t_mvc_book (bid, bname, price
)
values (#{bid,jdbcType=INTEGER}, #{bname,jdbcType=VARCHAR}, #{price,jdbcType=REAL}
)
insert into t_mvc_book
bid,
bname,
price,
#{bid,jdbcType=INTEGER},
#{bname,jdbcType=VARCHAR},
#{price,jdbcType=REAL},
update t_mvc_book
bname = #{bname,jdbcType=VARCHAR},
price = #{price,jdbcType=REAL},
where bid = #{bid,jdbcType=INTEGER}
update t_mvc_book
set bname = #{bname,jdbcType=VARCHAR},
price = #{price,jdbcType=REAL}
where bid = #{bid,jdbcType=INTEGER}
在BookMapper.java 中可以看到@Repository注解,对BookMapper.java进行注册,交给spring管理。其他层也有相关注解。
BookServiceImpl.java (实现类在impl包下)
package com.zwf.service.impl;
import com.zwf.mapper.BookMapper;
import com.zwf.model.Book;
import com.zwf.service.BookService;
import com.zwf.util.PageBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class BookServiceImpl implements BookService {
@Autowired
private BookMapper bookMapper;
@Override
public int deleteByPrimaryKey(Integer bid) {
return bookMapper.deleteByPrimaryKey(bid);
}
@Override
public int insert(Book record) {
return 0;
}
@Override
public int insertSelective(Book record) {
return 0;
}
@Override
public Book selectByPrimaryKey(Integer bid) {
return null;
}
@Override
public int updateByPrimaryKeySelective(Book record) {
return 0;
}
@Override
public int updateByPrimaryKey(Book record) {
return 0;
}
@Override
public List listPager(Book book, PageBean pageBean) {
return bookMapper.listPager2(book);
}
}
BookService.java (接口在service包下)
package com.zwf.service;
import com.zwf.model.Book;
import com.zwf.util.PageBean;
import java.util.List;
public interface BookService {
int deleteByPrimaryKey(Integer bid);
int insert(Book record);
int insertSelective(Book record);
Book selectByPrimaryKey(Integer bid);
int updateByPrimaryKeySelective(Book record);
int updateByPrimaryKey(Book record);
List listPager(Book book, PageBean pageBean);
}
BookController.java
package com.zwf.controller;
import com.zwf.model.Book;
import com.zwf.service.BookService;
import com.zwf.util.PageBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.List;
@Controller
@RequestMapping("book")
public class BookController {
@Autowired
private BookService bookService;
@ResponseBody
@RequestMapping("getBookList")
public List getBookList(){
List books = bookService.listPager(new Book(1, "%圣墟%", 2f), new PageBean());
books.forEach(System.out::println);
return books;
}
}
在上面提到的PageBean和缓存所需要的工具类都在工具包下
运行成功如下图所示:
调用listPager2方法:
mapper(dao)层:@Repository
service(biz)层:@Service
controller(web)层:
@Autowired:注册对象(让service中的mapper接口有初始值),由spring来完成!
①@Controller
②springMVC相关:@RequestMapping("xxx") :在类上可区分某某模块,在方法上,表示方法调用。
例:调用book模块中的listPager2方法,如上图所示!
该篇主要是快速搭建SSM+redis环境,具体一些注解,配置文件等的学习请看相关文章!