Spring综合练习 —— 基于Spring+SpringMVC的后台管理系统Demo案例
往期文章
Spring01 —— Spring概念及快速入门
Spring02 —— Spring配置文件详解和依赖注入
Spring03 —— SpringAPI和在Spring中配置数据源
Spring04 —— Spring的注解开发
Spring05 —— Spring集成Junit
Spring06 —— Spring集成web环境
SpringMVC01 —— SpringMVC简介&快速入门
SpringMVC02 —— SpringMVC的各组件详解
SpringMVC03 —— Spring的请求和响应
Spring07 —— Spring JdbcTemplate的相关操作
在之前我们已经学习了Spring和SpringMVC。Spring的每一层都提供了相应的解决方案,web层有SpringMVC,整体Spring有Spring容器和di依赖注入,我们可以将每一层的bean都交由Spring去产生,dao层有Spring jdbctemplate,所以可以基于上述技术做一个案例小练习。
资料下载地址:
https://pan.baidu.com/s/1HuKBWv94S6Scrs9VzpU-vQ?pwd=itch
提取码:itch
一、环境搭建
1、创建一个新的module
2、导入静态页面
3、导入依赖坐标
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.zhou</groupId> <artifactId>spring_ExampleTest</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.32</version> </dependency> <dependency> <groupId>c3p0</groupId> <artifactId>c3p0</artifactId> <version>0.9.1.2</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.10</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.0.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>5.0.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>5.0.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.0.5.RELEASE</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.0.1</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>javax.servlet.jsp-api</artifactId> <version>2.2.1</version> <scope>provided</scope> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.9.0</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.9.0</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>2.9.0</version> </dependency> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.1</version> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.3</version> </dependency> <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.2</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.7</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.0.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>5.0.5.RELEASE</version> </dependency> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> </dependencies> </project>
4、创建包结构
5、准备数据库环境
导入成功!
6、创建实体类
用户实体类
package com.itch.exercise.domain;public class User { private Long id; private String username; private String email; private String password; private String phoneNum; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getPhoneNum() { return phoneNum; } public void setPhoneNum(String phoneNum) { this.phoneNum = phoneNum; } @Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\'' + ", email='" + email + '\'' + ", password='" + password + '\'' + ", phoneNum='" + phoneNum + '\'' + '}'; }}
角色实体类
package com.itch.exercise.domain;public class Role { private Long id; private String roleName; private String roleDesc; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getRoleName() { return roleName; } public void setRoleName(String roleName) { this.roleName = roleName; } public String getRoleDesc() { return roleDesc; } public void setRoleDesc(String roleDesc) { this.roleDesc = roleDesc; } @Override public String toString() { return "Role{" + "id=" + id + ", roleName='" + roleName + '\'' + ", roleDesc='" + roleDesc + '\'' + '}'; }}
7、创建相关配置文件
1、创建log4j配置文件
2、创建jdbc.properties
3、创建applicationContext.xml
在spring的核心配置文件中我们只需要配置数据源和配置jdbc的模板对象
<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"> <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></beans>
4、创建spring-mvc.xml
在spring-mvc.xml文件中我们需要配置springMVC的注解驱动、视图解析器、静态资源访问权限的开放
<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"> <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 /></beans>
spring和Spring个mvc想集成到web项目中需要配置web.xml
5、web.xml
在web.xml中配置spring的监听器,springMVC的前端控制器
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <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></web-app>
二、功能实现
2.1、角色列表展示
需求:点击角色管理展示所有角色信息
思路:
①点击角色管理菜单发送请求到服务器端(修改角色管理菜单的url地址)
②创建RoleController和list()方法
③创建RoleService和list()方法
④创建RoleDao和findAll()方法
⑤使用JdbcTemplate完成查询操作
⑥将查询数据存储到modelAndView中
⑦转发到role-list.jsp页面进行展示
dao层
public interface RoleDao { public List<Role> findAllRole();}
public class RoleDaoImpl implements RoleDao { // 通过set注入jdbctemplate private JdbcTemplate jdbcTemplate; public void setJdbcTemplate(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } public List<Role> findAllRole() { // 定义sql String sql = "select * from sys_role"; // 执行sql List<Role> roleList = jdbcTemplate.query(sql, new BeanPropertyRowMapper<Role>(Role.class)); return roleList; }}
service层
public interface RoleService { public List<Role> findAllRole();}
public class RoleServiceImpl implements RoleService { // 通过set注入RoleDao private RoleDao roleDao; public void setRoleDao(RoleDao roleDao) { this.roleDao = roleDao; } public List<Role> findAllRole() { return roleDao.findAllRole(); }}
controller层
@Controller@RequestMapping("/role")public class RoleController { // 注入RoleService @Autowired private RoleService roleService; @RequestMapping("/list") public ModelAndView listRole(){ List<Role> roleList = roleService.findAllRole(); System.out.println(roleList); ModelAndView modelAndView = new ModelAndView(); // 设置模型 modelAndView.addObject("roleList",roleList); // 设置视图 modelAndView.setViewName("role-list"); // 返回ModelAndView return modelAndView; }}
前端代码
修改侧边栏得到请求路径
前端页面数据展示 role-list.jsp
引入jstl
配置相关文件
配置spring-mvc.xml开启组件扫描
<context:component-scan base-package="com.itch.test.controller" />
配置applicationContext.xml
<bean id="roleDao" class="com.itch.test.dao.impl.RoleDaoImpl"> <property name="jdbcTemplate" ref="jdbcTemplate"/></bean><bean id="roleService" class="com.itch.test.service.impl.RoleServiceImpl"> <property name="roleDao" ref="roleDao" /></bean>
部署测试
刷新页面
2.2、添加角色
需求:点击新建 创关键一个新的角色
dao层
/ * 添加角色 * @param role */public void saveRole(Role role);
public void saveRole(Role role) { String sql = "insert into sys_role values(null,?,?)"; jdbcTemplate.update(sql,role.getRoleName(),role.getRoleDesc());}
service层
/ * 添加角色 * @param role */public void saveRole(Role role);
public void saveRole(Role role) { roleDao.saveRole(role);}
controller层
controller层调用service层进行保存 重定向到list进行查询
@RequestMapping("/save")public String save(Role role){ roleService.saveRole(role); return "redirect:/role/list";}
前端代码
全局乱码过滤器
由于是使用post请求方式,所以存在乱码问题,配置全局乱码过滤器
<filter> <filter-name>encodingFilter</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>encodingFilter</filter-name> <url-pattern>/*</url-pattern></filter-mapping>
部署测试
2.3、删除角色
需求:点击删除按钮删除该角色
dao层
/ * 删除角色 * @param id 根据id删除角色 */public void deleteRole(int id);
public void deleteRole(int id) { String sql = "delete from sys_role where id = ?"; jdbcTemplate.update(sql,id);}
service层
/ * 删除角色 * @param id */public void deleteRole(int id);
public void deleteRole(int id) { roleDao.deleteRole(id);}
controller层
@RequestMapping("/delete")public String delete(String id){ int rid = Integer.parseInt(id); roleService.deleteRole(rid); return "redirect:/role/list";}
前端代码
部署测试
2.4、用户列表展示
需求:点击用户管理查询数据库 展示所有用户信息
思路:
①点击用户管理菜单发送请求到服务器端(修改用户管理菜单的url地址)
②创建UserController和list()方法
③创建UserService和list()方法
④创建UserDao和fifindAll()方法
⑤使用JdbcTemplate完成查询操作
⑥将查询数据存储到modelAndView中
⑦转发到user-list.jsp页面进行展示
编码:
dao层
public interface UserDao { / * 查询所有用户 * @return */ public List<User> findAllUser();}
public class UserDaoImpl implements UserDao { // 注入jdbctemplate private JdbcTemplate jdbcTemplate; public void setJdbcTemplate(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } public List<User> findAllUser() { String sql = "select * from sys_user"; List<User> userList = jdbcTemplate.query(sql, new BeanPropertyRowMapper<User>(User.class)); return userList; }}
service层
public interface UserService { / * 查找所有用户 * @return */ public List<User> findAllUser();}
public class UserServiceImpl implements UserService { // 注入userDao private UserDao userDao; public void setUserDao(UserDao userDao) { this.userDao = userDao; } public List<User> findAllUser() { return userDao.findAllUser(); }}
controller层
@Controller@RequestMapping("/user")public class UserController { @Autowired private UserService userService; @RequestMapping("/list") public ModelAndView list(){ List<User> userList = userService.findAllUser(); ModelAndView modelAndView = new ModelAndView(); modelAndView.addObject("userList",userList); modelAndView.setViewName("user-list"); return modelAndView; }}
配置文件
在spring核心配置文件application.xml中添加如下配置:
<bean id="userDao" class="com.itch.test.dao.impl.UserDaoImpl"> <property name="jdbcTemplate" ref="jdbcTemplate"/></bean><bean id="userService" class="com.itch.test.service.impl.UserServiceImpl"> <property name="userDao" ref="userDao" /></bean>
前端代码
部署测试
发现问题:用户具有的角色我们并不能够查出来,所以查询用户的时候关联查询出该用户所具有的所有角色信息,需要完善查询用户的service层代码
所以我们需要在业务层UserService中向每一个User封装角色信息roles
dao层处理简单业务 service层处理复杂业务
【1】给User实体类添加roles属性
【2】在UserService中完善代码
public List<User> findAllUser() { List<User> userList = userDao.findAllUser(); // 封装每一个user的roles数据 for (User user : userList) { Long id = user.getId();//获得每个用户的id // 将id作为参数查询出当前用户对应的具有的角色信息 根据userId查询出roleId 再根据roleId查询出角色信息 List<Role> roles = roleDao.findRolesById(id); // 将roles设置到user user.setRoles(roles); } return userList;}
这里我们需要在UserService中也注入roleDao,注意在配置文件中进行相应的注入。
【3】在RoleDao中添加根据id查询角色信息
/ * 根据id查询角色 * @param id * @return */ public List<Role> findRolesById(Long id);
public List<Role> findRolesById(Long id) { List<Role> roleList = null; try { String sql = "SELECT * FROM sys_role r,sys_user_role ur WHERE ur.`roleId` = r.`id` AND ur.`userId` = ?"; roleList = jdbcTemplate.query(sql, new BeanPropertyRowMapper<Role>(Role.class), id); } catch (DataAccessException e) { e.printStackTrace(); } return roleList; }
【4】修改前端代码
【5】部署测试
2.5、添加用户
第一步:查询角色信息展示
新建用户时,点击新建按钮先去到添加用户的页面user-add.jsp,在添加用户页面需要展示可供选择的角色信息,因此来到添加页面时需要查询所有的角色信息并展示。所以第一步需要查询出角色信息而不是直接跳转到新增个用户页面
dao层
在之前的角色管理中我们已经写了查询所有角色的dao实现,所以我们只需要使用就行
controller层
在userController中新增一个方法,是为了查询角色并展示到页面
@RequestMapping("/saveUserUI")public ModelAndView saveUserUI(){ ModelAndView modelAndView = new ModelAndView(); List<Role> roleList = roleService.findAllRole(); modelAndView.addObject("roleList",roleList); modelAndView.setViewName("user-add"); return modelAndView;}
前端代码
测试
第二步:添加用户功能实现
添加用户,需要向sys_user表中存放数据,也需要向sys_user_role表中存放数据
所以需要接收的参数一个是user 一个是选择的角色id们,添加用户时用户分配的角色信息应存储到中间表sys_user_role表中,需要用户的id,角色的id,而角色的id由前台页面点选的,用户的id应该是在保存操作由mysql主键自动生成的,那如何获取mysql自增的主键值呢?
controller层
@RequestMapping("/saveUser")public String saveUser(User user,Long[] roleIds){ userService.addUser(user,roleIds); return "redirect:/user/list";}
service层
public void addUser(User user, Long[] roleIds) { // 1、向sys_user表中存储数据 该方法的返回值是自增生成的主键id Long userId = userDao.addUser(user); // 2、向sys_user_role关系中间表中存储多条数据 映射用户id和角色 userDao.saveUserRoleRelation(userId,roleIds);}
这里发现在存放数据到sys_user表的时候,由于后续需要使用到自动生成的主键id,所以需要返回自动生成的主键id,那么关键问题就在于怎样返回自动生成的主键id呢?
其实jdbctemplate有一个API可以帮助我们返回生成的主键id,这个API相对比较复杂
通过自定义底层的preparestatement开启返回自动生成的主键id
所以dao层的代码编写如下;
dao层
添加用户的dao层操作:
public Long addUser(final User user) { // 1、创建PrepareStatementCreator PreparedStatementCreator creator = new PreparedStatementCreator(){ public PreparedStatement createPreparedStatement(Connection connection) throws SQLException { // 使用原始的jdbc完成一个preparestatement的创建 String sql = "isnert into sys_user values(?,?,?,?,?)"; PreparedStatement preparedStatement = connection.prepareStatement(sql,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; } }; // 2、创建keyHolder GeneratedKeyHolder keyHolder = new GeneratedKeyHolder(); jdbcTemplate.update(creator,keyHolder); // 3、通过keyholder获得生成的主键 long userId = keyHolder.getKey().longValue(); return userId;}
添加用户月角色映射的dao层操作:
public void saveUserRoleRelation(Long userId, Long[] roleIds) { // 向关系表中保存用户id对应的角色id for (Long roleId : roleIds) { jdbcTemplate.update("insert into sys_user_role values(?,?)",userId,roleId); }}
部署测试
2.6、删除用户
需求:点击删除按钮删除该用户
思路:
①点击用户列表的删除按钮,发送请求到服务器端
②编写UserController的del()方法
③编写UserService的del()方法
⑤编写UserDao的delUserRoleRel()方法
⑥跳回当前用户列表页面
完成用户的删除操作,不仅要删除用户表数据,同时需要将用户和角色的关联表数据进行删除
dao层
/ * 删除用户 * @param userId */public void deleteUser(Long userId);/ * 删除用户与角色的关系 * @param userId */public void deleteRelation(Long userId);
public void deleteUser(Long userId) { String sql = "delete from sys_user where id = ?"; jdbcTemplate.update(sql, userId);}public void deleteRelation(Long userId) { String sql = "delete from sys_user_role where userId = ?"; jdbcTemplate.update(sql,userId);}
service层
public void deleteUser(Long uid);
public void deleteUser(Long uid) { // 要先删除关系表 userDao.deleteRelation(uid); // 再删除user表 userDao.deleteUser(uid);}
controller层
@RequestMapping("/delete/{uid}")public String deleteUser(@PathVariable("uid") Long id){ userService.deleteUser(id); return "redirect:/user/list";}