SSM整合—XML开发
# 注入mapper
导入依赖坐标(注意,c3p0的0.9.1.2版本必须对应mybatis3.4.5版本或者以下)
<!--spring _ 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>2.0.5</version> </dependency> <!-- 数据源--> <dependency> <groupId>c3p0</groupId> <artifactId>c3p0</artifactId> <version>0.9.1.2</version> </dependency> <!-- spring -tx 这个包一定要有 即使不用jdbc模板也要有--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>5.3.6</version> </dependency>在spring配置文件中 配置sqlSessionFactory和mapper
<!--配置 sqlSessionFactory--> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource_c3p0"/> <!-- 加载核心配置文件--> <property name="configLocation" value="classpath:mybatis-config-spring.xml"/> </bean> <!-- 扫描mapper所在的包 为mapper包创建实现类--> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.diana.mapper"/> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/><!-- 这句可没有--> </bean>
代码编写
@Service("userService") public class UserService { @Autowired private userMapper mapper;//注入mapper public User selectById(int id){ User user = mapper.selectById(id);//调用方法 System.out.println(user); return user; } }@Controller("userController") public class UserController { @Autowired private UserService userService;//注入service @RequestMapping("/user") public String selectById(){ int id=1; User user = userService.selectById(id); System.out.println(user); return "success"; } }
# 事务控制 (同spring原始的事务控制)
- 导入依赖 (aop配置的依赖)因为spring实现事务控制底层就是aop
<!-- aspectj aop 配置-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
- 开发步骤
service层注解
在service方法上加@Transactional(isolation = Isolation.REPEATABLE_READ),表示要对这个方法进行事务控制
可在类上直接配置@Transactional,表示整个类所有方法的默认事务控制
当方法和类上同时都有事务控制时,以方法上的为主,就近原则
//先删除外键对,再删除用户 两个id是一样的 //要开启事务控制 @Transactional public void delete(int id){ System.out.println("删除id "+id); //删除外键对 mapper_role.deleteByUid(id); //int i=1/0; //模拟异常 //删除用户 mapper.deleteById(id); }xml中剩余配置
- 把原配置中的 增强方法 声明和 织入过程 用@Transactional()来代替
- 添加了一个包扫描和事务的注解驱动配置
<!-- jdbc模板数据 别人的东西 一般在xml中配置--> <!--加载外部配置文件property--> <context:property-placeholder location="classpath:jdbc.properties"/> <!-- el表达式 来获取配置文件信息--> <bean id="dataSource_c3p0" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="${jdbc.driver}"/> <property name="user" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> <property name="jdbcUrl" value="${jdbc.url}"/> </bean> <!-- 在spring 容器中产生 jdbc模板对象 同时注入数据源--> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource_c3p0"/> </bean> <!-- 配置一个平台事务管理器--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource_c3p0"/> </bean> <!-- 事务的注解驱动--> <tx:annotation-driven transaction-manager="transactionManager"/> <!-- 包扫描--> <context:component-scan base-package="com.diana"/>
# 注意问题
# 1.模型设置
记得起名字,然后在网页中调用模型的名字。
modelAndView.addObject("roleList",roles);<c:forEach items="${roleList}" var="role">
# 2.数据添加
数据添加完成后,不要直接跳转到展示页面,因为单单一个视图是没有数据的,要重定向(redirect)到查询所有的url。
return "redirect:/role/list";
# 3.查询带有角色信息的所有用户
因为要显示用户的角色信息,所有涉及到多表查询。在User对象中封装一个Role的集合,作为外键连接,然后在输出时进行映射。
<resultMap id="user_order" type="user_role"> <id column="userId" property="id"/> <result column="username" property="username"/> <result column="password" property="password"/> <result column="email" property="email"/> <result column="phoneNum" property="phoneNum"/> <collection property="roles" ofType="role"> <result column="roleName" property="roleName"/> </collection> </resultMap> <select id="selectAll_Order" resultMap="user_order"> select *,u.id,r.id from sys_user u,sys_role r,sys_user_role ur where u.id=userId and r.id=roleId </select>public class User_role { private int id; private String username; private String email; private String password; private String phoneNum; //封装一个角色对象 private List<Role> roles;}
# 4.新增用户
因为涉及到多对多,所以有第三张外键对应表。即,在新增用户表的时候,还有添加对应的外键表。
因为在新增页面,需要显示当前角色有哪些,所以要进行数据回显,先查询当前角色信息,然后在跳转到添加页面。一般该页面被称为addUI。
<c:forEach items="${roleList}" var="role" > ${role.roleName} </c:forEach>
```java //进入添加页面 回显数据 显示角色信息 @RequestMapping("/addUI") public ModelAndView addUI(){ ModelAndView modelAndView=new ModelAndView(); //查询数据 List<Role> roles = roleService.selectAll(); modelAndView.addObject("roleList",roles); modelAndView.setViewName("user-add"); return modelAndView; }
外键表需要Uid和Rid,Uid在从网页获取新增数据的时候是获取不到,因为Uid对于User表来说是主键,自增的,不能让用户输入。所以要在插入User表数据后,获取对应的Uid。而Rid则以数组的形式直接从网页读取即可,这里数组的名字要和表单提交信息的name值相同。
<!-- 这里非常重要 ,一般的插入是得不到id的--> <insert id="add" useGeneratedKeys="true" keyProperty="id" > insert into sys_user(username, email, password, phoneNum) VALUES (#{username},#{email},#{password},#{phoneNum}) </insert>//service层 //新增用户 +新增对应外键 //要开启事务控制 @Transactional //开始事务控制 public void add(User_role user_role,int[] roleIds){ // 新增用户表 mapper.add(user_role); //要先插入数据,通过插入数据来获取id int userId=user_role.getId(); //新增外键 for(int roleId:roleIds){ mapper_role.add(userId,roleId); } }//两个roleId 名称必须一致 Rid通过value值获取 @RequestMapping("/add") public String add(User_role user,int[] roleId){} <input class="" type="checkbox" name="roleId" value="${role.id}">${role.roleName}要进行事务操作 @Transactional
# 5.删除用户信息
* 因为有外键约束,所以要先删除对应外键表,然后在删除用户信息表。 ```java //service层 //先删除外键对,再删除用户 两个id是一样的 //要开启事务控制 @Transactional //开启事务控制 public void delete(int id){ System.out.println("删除id "+id); //删除外键对 mapper_role.deleteByUid(id); //删除用户 mapper.deleteById(id); } ``` * 通过get方式得到要删除的id。User表的id和外键表的Uid是一样的,所以只需要一个参数即可。 ```jsp <a href="${pageContext.request.contextPath}/user/delete?id=${user.id}" class="btn bg-olive btn-xs">删除</a> ``` * 要进行事务操作 @Transactional
# 6.用户登录
使用拦截器拦截对url的访问,只有当完成登录操作后,才可以进入后台。
<mvc:interceptors> <mvc:interceptor> <!-- 配置对哪些资源进行拦截操作--> <mvc:mapping path="/**"/> <!-- 配置对哪些资源不进行拦截操作--> <mvc:exclude-mapping path="/login"/> <!-- 不拦截登陆页面--> <bean class="com.diana.interceptor.Myinterceptor"/> </mvc:interceptor> </mvc:interceptors>重定向到另一个页面时,路径名要写全 spring-mvc中配置的内部资源解析器(“/pages/”+str+".jsp")不适应用它
@RequestMapping("/login") public String login(String username, String password, HttpSession session){ //获取数据库查询的用户 User_role user = userService.login(username, password); System.out.println(user); //如果用户存在 if(user!=null){ //如果正确,将用户信息存入session域中,重定向到主页面 session.setAttribute("user",user); // return "redirect:/index.jsp"; return "redirect:/pages/main.jsp"; //重定向 的话 要写全路径名 spring-mvc中配置的内部资源解析器不适应用它 }else{ //如果不正确,跳转到登陆页面 return "redirect:/login.jsp"; } }获取url访问的外部名称--request.getContextPath()
//执行方法之前 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { //得到session域中存放的用户对象 HttpSession session = request.getSession(); User_role user = (User_role)session.getAttribute("user"); System.out.println(user); //如果session域中没有用户对象 if(user==null){ //request.getContextPath() 获取外部名称 response.sendRedirect(request.getContextPath()+"/login.jsp");//如果没有登陆,则重定向到登陆页面 return false; } //如果session域中有用户对象 return true; }
# 7.service注入
因为要使用事务,所以使用了动态代理技术,所以在注入的时候要使用接口进行注入
@Autowired private UserService userService;//注入userService 用接口来接 因为用到了动态代理技术 事务 @Autowired private RoleService roleService;//注入roleService
