SSM整合
Posted xfdhh
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SSM整合相关的知识,希望对你有一定的参考价值。
第一步:准备依赖
1、Spring-core beans expression context aop tx jdbc web webmvc
2、Druid mysql-connector-java mybatis mybatis-spring
3、 Log4j slf4j-api slf4j-log4j12
4、Jstl servlet-api Lombok aspectjweaver
第二步:项目准备
1、数据库准备,准备好测试要用的表及数据
2、架构设计
3、bean中的类(属性与数据库中的表对应)
@Setter@Getter@AllArgsConstructor@NoArgsConstructor@ToString public class User private Integer id; private String username; private String pwd; @DateTimeFormat(pattern = "yyyy-MM-dd") private Date date; public String getDate() SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); return sdf.format(this.date);
条件查询时封装的条件类
@Setter@Getter@ToString public class QueryBean private String username; @DateTimeFormat(pattern = "yyyy-MM-dd") private String date; private Integer currentPage; private Integer pageSize; //修改set方法可以在接收前端参数进行封装时进行判断修改 public void setCurrentPage(Integer currentPage) if(currentPage!=null) this.currentPage=currentPage; else this.currentPage=1; public void setPageSize(Integer pageSize) if(pageSize!=null) this.pageSize=pageSize; else this.pageSize=3; //重写get方法,对多条件的结果进行预判断,可以减少xml中配置的代码 public String getUsername() return StringUtils.isNullOrEmpty(this.username)?null:this.username; public String getDate() return StringUtils.isNullOrEmpty(this.date)?null:this.date; //使用getStart方法可以返回start属性,在定义分页工具查询时使用 public Integer getStart() return (this.currentPage-1)*this.pageSize; /*如果使用date类型的date,可以将get方法返回的结果转换格式返回 public String getDate() SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); return sdf.format(this.date); */
4、mapper接口,以及对应方法的xml文件
public interface UserMapper //增删改查 Integer save(User user); Integer update(User user); Integer delete(Integer id); User findById(Integer id); List<User> findAll(); //条件查询用到的方法 List<User> select(QueryBean queryBean); //登录检查需要用到的方法 String login(String username); //手动实现分页需要用到的方法 Integer selectCount(QueryBean queryBean); List<User> selectAll(QueryBean queryBean);
<?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.test.ssm.mapper.UserMapper"> <insert id="save"> insert into users values(null,#username,#pwd,#date) </insert> <update id="update"> update users set username=#username,pwd=#pwd,date=#date where id=#id </update> <delete id="delete"> delete from users where id=#id </delete> <resultMap id="myResultMap" type="user"> <id property="id" column="id"/> <result column="username" property="username"/> <result column="pwd" property="pwd"/> <result column="date" property="date"/> </resultMap> <select id="findById" resultMap="myResultMap"> select * from users where id=#id </select> <select id="findAll" resultMap="myResultMap"> select * from users </select> <select id="select" resultMap="myResultMap"> select * from users <where> <!--在条件类中将get方法封装后可以简化的代码 <if test="username!=null and username!=‘‘"> and username like concat(‘%‘,#username,‘%‘) </if> <if test="date!=null and date!=‘‘"> and date like concat(‘%‘,#date,‘%‘) </if>--> <if test="username!=null"> and username like concat(‘%‘,#username,‘%‘) </if> <if test="date!=null"> and date like concat(‘%‘,#date,‘%‘) </if> </where> </select> <!--手动实现分页需要用到的查询,查询总条数--> <select id="selectCount" resultType="integer"> select count(*) from users <where> <if test="username!=null"> and username like concat(‘%‘,#username,‘%‘) </if> <if test="date!=null"> and date like concat(‘%‘,#date,‘%‘) </if> </where> </select> <!--手动实现分页需要用到的查询,条件查询--> <select id="selectAll" resultMap="myResultMap"> select * from users <where> <if test="username!=null"> and username like concat(‘%‘,#username,‘%‘) </if> <if test="date!=null"> and date like concat(‘%‘,#date,‘%‘) </if> </where> limit #start,#pageSize </select> <!--登录检测需要用到的查询--> <select id="login" resultType="java.lang.String"> select pwd from users where username=#username </select> </mapper>
5、service接口,以及实现类(使用mapper对象)
传统的方式是
1:获取Factory对象,new SqlSessionFactoryBuilder().build(输入流);
2:获取SqlSession对象,Factory.openSession()
3:获取mapper对象,SqlSession.getMapper()
整合后的方式为
1.配置MapperFactoryBean(一次只能创建一个) mapperScannerConfigurer(批量创建,从配置的包中扫描所有赛接口,并且创建代理对象)
2.两个属性,一个是要创建的接口<property name="mapperInterface" value=""/>,一个是sqlsessionfactory
3.配置sqlsessionfactory,几个主要属性
数据源dataSource
配置别名typeAliasesPackage
关联mapper映射文件mapperLocations
关联mybatis的主配置文件configLocation
<?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" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" 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/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd "> <!--加载数据库的配置文件--> <context:property-placeholder location="classpath:db.properties" system-properties-mode="NEVER"/> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="$jdbc.driverClassName"/> <property name="url" value="$jdbc.url"/> <property name="username" value="$jdbc.username"/> <property name="password" value="$jdbc.password"/> </bean> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <!--数据源--> <property name="dataSource" ref="dataSource"/> <!--配置别名--> <property name="typeAliasesPackage" value="com.test.ssm.bean"/> <!--关联mapper映射文件--> <property name="mapperLocations" value="classpath:com/test/ssm/mapper/*Mapper.xml"/> <!--关联mybatis的主配置文件--> <property name="configLocation" value="classpath:mybatis.xml"/> </bean> <!--<bean id="mapperFactory" class="org.mybatis.spring.mapper.MapperFactoryBean"> <property name="mapperInterface" value="com.test.ssm.mapper.UserMapper"/> <property name="sqlSessionFactory" ref="sqlSessionFactory"/> </bean> <bean id="service" class="com.test.ssm.service.impl.UserServiceImpl"> <property name="userMapper" ref="mapperFactory"/> </bean>--> <!--配置mapper接口扫描器MapperScannerConfigurer 会从配置的包中,扫描所有的接口,并且创建接口的代理对象 下面的bean等同与上面注释的两个的作用 --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.test.ssm.mapper"/> <!--当配置文件中只有一个数据源的时候,可以不写这个参数 有多个数据源的时候,需要指定使用哪个数据源--> <!--<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />--> </bean> <!--IoC注解扫描--> <context:component-scan base-package="com.test.ssm"/> <!--事务管理器--> <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <!--使用注解方式只需要配置事务注解驱动,然后将事务管理器进行绑定 在需要事务控制的类上贴上@Transactional即可--> <!--<aop:config> <aop:pointcut id="pointcut" expression="execution( * com.test.ssm.service..*.*(..))"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut"/> </aop:config> <tx:advice id="txAdvice" transaction-manager="txManager"> <tx:attributes> <tx:method name="find*" read-only="true"/> <tx:method name="*"/> </tx:attributes> </tx:advice>--> <!--事务管理器注解驱动--> <tx:annotation-driven transaction-manager="txManager"/> </beans>
public interface UserMapper //增删改查 Integer save(User user); Integer update(User user); Integer delete(Integer id); User findById(Integer id); List<User> findAll(); //条件查询用到的方法 List<User> select(QueryBean queryBean); //登录检查需要用到的方法 String login(String username); //手动实现分页需要用到的方法 Integer selectCount(QueryBean queryBean); List<User> selectAll(QueryBean queryBean);
@Service @Transactional public class UserServiceImpl implements IUserService @Autowired private UserMapper userMapper; public Integer save(User user) return userMapper.save(user); public Integer update(User user) Integer update = userMapper.update(user); //System.out.println(1/0); return update; public Integer delete(Integer id) return userMapper.delete(id); public User findById(Integer id) return userMapper.findById(id); public List<User> findAll() return userMapper.findAll(); public Boolean login(String username, String pwd) String login = userMapper.login(username); if(login.equals(pwd)) return true; return false; public List<User> select(QueryBean queryBean) return userMapper.select(queryBean); //分页插件的使用 public PageInfo<User> select2(QueryBean queryBean) PageHelper.startPage(queryBean.getCurrentPage(),queryBean.getPageSize()); List<User> list = userMapper.select(queryBean); PageInfo<User> pageInfo = new PageInfo<>(list); return pageInfo; /*将属性封装到类中,减少业务端代码 public PageUtils select3(QueryBean queryBean) Integer total = userMapper.selectCount(queryBean); PageUtils pageUtils = new PageUtils(); //从前台取出的数据赋值 pageUtils.setPageNum(queryBean.getCurrentPage()); pageUtils.setPageSize(queryBean.getPageSize()); //从数据库中查询出的数据赋值 pageUtils.setList(userMapper.selectAll(queryBean)); pageUtils.setTotal(total); //经过计算得到的数据赋值 int pages = Double.valueOf(Math.ceil(pageUtils.getTotal()*1.0/pageUtils.getPageSize())).intValue(); pageUtils.setPages(pages); Integer nextPage; if(queryBean.getCurrentPage()==pageUtils.getPages()) nextPage=1; else nextPage=queryBean.getCurrentPage()+1; pageUtils.setNextPage(nextPage); Integer prePage; if(queryBean.getCurrentPage()==1) prePage=pageUtils.getPages(); else prePage=queryBean.getCurrentPage()-1; pageUtils.setPrePage(prePage); return pageUtils; */ public PageUtils select3(QueryBean queryBean) Integer total = userMapper.selectCount(queryBean); if(total==0) //可以减少一次查询,提高效率 return new PageUtils(queryBean.getCurrentPage(),queryBean.getPageSize(),null,total); List<User> list = userMapper.selectAll(queryBean); return new PageUtils(queryBean.getCurrentPage(),queryBean.getPageSize(),list,total);
6、这时可先测试一下代码,使用测试类App测试增删改查
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext.xml") public class App @Autowired private IUserService userService; @Test public void testSave() User user = new User(null,"林丹","qwer",new Date()); userService.save(user); @Test public void testUpdate() User user =new User(10,"小芳","qwer",new Date()); userService.update(user); @Test public void testDelete() userService.delete(5); @Test public void testFindOneById() System.out.println(userService.findById(3)); @Test public void testFindAll() System.out.println(userService.findAll());
第三步:添加事务控制
1、添加依赖 aspectj
2、配置事务管理器,本质上是一个<bean id="txManager" class=""/>
3、配置事务(两种方式)
1.xml方式
<aop:config> <aop:pointcut id="pointcut" expression="execution( * com.test.ssm.service..*.*(..))"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut"/> </aop:config> <tx:advice id="txAdvice" transaction-manager="txManager"> <tx:attributes> <tx:method name="find*" read-only="true"/> <tx:method name="*"/> </tx:attributes> </tx:advice>
2.使用注解的方式
配置事务管理器,需要配置事务管理器注解驱动@Transactional即可
<!--事务管理器注解驱动--> <tx:annotation-driven transaction-manager="txManager"/>
第四步:配置前端页面
1、导入依赖servlet-api
2、在web.xml中配置前端控制器(本质上是一个servlet)
客户端访问时会先通过前端控制器,再通过拦截器
<!--配置前端控制器--> <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:springMVC.xml</param-value> </init-param> <!--配置自动启动前端控制器--> <load-on-startup>2</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcherServlet</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping>
注意:配置中的文件关联有没有将配置信息引入,可以在springMVC中使用import标签进行引入
<?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" 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"> <!--引入后台的Spring配置文件--> <import resource="classpath:applicationContext.xml"/> </beans>
3、在web.xml中配置编码过滤器,解决中文乱码问题
<!--请求编码过滤器--> <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> <!--设置请求和响应是否强制编码--> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>characterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
4、在springMVC中配置拦截器,拦截想要跳过登录界面访问受保护资源的请求
<!--拦截器--> <mvc:interceptors> <!--登录检查拦截器--> <!--路径/**表示拦截所有路径,/*只能拦截所有一级路径--> <mvc:interceptor> <mvc:mapping path="/**"/> <!--对某个请求放行--> <mvc:exclude-mapping path="/login.do"/> <!--配置拦截器的全限定名--> <bean class="com.test.ssm.interceptor.MyInterceptor"></bean> </mvc:interceptor> </mvc:interceptors>
拦截器
public class MyInterceptor implements HandlerInterceptor @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception HttpSession session = request.getSession(); if(session.getAttribute("USER_IN_SESSION")==null) response.sendRedirect("/index.html"); return false; return true;
第五步:编写Controller和访问页面
在web.xml中添加如下代码,可以默认访问此页面
<welcome-file-list> <welcome-file>index.html</welcome-file> </welcome-file-list>
Controller代码示例
@Controller public class UserController @Autowired private IUserService userService; @RequestMapping("/findAll") public String findAll(Model model) List<User> list = userService.findAll(); model.addAttribute("list",list); return "list"; @RequestMapping("/login") public String login(String username, String pwd, HttpSession session) Boolean login = userService.login(username, pwd); if(login) session.setAttribute("USER_IN_SESSION",username); return "redirect:/findAll.do"; return "redirect:/index.html"; @RequestMapping("/edit") public String edit(Integer id,Model model) if(id!=null) model.addAttribute("user",userService.findById(id)); return "edit"; //将添加和保存写在同一个页面内 @RequestMapping("/saveOrUpdate") public String saveOrUpdate(User user) if(user.getId()!=null) userService.update(user); else userService.save(user); return "redirect:/findAll.do"; @RequestMapping("/delete") public String delete(Integer id) if(id!=null) userService.delete(id); return "redirect:/findAll.do"; //条件查询 @RequestMapping("/select") public String select(@ModelAttribute("queryBean") QueryBean queryBean, Model model) List<User> list = userService.select(queryBean); model.addAttribute("list",list); return "list"; //使用分页插件进行条件查询 @RequestMapping("/select2") public String select2(@ModelAttribute("queryBean") QueryBean queryBean, Model model) PageInfo<User> pageInfo = userService.select2(queryBean); model.addAttribute("page",pageInfo); return "list"; //使用自己定义的分页功能进行条件查询 @RequestMapping("/select3") public String select3(@ModelAttribute("queryBean") QueryBean queryBean, Model model) PageUtils pageUtils = userService.select3(queryBean); model.addAttribute("page",pageUtils); return "list";
页面代码
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h2>Hello World!</h2> <form action="/login.do" method="post"> 用户名:<input type="text" name="username"/> 密码:<input type="text" name="pwd"/> <input type="submit"/> </form> </body> </html>
下面两个页面在WEB-INF下的views里,是受保护页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <div style="text-align: center;"> <h2>用户编辑</h2> <form action="/saveOrUpdate.do" method="post"> <input type="hidden" name="id" value="$user.id"/> 用户名:<input type="text" name="username" value="$user.username"/> <br/>密码:<input type="text" name="pwd" value="$user.pwd"/><br/> 日期:<input type="date" name="date" value="$user.date"/><br/> <input type="submit" value="保存"/> </form> </div> </body> </html>
<%@ 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> <script type="text/javascript"> function goPage(page) //设置当前页的值 document.getElementById("currentPage").value = page; //提交表单 var form = document.getElementById("f1"); form.submit(); //提交表单 </script> </head> <body> <div style="text-align: center;"> <h1>用户列表</h1> <%--使用了对象进行参数接受的时候,在参数封装的同时会将对象加入到作用域中 --%> <form id="f1" action="/select3.do" method="post"> 用户姓名:<input type="text" name="username" value="$queryBean.username"/> 注册日期:<input type="text" name="date" value="$queryBean.date"/> <input type="submit" value="查询"/> <input type="button" onclick="location.href=‘/edit.do‘" value="增加" style="width: 40px;text-align: center"/> <table border="1px" width="60%" style="text-align: center;margin: 0 auto;"> <tr> <th>编号</th> <th>姓名</th> <th>密码</th> <th>注册日期</th> <th>操作</th> </tr> <c:forEach items="$page.list" var="user" varStatus="index"> <tr> <td>$index.count</td> <td>$user.username</td> <td>$user.pwd</td> <td>$user.date</td> <td><a href="/edit.do?id=$user.id">修改</a>|<a href="/delete.do?id=$user.id">删除</a></td> </tr> </c:forEach> <tr> <td colspan="5"> <a href="javascript:void(0);" onclick="goPage(1)">首页</a> <a href="javascript:void(0);" onclick="goPage($page.prePage)">上一页</a> <a href="javascript:void(0);" onclick="goPage($page.nextPage)">下一页</a> <a href="javascript:void(0);" onclick="goPage($page.pages)">尾页</a> <input type="text" name="currentPage" id="currentPage"/> <input type="submit" value="跳转"/> 每页显示: <select name="pageSize" onchange="goPage(1)"> <option value="3" $queryBean.pageSize==3?‘selected‘:‘‘>3</option> <option value="4" $queryBean.pageSize==4?‘selected‘:‘‘>4</option> <option value="5" $queryBean.pageSize==5?‘selected‘:‘‘>5</option> </select> 当前$page.pageNum页/共$page.pages页/共$page.total条记录 </td> </tr> </table> </form> </div> </body> </html>
多条件查询
待明天补充,休息拉
分页
以上是关于SSM整合的主要内容,如果未能解决你的问题,请参考以下文章