项目环境搭建
创建工程(Project&Module)
导入静态页面(见jsp页面)
导入需要坐标(见pom.xml)
创建包结构(controller、service、dao、domain、utils)
导入数据库脚本(见数据库sys_role、sys_user、sys_user_role)
创建POJO类
1 2 3 4 5 6 7 8 9 10 11 public class Role { private Long id; private String roleName; private String roleDesc; @Override public String toString () {...} }
1 2 3 4 5 6 7 8 9 10 11 12 13 public class User { private Long id; private String username; private String email; private String password; private String phoneNum; set AND get... @Override public String toString () {...} }
创建配置文件(applicationContext.xml、spring-mvc.xml、jdbc.properties、log4j.properties)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 web.xml<context-param > <param-name > contextConfigLocation</param-name > <param-value > classpath:applicationContext.xml</param-value > </context-param > <listener > <listener-class > org.springframework.web.context.ContextLoaderListener</listener-class > </listener > <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:spring-mvc.xml</param-value > </init-param > <load-on-startup > 1</load-on-startup > </servlet > <servlet-mapping > <servlet-name > DispatcherServlet</servlet-name > <url-pattern > /</url-pattern > </servlet-mapping >
1 2 3 4 5 6 7 8 9 10 11 12 13 spring-mvc.xml<mvc:annotation-driven /> <bean class ="org.springframework.web.servlet.view.InternalResourceViewResolver" > <property name ="prefix" value ="/pages/" /> <property name ="suffix" value =".jsp" /> </bean > <mvc:default-servlet-handler />
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 appliccationContext.xml<context:property-placeholder location ="classpath:jdbc.properties" /> <bean id ="dataSource" class ="com.mchange.v2.c3p0.ComboPooledDataSource" > <property name ="driverClass" value ="${jdbc.driver}" /> <property name ="jdbcUrl" value ="${jdbc.url}" /> <property name ="user" value ="${jdbc.username}" /> <property name ="password" value ="${jdbc.password}" /> </bean > <bean id ="jdbcTemplate" class ="org.springframework.jdbc.core.JdbcTemplate" > <property name ="dataSource" ref ="dataSource" /> </bean >
用户和角色的关系
角色列表的展示和添加功能 角色列表的展示 效果图
步骤分析 ① 点击角色管理菜单发送请求到服务器端(修改角色管理菜单的url地址)
② 创建 RoleController 和 showList() 方法
③ 创建 RoleService 和 showList() 方法
④ 创建 RoleDao 和 findAll() 方法
⑤ 使用 JdbcTemplate 完成查询操作
⑥ 将查询数据存储到 Model 中
⑦ 转发到 role-list.jsp 页面进行展示
详细开发流程 1. 修改角色管理菜单的url地址 通过查看代码发现,首页是重定向到 main.jsp :
而我们要点击的角色列表所在的导航侧栏又在 aside.jsp 中:
在 aside.jsp 中指定点击角色管理菜单后要调用的 controller 层中的方法(请求虚拟映射地址):
2. 创建 RoleController 和 list() 方法 创建controller层的 RoleController ,提供使用ModelAndView对象封装所有角色信息的 list() 方法,并将第一步中的请求虚拟地址映射到具体的方法上:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 @RequestMapping("/role") public class RoleController { private RoleService roleService; public void setRoleService (RoleService roleService) { this .roleService = roleService; } @RequestMapping("/list") public ModelAndView list () { ModelAndView modelAndView = new ModelAndView(); List<Role> roleList = roleService.list(); modelAndView.addObject("roleList" ,roleList); modelAndView.setViewName("role-list" ); return modelAndView; } }
3. 创建 RoleService 和 list() 方法 创建业务service层的 RoleService 接口及实现类 RoleServiceImpl ,提供通过dao层获取所有角色信息的 list() 方法:
1 2 3 4 5 public interface RoleService { public List<Role> list () ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public class RoleServiceImpl implements RoleService { private RoleDao roleDao; public void setRoleDao (RoleDao roleDao) { this .roleDao = roleDao; } @Override public List<Role> list () { List<Role> roleList = roleDao.findAll(); return roleList; } }
4. 创建 RoleDao 和 findAll() 方法 创建业务dao层的 RoleDao 接口及实现类 RoleDaoImpl ,并提供从数据库获取所有角色信息的 findAll() 方法:
1 2 3 4 5 public interface RoleDao { List<Role> findAll () ; }
1 2 3 4 5 6 7 public class RoleDaoImpl implements RoleDao { @Override public List<Role> findAll () { return null ; } }
5. 使用 JdbcTemplate 完成查询操作 在 findAll() 方法中通过JdbcTemplate从数据库查询所有角色信息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public class RoleDaoImpl implements RoleDao { private JdbcTemplate jdbcTemplate; public void setJdbcTemplate (JdbcTemplate jdbcTemplate) { this .jdbcTemplate = jdbcTemplate; } @Override public List<Role> findAll () { List<Role> roleList = jdbcTemplate.query("select * from sys_role" , new BeanPropertyRowMapper<Role>(Role.class)); return roleList; } }
6. 将查询数据存储到 Model 中 这一步步骤2中我们已经完成了。
7. 进行Spring 相关配置 说明我们把具体的业务写好了,但 Spring 容器中并没有对应的实例,我们需要配置把所有的类的实例加入到 Spring 容器中。
web层 使用 @Controller 注解实例化 RoleController,使用 @Autowired 注解为字段注入实例:
1 2 3 4 5 6 7 @Controller public class RoleController { @Autowired private RoleService roleService; ………… }
因为我们使用的是注解方式产生 bean,所以还需要在 spring-mvc .xml 中配置组件扫描:
1 2 <context:component-scan base-package ="cc.gaojie.controller" />
dao层 在核心配置文件 applicationContext.xml 中配置 RoleDao,并为其注入 jdbcTemplate
1 2 3 4 <bean id ="roleDao" class ="cc.gaojie.dao.impl.RoleDaoImpl" > <property name ="jdbcTemplate" ref ="jdbcTemplate" /> </bean >
service层 在核心配置文件 applicationContext.xml 中配置 RoleService,并为其注入 roleDao。
1 2 3 4 <bean id ="RoleService" class ="cc.gaojie.service.impl.RoleServiceImpl" > <property name ="roleDao" ref ="roleDao" /> </bean >
8. 转发到 role-list.jsp 页面进行展示 在页面 role-list.jsp 中取值展示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <tbody> <c:forEach items="${roleList} " var ="role" > <tr> <td><input name="ids" type="checkbox" ></td> <td>${role.id}</td> <td>${role.roleName}</td> <td>${role.roleDesc}</td> <td class ="text-center" > <a href="#" class ="btn bg-olive btn-xs" >删除</a> </td> </tr> </c:forEach> </tbody>
到此,角色列表展示的功能开发完成。启动服务器,在首页中点击角色管理选项,就能查看到数据库中对应的角色信息了:
角色的添加功能 效果图
步骤分析
点击列表页面新建按钮跳转到角色添加页面
输入角色信息,点击保存按钮,表单数据提交服务器
编写 RoleController 的 save() 方法
编写 RoleService 的 save() 方法
编写 RoleDao 的 save() 方法
使用 JdbcTemplate 保存 Role 数据到 sys_role
跳转回角色列表页面
详细开发流程 1. 修改列表页面新建按钮的url地址 在角色添加页面 role-add.jsp 中指定点击列表页面新建按钮要调用的 controller 层中的方法(请求虚拟映射地址):
因为我们这里使用的是 post 的方式发送到请求,为防止提交到数据库后字符出现乱码,需要在 web.xml 中配置一个字符编码过滤器:
1 2 3 4 5 6 7 8 9 10 11 12 13 <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 >
2. 编写 RoleController 的 save() 方法 在controller层的 RoleController 中编写用于保存新添加角色的 save() 方法。 添加完以重定向的方式跳转回角色列表页面:
1 2 3 4 5 6 7 8 9 10 11 12 public class RoleController { @Autowired private RoleService roleService; public void setRoleService (RoleService roleService) { this .roleService = roleService; } @RequestMapping("/save") public String save (Role role) { roleService.save(role); return "redirect:/role/list" ; } }
3. 编写 RoleService 的 save() 方法 1 2 3 4 5 6 public interface RoleService { public List<Role> list () ; void save (Role role) ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 public class RoleServiceImpl implements RoleService { private RoleDao roleDao; public void setRoleDao (RoleDao roleDao) { this .roleDao = roleDao; } @Override public void save (Role role) { roleDao.save(role); } }
4. 编写RoleDao的save()方法,使用 JdbcTemplate 保存 Role 数据到 sys_role 1 2 3 4 5 6 public interface RoleDao { List<Role> findAll () ; void save (Role role) ; }
1 2 3 4 5 6 7 8 9 10 11 12 public class RoleDaoImpl implements RoleDao { private JdbcTemplate jdbcTemplate; public void setJdbcTemplate (JdbcTemplate jdbcTemplate) { this .jdbcTemplate = jdbcTemplate; } @Override public void save (Role role) { jdbcTemplate.update("insert into sys_role values(?,?,?)" ,null , role.getRoleName(),role.getRoleDesc()) } }
到此,角色添加的功能开发完成。点击列表页面新建按钮,就可以将新角色信息添加到数据库并展示在页面了:
用户列表的展示和添加功能 用户列表的展示 效果图
步骤分析
点击用户管理菜单发送请求到服务器端(修改用户管理菜单的url地址)
创建 RoleController 和 list() 方法
创建 RoleService 和 list() 方法
创建 RoleDao 和 findAll() 方法
使用 JdbcTemplate 完成查询操作
将查询数据存储到 Model 中
转发到 user-list.jsp 页面进行展示
详细开发流程 1. 描述实体之间的关系关系 一个用户可以具备多个角色,即 User 与 Role 是一对多关系。在实体类 User 中通过对象引用的方式描述这种关系:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public class User { private Long id; private String username; private String email; private String password; private String phoneNum; private List<Role> roles; public List<Role> getRoles () { return roles; }
2. 修改用户管理菜单的url地址 在 aside.jsp 中指定点击用户列表菜单后要调用的 controller 层中的方法(请求虚拟映射地址):
3. 创建 UserController 和 list() 方法 创建 controller 层的 UserController ,提供使用ModelAndView对象封装所有用户信息的 list() 方法,并将第二步中的请求虚拟地址映射到具体的方法上:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 @Controller @RequestMapping("/user") public class UserController { @Autowired private UserService userService; @RequestMapping("/list") public ModelAndView list () { List<User> userList = userService.list(); ModelAndView modelAndView = new ModelAndView(); modelAndView.addObject("userList" ,userList); modelAndView.setViewName("user-list" ); return modelAndView; } }
4. 创建 UserService 和 list() 方法 创建业务service层的 UserService 接口及实现类 UserServiceImpl ,提供通过dao层获取所有用户信息的 list() 方法:
1 2 3 4 5 public interface UserService { List<User> list () ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 public class UserServiceImpl implements UserService { private UserDao userDao; public void setUserDao (UserDao userDao) { this .userDao = userDao; } @Override public List<User> list () { return userDao.findAll(); } }
5. 创建 UserDao 和 findAll() 方法 创建业务dao层的 UserDao 接口及实现类 UserDaoImpl ,并提供从数据库获取所有角色信息的 findAll() 方法:
1 2 3 4 5 public interface UserDao { List<User> findAll () ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public class UserDaoImpl implements UserDao { private JdbcTemplate jdbcTemplate; public void setJdbcTemplate (JdbcTemplate jdbcTemplate) { this .jdbcTemplate = jdbcTemplate; } @Override public List<User> findAll () { List<User> userList = jdbcTemplate.query("select * from sys_user" , new BeanPropertyRowMapper<User>(User.class)); return userList; } }
6. 进行Spring 相关配置 除 controller 层已经使用注解配置外,其他层还未进行配置,Spring 容器中还没有对应的实例,我们采用配置核心配置文件 applicationContext.xml 的方式来配置:
1 2 3 4 5 6 7 8 9 <bean id ="userService" class ="cc.gaojie.service.impl.UserServiceImpl" > <property name ="userDao" ref ="userDao" /> </bean > <bean id ="userDao" class ="cc.gaojie.dao.impl.UserDaoImpl" > <property name ="jdbcTemplate" ref ="jdbcTemplate" /> </bean >
7. 转发到 user-list.jsp 页面进行展示 在页面 user-list.jsp 中取值展示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <tbody> <c:forEach items="${userList}" var ="user" > <tr> <td><input name="ids" type="checkbox" ></td> <td>${user.id}</td> <td>${user.username}</td> <td>${user.email}</td> <td>${user.phoneNum}</td> <td class ="text-center" > 课程研究员 讲师 </td> <td class ="text-center" > <a href="javascript:void(0);" class ="btn bg-olive btn-xs" >删除</a> </td> </tr> </c:forEach> </tbody>
8. 封装用户的 roles 数据 通过上面的操作,我们完成了用户除角色外信息的查询和展示,但用户的角色信息不在 sys_user 表中,需要我们进一步封装。
service 层 在 UserService 中将id作为参数,查询当前userId对应的Role集合数据并封装返回给 controller 层:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 public class UserServiceImpl implements UserService { private UserDao userDao; public void setUserDao (UserDao userDao) { this .userDao = userDao; } private RoleDao roleDao; public void setRoleDao (RoleDao roleDao) { this .roleDao = roleDao; } @Override public List<User> list () { List<User> userList = userDao.findAll(); for (User user: userList) { Long id = user.getId(); List<Role> roleList = roleDao.findByUserId(id); user.setRoles(roleList); } return userList; } }
在核心配置文件 applicationContext.xml 中进行配置注入:
1 2 3 4 5 <bean id ="userService" class ="cc.gaojie.service.impl.UserServiceImpl" > <property name ="userDao" ref ="userDao" /> <property name ="roleDao" ref ="roleDao" /> </bean >
dao 层 在 UserDaoImpl 中,创建 ***findByUserId()***方法, 通过 JdbcTemplate ,以service层传过来的id作为参数,结合中间表 sys_user_role 和角色表 sys_role 查询对应用户的角色数据返回给 service 层:
1 2 3 4 5 @Override public List<Role> findByUserId (Long id) { List<Role> roles = jdbcTemplate.query("select * from sys_user_role ur,sys_role r where ur.roleId=r.id and ur.userId = ?" , new BeanPropertyRowMapper<Role>(Role.class), id); return roles; }
9. 在页面 user-list.jsp 中取值展示用户角色信息 1 2 3 4 5 <td class ="text-center" > <c:forEach items="${user.roles}" var ="role" > ${role.roleName} </c:forEach> </td>
到此,用户列表展示的功能开发完成。启动服务器,在首页中点击用户管理选项,就能查看到数据库中对应的用户信息了:
用户的添加功能 效果图
步骤分析
点击列表页面新建按钮跳转到角色添加页面
输入角色信息,点击保存按钮,表单数据提交服务器
编写 RoleController 的 save() 方法
编写 RoleService 的 save() 方法
编写 RoleDao 的 save() 方法
**使用 JdbcTemplate 保存 Role 数据到 sys_role **
跳转回角色列表页面
详细开发流程 1. 点击列表页面新建按钮跳转到角色添加页面 在 user-list.jsp 中指定点击列表页面新建按钮要调用的 controller 层中的方法,即获取所有的角色信息,在用户添加页面展示所有角色的UI,让用户选择:
2. 编写 UserController 的 saveUI() 方法 在controller层的 RoleController 中的 saveUI() 方法里查询所有角色的信息的, 查询完跳转到用户添加页面并展示这些角色信息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @Controller @RequestMapping("/user") public class UserController { @Autowired private UserService userService; @Autowired private RoleService roleService; @RequestMapping("/saveUI") public ModelAndView saveUI () { List<Role> roleList = roleService.list(); ModelAndView modelAndView = new ModelAndView(); modelAndView.addObject("roleList" ,roleList); modelAndView.setViewName("user-add" ); return modelAndView; }
3. 在用户添加页面展示所有角色信息 在 user-add.jsp 取值展示所有的角色,供用户选择。当用户勾选某些角色信息后,将勾选角色的对应id传递会服务端进行后续操作。
1 2 3 4 5 6 7 8 9 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <div class ="col-md-2 title" >用户角色</div> <div class ="col-md-10 data" > <c:forEach items="${roleList}" var ="role" > <input class ="" type="checkbox" name="roleIds" value="${role.id}" >${role.roleName} </c:forEach> </div> </div>
4. 编写 UserController 的 save() 方法 在controller层的 RoleController 中的 save() 方法里接收用户添加页面提交过来的数据,返回给 service 层处理。最后以重定向的方式跳转回角色列表页面:
1 2 3 4 5 6 7 8 9 10 @Controller @RequestMapping("/user") public class UserController { @RequestMapping("/save") public String save (User user,Long[] roleIds) { userService.save(user,roleIds); return "redirect:/user/list" ; } }
5. 编写 UserService 的 save() 方法 在 service 层的 UserService 中创建 save() 方法,通过dao层保存用户相关信息到数据库。
1 2 3 4 5 6 public interface UserService { List<User> list () ; void save (User user, Long[] roleIds) ; }
1 2 3 4 5 6 7 8 9 10 11 public class UserServiceImpl implements UserService { @Override public void save (User user, Long[] roleIds) { Long userId = userDao.save(user); userDao.saveUserRoleRel(userId,roleIds) } }
6. 编写 UserDao 中保存数据的相关方法 1 2 3 4 5 6 public interface UserDao { Long save (User user) ; void saveUserRoleRel (Long id, Long[] roleIds) ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 public class UserDaoImpl implements UserDao { private JdbcTemplate jdbcTemplate; public void setJdbcTemplate (JdbcTemplate jdbcTemplate) { this .jdbcTemplate = jdbcTemplate; } @Override public Long save (User user) { PreparedStatementCreator creator = new PreparedStatementCreator() { @Override public PreparedStatement createPreparedStatement (Connection connection) throws SQLException { PreparedStatement preparedStatement = connection.prepareStatement("insert into sys_user values(?,?,?,?,?)" , PreparedStatement.RETURN_GENERATED_KEYS); preparedStatement.setObject(1 , null ); preparedStatement.setString(2 , user.getUsername()); preparedStatement.setString(3 , user.getEmail()); preparedStatement.setString(4 , user.getPassword()); preparedStatement.setString(5 , user.getPhoneNum()); return preparedStatement; } }; GeneratedKeyHolder keyHolder = new GeneratedKeyHolder(); jdbcTemplate.update(creator,keyHolder); long userId = keyHolder.getKey().longValue(); return userId; } @Override public void saveUserRoleRel (Long userId, Long[] roleIds) { for (Long roleId : roleIds) { jdbcTemplate.update("insert into sys_user_role values (?,?)" , userId, roleId); } } }
到此,用户添加的功能开发完成。点击列表页面新建按钮,就可以将新用户信息添加到数据库并展示在页面了:
删除用户 效果图
删除用户的步骤分析
点击用户列表的删除按钮,发送请求到服务器端
编写 UserController 的 del 方法
编写 UserService 的 del 方法
编写 UserDao 的 del 方法
编写 UserDao 的 delUserRoleRel方法
跳回当前用户列表页面
详细开发流程 1. 编写删除按钮要触发的逻辑 在 user-list.jsp 中编写用户点击删除按钮后要触发的事件:给出提示信息,并传递当前用户的 id ,调用 controller 层中的方法。(这里用到了Restful风格的参数,详细介绍见『传送门 』)
1 2 3 4 5 6 7 8 9 10 11 <script> function delUser (userId) { if (confirm("您确认要删除吗?" )){ location.href="${pageContext.request.contextPath}/user/del/" +userId } } </script> <td class ="text-center" > <a href="javascript:void(0);" onclick="delUser('${user.id}')" class ="btn bg-olive btn-xs" >删除</a> </td>
2. 编写 UserController 的 del() 方法 在dao层的 UserController 中调用service层删除用户的方法,并重定向到用户列表页。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 @Controller @RequestMapping("/user") public class UserController { @Autowired private UserService userService; @RequestMapping("/del/{userId}") public String del (@PathVariable("userId") Long userId) { userService.del(userId); return "redirect:/user/list" ; } }
3. 编写 UserService 的 del 方法 在service层的 UserController 中调用dao层的方法,删除关系表和用户表中的对应数据。
1 2 3 4 5 public interface UserService { void del (Long userId) ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public class UserServiceImpl implements UserService { private UserDao userDao; public void setUserDao (UserDao userDao) { this .userDao = userDao; } @Override public void del (Long userId) { userDao.delUserRoleRel(userId); userDao.del(userId); } }
4. 编写 UserDao 的 deleteById() 方法 在dao层的 UserDao 中编写 del() 和 delUserRoleRel() 方法,利用JdbcTemplate删除关系表和用户表中的对应数据。
1 2 3 4 5 6 public interface UserDao { void delUserRoleRel (Long userId) ; void del (Long userId) ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class UserDaoImpl implements UserDao { private JdbcTemplate jdbcTemplate; public void setJdbcTemplate (JdbcTemplate jdbcTemplate) { this .jdbcTemplate = jdbcTemplate; } @Override public void delUserRoleRel (Long userId) { jdbcTemplate.update("delete from sys_user_role where userId = ?" , userId); } @Override public void del (Long userId) { jdbcTemplate.update("delete from sys_user where id = ?" , userId); } }
到此,用户删除的功能开发完成。点击列表页面删除按钮,就可以将用户信息从数据库中删除了: