1. Spring练习环境搭建
1.1 Spring环境搭建步骤
- 1、创建工程(Project&Module)
- 2、导入静态页面(见资料jsp页面)
- 3、导入需要的坐标(见资料中的pom.xml)
- 4、创建包结构(controller、service、dao、domain、utils)
- 5、导入数据库脚本(见资料test.sql)
- 6、创建POJO类(见资料User.java和Role.java)
- 7、创建配置文件(applicationContext.xml、spring-mvc.xml、jdbc-properties、log4j.properties)
工程结构
页面素材链接:https://gitee.com/LChengxin/spring-exercises.git
pom.xml需要的坐标
<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>
数据库脚本test.sql
/*
SQLyog Ultimate v12.09 (64 bit)
MySQL - 5.7.24-log : Database - test
*********************************************************************
*/
/*!40101 SET NAMES utf8 */;
/*!40101 SET SQL_MODE=''*/;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
CREATE DATABASE /*!32312 IF NOT EXISTS*/`test` /*!40100 DEFAULT CHARACTER SET utf8 */;
USE `test`;
/*Table structure for table `sys_role` */
DROP TABLE IF EXISTS `sys_role`;
CREATE TABLE `sys_role` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`roleName` varchar(50) DEFAULT NULL,
`roleDesc` varchar(50) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
/*Data for the table `sys_role` */
insert into `sys_role`(`id`,`roleName`,`roleDesc`) values (1,'院长','负责全面工作'),(2,'研究员','课程研发工作'),(3,'讲师','授课工作'),(4,'助教','协助解决学生的问题');
/*Table structure for table `sys_user` */
DROP TABLE IF EXISTS `sys_user`;
CREATE TABLE `sys_user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`username` varchar(50) DEFAULT NULL,
`email` varchar(50) DEFAULT NULL,
`password` varchar(80) DEFAULT NULL,
`phoneNum` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
/*Data for the table `sys_user` */
insert into `sys_user`(`id`,`username`,`email`,`password`,`phoneNum`) values (1,'zhangsan','zhangsan@itcast.cn','123','13888888888'),(2,'lisi','lisi@itcast.cn','123','13999999999'),(3,'wangwu','wangwu@itcast.cn','123','18599999999');
/*Table structure for table `sys_user_role` */
DROP TABLE IF EXISTS `sys_user_role`;
CREATE TABLE `sys_user_role` (
`userId` bigint(20) NOT NULL,
`roleId` bigint(20) NOT NULL,
PRIMARY KEY (`userId`,`roleId`),
KEY `roleId` (`roleId`),
CONSTRAINT `sys_user_role_ibfk_1` FOREIGN KEY (`userId`) REFERENCES `sys_user` (`id`),
CONSTRAINT `sys_user_role_ibfk_2` FOREIGN KEY (`roleId`) REFERENCES `sys_role` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
/*Data for the table `sys_user_role` */
insert into `sys_user_role`(`userId`,`roleId`) values (1,1),(1,2),(2,2),(2,3);
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
domain下创建POJO类(User.java和Role.java)
User.java
package com.abner.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 + '\'' +
'}';
}
}
Role.java
package com.abner.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 + '\'' +
'}';
}
}
创建配置文件(applicationContext.xml、spring-mvc.xml、jdbc-properties、log4j.properties)
applicationContext.xml、spring-mvc.xml暂时不配置
jdbc-properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test
jdbc.username=root
jdbc.password=root
log4j.properties(主要是用来消除项目启动时的警告)
### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
### direct messages to file mylog.log ###
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=c:/mylog.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
### set log levels - for more verbose logging change 'info' to 'debug' ###
log4j.rootLogger=info, stdout
在web.xml文件中配置监听器、前端控制器、
<?xml version="1.0" encoding="UTF-8"?>
<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>
<!--spring的监听器-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!--springMVC的前端控制器-->
<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>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
配置spring-mvc.xml
首先引用一下mvc的命名空间,因为需要用到命名空间内部的标签。
xmlns:mvc="http://www.springframework.org/schema/mvc"
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
配置mvc注解驱动、视图解析器(在视图解析器中声明前缀和后缀那么我们在请求方法中返回时只需要返回页面的名字,而不需要页面的路径(前缀)和后缀,例如某个页面是/aaa/bb.jsp,我们只需要返回bb)、静态资源权限开放(放行js,css,图片等静态资源,访问时sprig-mvc的前端控制器DispatcherServlet不能帮我访问到资源,那么就交由默认缺省的Servlet帮我完成静态资源的返回)
例如我们把鼠标放到某个我们要访问的地方,左下角就会有访问的请求地址,当我们点击角色管理时,我们只需要在方法中返回role-list
<!--1、配置mvc注解驱动-->
<mvc:annotation-driven/>
<!--2、配置视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/pages/"/><!--前缀-->
<property name="suffix" value=".jsp"/><!--后缀-->
</bean>
<!--3、静态资源权限开放-->
<mvc:default-servlet-handler/>
配置applicationContext.xml文件
首先引用context命名空间
xmlns:context="http://www.springframework.org/schema/context"
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
加载jdbc.properties,在容器中注入数据源和jdbc模板对象
<!--1、加载jdbc.properties-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!--2、数据源-->
<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>
<!--3、配置jdbc模板对象-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
2.角色列表的展示和添加操作
2.1 角色列表的展示步骤分析
- 1、点击角色管理菜单发送请求到服务器(修改角色管理菜单的url地址)
- 2、创建RoleController和showList()方法
- 3、创建RoleService和showList()方法
- 4、创建RoleDao和findAll()方法
- 5、使用JdbcTemplate完成查询操作
- 6、将查询数据存储到Model中
- 7、转发role-list.jsp页面进行展示
在我们启动项目后,按道理来说应该是去到index页面,那为什么是去到main.jsp页面呢?
查看我们的index页面后发现,当我们启动后确实来到了index页面,只不过index页面中的这段代码帮我们重定向到了main页面。
接下来我们看看main.jsp页面
可以看到有引入的头部、侧边导航栏和内容区域。
我们对角色和用户的管理都是在侧边的导航栏,所以我们去侧边导航栏的页面aside.jsp页面查看
当我们点击用户管理或者角色管理时,我们应该请求页面应该是Controller方法中的@RequestMapping中的映射地址
即改成这样
和Controller方法中的映射是一样的
- RoleController代码(返回值类型统一为ModelAndView类型)
package com.abner.controller;
import com.abner.domain.Role;
import com.abner.service.RoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import java.util.List;
@RequestMapping("/role")
@Controller
public class RoleController {
@Autowired
private 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;
}
}
RoleController中的list方法调用业务层RoleService中的list方法,list方法中把在业务层中获取到的泛型为Role类型的List添加到Model中,设置role-list.jsp为View。在Controller层中我们使用注解的方式自动注入RoleService,在其它层的注入采用配置文件注入。
RoleController使用注解产生Bean,需要在spring-mvc.xml文件中配置组件扫描
<!--4、组件扫描,扫描controller层-->
<context:component-scan base-package="com.abner.controller"/>
要使RoleService 自动注入到Controller层,我们要在Spring IOC容器中注入RoleService 的Bean
业务层中的list方法调用Dao层中的findAll,返回值为Role类型的List。Service层内部需要调用Dao层,RoleDao也许需要注入到Service层中,这个Dao层对象也是IOC容器提供的,所以我们也需要在applicationContext.xml中注入
- RoleServiceImpl代码
package com.abner.service.Impl;
import com.abner.dao.RoleDao;
import com.abner.domain.Role;
import com.abner.service.RoleService;
import java.util.List;
/**
* 业务层
*/
public class RoleServiceImpl implements RoleService {
private RoleDao roleDao;
public void setRoleDao(RoleDao roleDao) {
this.roleDao = roleDao;
}
@Override
public List<Role> list() {
List<Role> roleDaoAll = roleDao.findAll();
return roleDaoAll;
}
}
- RoleDaoImpl代码
package com.abner.dao.Impl;
import com.abner.dao.RoleDao;
import com.abner.domain.Role;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import java.util.List;
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;
}
}
在applicationContext.xml文件中添加:
<!--配置roleService-->
<bean id="roleService" class="com.abner.service.Impl.RoleServiceImpl">
<property name="roleDao" ref="roleDao"/>
</bean>
<!--配置roleDao-->
<bean id="roleDao" class="com.abner.dao.Impl.RoleDaoImpl">
<property name="jdbcTemplate" ref="jdbcTemplate"/>
</bean>
Dao层的实现需要依靠JdbcTemplate模板对象,所以JdbcTemplate对象也需要在IOC容器中,在上面的工作中我们已经注入。然后把JdbcTemplate注入到Dao层。
页面的展示
我们要把从数据库中查询到的数据在页面中展示,我们需要修改页面,数据是存在ModelAndView中的,然后转发这个页面,这也页面需要取到这个数据进行展示,使用jstl+EL在jsp页面中取到数据for循环进行展示。
在role-list页面中引用jstl标签库
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
找到数据展示的地方,把多余的删掉,留下一个,用for循环输出展示
<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>
c:forEach items="${roleList}" var="role"
的作用相当于for循环,把Controller方法中用ModelAndView封装到的数据取出来赋值给item,var = 'role’就是接受item中的每一个元素相当于java代码中的for(User role: item )。
启动服务
数据展示成功。
2.2 角色的添加
角色的添加效果
角色添加的步骤分析
- 1、点击列表页面新建按钮跳转到角色添加页面
- 2、输入角色信息,点击保存按钮,表单数据提交服务器
- 3、编写RoleController的save()方法
- 4、编写RoleService的save()方法
- 5、编写RoleDao的save方法
- 6、使用JdbcTemplate保存Role数据到sys_role
- 7、跳转回角色列表页面
找到role-add.jsp页面,找到表单项
可以看到,表单提交的参数中和Role中的属性名一致,所以我们在RoleController中的save方法用参数Roler类型接收,调用Service层更新信息后从定向到角色管理的展示页面
- RoleController中的save方法
@RequestMapping("/save")
public String save(Role role){
roleService.save(role);
return "redirect:/role/list";
}
- RoleServiceImpl中的save方法,调用Dao层进行更新操作
@Override
public void save(Role role) {
roleDao.save(role);
}
- RoleDaoImpl中的save方法
@Override
public void save(Role role) {
jdbcTemplate.update("insert into sys_role values (?,?,?)",null,role.getRoleName(),role.getRoleDesc());
}
由于表单提交方式为post,而post提交方式有中文乱码问题,所以我们需要在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>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
展示效果
3. 用户列表的展示和添加操作
3.1 用户列表展示效果
用户列表的展示和角色列表差不多,不同的地方是在展示用户管理页面的时候,每个用户具有不同的角色,而这一列信息不再用户表中
这个时候就涉及到多表的查询,多表查询稍微复杂,而Dao层值一般负责比较简单的查询,所以我们要把复杂的查询放到service层(业务层)
在User类中添加角色列表属性,并创建get个set方法
//当前用户具备哪些角色
private List<Role> roles;
public List<Role> getRoles() {
return roles;
}
public void setRoles(List<Role> roles) {
this.roles = roles;
}
首先我们在Dao层中把所有的用户查询出来
- UserDaoImpl代码
package com.abner.dao.Impl;
import com.abner.dao.UserDao;
import com.abner.domain.User;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import java.util.List;
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;
}
}
在service层中,用查询出来的用户的id通过中间表sys_user_role查询sys_role表,然后把查询出来的前User Id对应的Role集合数据封装到每一个User中
- UserServiceImpl 代码
package com.abner.service.Impl;
import com.abner.dao.RoleDao;
import com.abner.dao.UserDao;
import com.abner.domain.Role;
import com.abner.domain.User;
import com.abner.service.UserService;
import java.util.List;
/**
* Dao层只负责比较简单的业务查询,业务层负责复杂的业务
*/
public class UserServiceImpl implements UserService {
private UserDao userDao;
private RoleDao roleDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void setRoleDao(RoleDao roleDao) {
this.roleDao = roleDao;
}
@Override
public List<User> list() {
List<User> userList = userDao.findAll();
//封装userList中的每一个User的roles数据
for (User user : userList) {
//获得user的id
Long id = user.getId();
//将Id作为参数查询当前User Id对应的Role集合数据
List<Role> roles = roleDao.findRoleByUserId(id);
user.setRoles(roles);
}
return userList;
}
}
我们在roleDao中添加方法findRoleByUserId,将roleDao注入到UserServiceImpl 中
- applicationContext.xml文件中添加
<!--配置userService-->
<bean id="userService" class="com.abner.service.Impl.UserServiceImpl">
<property name="userDao" ref="userDao"/>
<property name="roleDao" ref="roleDao"/>
</bean>
- RoleDaoImpl中添加方法
@Override
public List<Role> findRoleByUserId(long id) {
List<Role> roles = jdbcTemplate.query(
"select id,roleName,roleDesc from sys_role r join sys_user_role ur on r.id=ur.roleId where ur.userId=?",
new BeanPropertyRowMapper<Role>(Role.class), id);
return roles;
}
- UserController代码
package com.abner.controller;
import com.abner.domain.User;
import com.abner.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import java.util.List;
@RequestMapping("/user")
@Controller
public class UserController {
@Autowired
private UserService userService;
@RequestMapping("/list")
public ModelAndView list(){
ModelAndView modelAndView = new ModelAndView();
List<User> userList = userService.list();
//设置模型
modelAndView.addObject("userList", userList);
//设置视图
modelAndView.setViewName("user-list");
return modelAndView;
}
}
- jsp页面中用for循环展示
<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">
<c:forEach items="${user.roles}" var="role">
${role.roleName}
</c:forEach>
</td>
<td class="text-center">
<a href="javascript:void(0);" class="btn bg-olive btn-xs">删除</a>
</td>
</tr>
</c:forEach>
</tbody>
展示效果
3.2 用户添加
在用户添加页面中,我们需要准备一些数据
就是用户角色这里的数据,因为角色表有维护的过程,可能添加或删除某些角色,所以我们必须通过对数据库的查询出角色表里有什么样的角色然后进行展示,不能够写死。
在点击新建时,不能直接跳页面,点新建时要访问UserController中的一个方法,最终返回的是用户角色,让用户角色在新建页面动态展示
在user-list.jsp中找到新建按钮的标签
让他发送请求到UserController,UserController处理后再跳转到新建用户保存页面
在UserController注入 RoleService 并添加saveUI方法
@Autowired
private RoleService roleService;
@RequestMapping("/saveUI")
public ModelAndView saveUI(){
ModelAndView modelAndView = new ModelAndView();
List<Role> roleList = roleService.list();
modelAndView.addObject("roleList",roleList);
modelAndView.setViewName("user-add");
return modelAndView;
}
修改user-add.jsp页面中展示用户角色的部分,用for循环展示
<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>
展示结果
接下来就是插入数据的操作
表单出的请求地址是/user/save,所以我们在UserController中创建方法save,同样添加完用户后重定向到user/list。
由于表单中user表的数据和user_role中的数据是分开的,所以我们在Controller的方法中也要单独封装,所以在save方法参数中,User用来接收user表的数据,Long类型的数组接收所勾选到的角色的roleId
@RequestMapping("/save")
public String save(User user,Long[] roleIds){
userService.save(user,roleIds);
return "redirect:/user/list";
}
- UserServiceImpl中的save方法
@Override
public void save(User user, Long[] roleIds) {
userDao.save(user,roleIds);
}
- UserDaoImpl中的save方法
@Override
public void save(User user, Long[] roleIds) {
//创建PreparedStatementCreator
PreparedStatementCreator creator = new PreparedStatementCreator() {
@Override
public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
//使用原始的jdbc完成一个PreparedStatement的组建
PreparedStatement preparedStatement = connection.prepareStatement("insert into sys_user values (?,?,?,?,?)", PreparedStatement.RETURN_GENERATED_KEYS);//PreparedStatement.RETURN_GENERATED_KEYS的值是1,作用是指定生成主键
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;
}
};
//创建KeyHolder
GeneratedKeyHolder keyHolder = new GeneratedKeyHolder();
//插入user表并获取自动生成的id
jdbcTemplate.update(creator,keyHolder);//会把生成的主键封装到keyHolder中
//获得生成的主键
long userId = keyHolder.getKey().longValue();
//2、向sys_user_role表中存储多条数据
for (Long roleId : roleIds) {
jdbcTemplate.update("insert into sys_user_role values (?,?)",userId,roleId);
}
}
由于user表的id是自动生成的,所以我们通过以上方法获取到自动生成的id。
4. 删除用户操作
1、在删除按钮添加鼠标点击事件
当鼠标点击时,执行函数delUser(),并以userId作为参数,在头部添加script标签执行脚本
<script>
function delUser(userId) {
if(confirm("您确认要删除吗")){//点击确认使confirm返回的是true
//发请求
location.href="${pageContext.request.contextPath}/user/del/"+userId
}
}
</script>
当鼠标点击删除按钮时就会执行该函数
当点击确定时,该函数就会发送请求到服务端,请求的参数用Restful风格传到服务端,UserController执行请求方法,对数据库进行操作后重定向到用户展示页面
@RequestMapping("/del/{userId}")
public String del(@PathVariable("userId") Long userId){
userService.del(userId);
return "redirect:/user/list";
}
Controller层调用Service层方法
@Override
public void del(Long userId) {
//1、删除关系表
userDao.delUserRoleRel(userId);
//2、删除user表
userDao.delUser(userId);
}
由于关系表有外键约束,所以我们要先删除关系表,然后再删除用户表
Service层调用Dao层方法
@Override
public void delUserRoleRel(Long userId) {
jdbcTemplate.update("delete from sys_user_role where userId = ?",userId);
}
@Override
public void delUser(Long userId) {
jdbcTemplate.update("delete from sys_user where id = ?",userId);
}
Dao层使用JdbcTemplate模板方法更新数据库
删除成功