昨天我们实现了多表关联查询,还有分页显示数据的功能。那么今天我们要继续完善用户管理这一模块。
可以好好回想一下,前后端数据传递的知识(view怎么通过表单把数据传给controller端,controller端怎么通过model把数据传给view端)
现在我们要优化一下,我们的项目结构,删除一些多余的测试页面和测试映射
已删除,这里不展示图片和过程,文章最新的项目文件夹会去掉这些。
需求图如上,这里的话,我们要实现日期框架的引入,还要在输入的时候就对后端进行一个查询,也就是数据验证的功能。这里需要我们使用前端+Ajax方法实现。
熟悉pojo->dao->service->controller->view的过程
<insert id="addUser" parameterType="User" keyProperty="id" >
insert into user(userCode,userName,userPassword
<if test="gender!=null and gender!=0" >
,gender
if>
<if test="birthday!=null">
,birthday
if>
<if test="phone!=null and phone!=''">
,phone
if>
<if test="address!=null and address!=''">
,address
if>
<if test="userRole!=null and userRole!=0">
,userRole
if>
<if test="createdBy!=null and createdBy!=0">
,createdBy
if>
<if test="creationDate!=null">
,creationDate
if>
)
values (#{userCode},#{userName},#{userPassword}
<if test="gender!=null and gender!=0" >
,#{gender}
if>
<if test="birthday!=null">
,#{birthday}
if>
<if test="phone!=null and phone!=''">
,#{phone}
if>
<if test="address!=null and address!=''">
,#{address}
if>
<if test="userRole!=null and userRole!=0">
,#{userRole}
if>
<if test="createdBy!=null and createdBy!=0">
,#{createdBy}
if>
<if test="creationDate!=null">
,#{creationDate}
if>
)
insert>
这里使用了动态SQL,注意日期型不要进行!=’’判断。(上面的birthday和creationDate),否则在IDEA中会出现invalid comparison: java.util.Date and java.lang.String
错误
//新增用户
public int addUser(User user)throws Exception;
说明:上面我们加上了异常处理throw Exception,不加也可以,但是一般建议增删改最好加上异常处理, 因为增删改经常会有失败的时候。
基本同UserMapper接口一致,也可不一致,可以自己编写方法名和返回类型以及方法体,这里返回值为Boolean用于判断是否新增成功。
//新增用户,返回boolean类型用于判断是否新增成功
public Boolean addUser(User User) throws Exception;
@Override
public Boolean addUser(User user) throws Exception {
try{
int count=userMapper.addUser(user);
if (count>0){
return true;
}else {
return false;
}
}catch (RuntimeException e){
e.printStackTrace();
throw e;
}
}
这段代码的意思是,若是插入成功那么会返回一条记录就必定大于1,那么就插入成功返回true结果,反之则反。
@RequestMapping("/useradd")
public String showUserAddPage(){
logger.info("欢迎来到新增用户页面");
return "useradd";
}
@RequestMapping(value = "/useraddsave",method = RequestMethod.POST)
public String doUserAdd(User user,HttpSession session) throws Exception {
//添加用户表的createBy值
user.setCreatedBy(((User)session.getAttribute("user")).getId());
//添加用户表的createdDte值
user.setCreationDate((new Date()));
if(userService.addUser(user)==true){//如果添加成功就返回
return "redirect:/userlist";
}
return "useradd";//添加不成功则返回注册界面
}
说明:在doUserAdd()方法中,前台传入的user对象入参调用user Service的addUser()方法,实现数据保存。保存成功后,需要重定向到用户列表页 userlist;若保存失败,则继续留在新增页。
PS:在进行新增用户的保存操作时,需设置createdBy和creationDate两个字段,分别为当前登录用户id和系统当前时间。
<%--
Created by IntelliJ IDEA.
User: Administrator
Date: 2023/9/17
Time: 9:26
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@include file="/WEB-INF/pages/common/head.jsp"%>
你现在所在的位置是:
注册页面 >> 用户注册
<%@include file="/WEB-INF/pages/common/foot.jsp" %>
添加用户
如下图:
打开pojo->User.java文件,在出生日期的上面添加注解,并import相应的包。
这一步的操作是为了让页面传递回来的时间类型数据与我们设定的保持一致,这样就能在Controller中被接收。
@DateTimeFormat(pattern="yyyy-MM-dd")
private java.util.Date birthday;
用户输入数值时,我们需要验证对方输入的是否正确,这时就要用到数据验证。数据验证通常用前端或前端加Ajax方法实现。
我们在webapp->statics->js->useradd.js中用js进行了验证,里面大部分是前端知识,使用了正则表达式进行验证数据是否合法。
其中对用户代码Usercode和用户角色UserRole的验证比较特殊,我们需要验证这用户代码Usercode是否和以前的重复了, UserRole是否是Role表中有的id,对于这个我们采用了异步Ajax验证的方式,要使用Json数据传。
<dependency>
<groupId>com.alibabagroupId>
<artifactId>fastjsonartifactId>
<version>1.2.47version>
dependency>
PS:我们在登录的时候有一个方法 getUserByUserCode (),它可以根据用户输入的userCode读取用户的值,因此我们使用它就行,不需要另外添加dao层代码。(注意dao层的代码尽量重复使用)
//判断用户是否存在
public User selectUserCodeExist(String userCode);
@Override
public User selectUserCodeExist(String userCode) {
User user = null;
try {
user = userMapper.getUserByUserCode(userCode);
} catch (Exception e) {
e.printStackTrace();
}
return user;
}
代码解释:根据userCode读取是不是有用户存在,如果有返回值,表示已经有这个用户名了,没有就表示没有该用户名,可以添加。
打开controller->UserController.java类,
**import com.alibaba.fastjson.JSON;**先在上方import区确定添加了fastjson;
再增加通过用户名(userCode)进行同名验证的处理方法,代码如下
//判断是否存在userCode
@RequestMapping(value="/ucexist")
@ResponseBody
public Object ucexist(@RequestParam String userCode){
String data="{\"userCode\":\"noexist\"}"; //初始化字符串
if(userCode==null||userCode.length()==0){ //如果userCode是空值
data="{\"userCode\":\"exist\"}"; //空值直接返回已存在
}
else{
User user = userService.selectUserCodeExist(userCode);
if(user!=null)
data="{\"userCode\":\"exist\"}";
else
data="{\"userCode\":\"noexist\"}";
}
return JSONArray.toJSONString(data);//将data转为json对象,并将结果发回给当前页面
}
说明:在上述代码中,控制器的处理方法userCodeIsExit()通过前台传递过来的userCode进行入参,最后返回Object。在方法体内,调用后台的user Service.selectUserCode Exist(userCode)进行同名验证,并返回验证的结果user对象。若user为空,就证明没有重名,新增用户名可用;反之,则表示该用户名已存在,不可用。对于验证结果,我们把它放在一个Json变量里,里面只有一个键值 userCode, 它只有两个值:exist或noexist,通过调用JSONArray.to JSONString()方法,将其转换为JSON对象,进行返回输出。
PS:在该处理方法上,除了通过@Request Mapping指定请求的URL,还有一个@Response Body注解。该注解的作用是将标注该注解的处理方法的返回结果直接写入HTTP Response Body(Response对象的body数据区)中。一般情况下,@Response Body都会在异步获取数据时使用,被其标注的处理方法返回的数据将输出到响应流中,由客户端获取并显示数据。
**由于Json的key值必须要双引号,不能是单引号,因此我们在双引号的里面再写双引号时,需要加上一个/这个转义符:**
String data="{\"userCode\":\"noexist\"}"; //初始化字符串
简单地说,如果在双引号里还要加双引号,就要在内部的双引号前面加一个\
这时可以运行网站,输入网址ucexis并用?号给userCode赋参数,查看JSON数据结果:
在完成上一步控制器的处理方法之后,需要对前台页面以及js进行相应的调整,通过JQuery来进行异步请求的调用,以及对调用之后后台控制器处理方法返回的结果进行相应的数据展现。
修改useradd.js,加上下面的代码:
将请求的url改为**/ucexist**:
并在下面的69行下面加多一行,将字符转为JSON对象:
var data=$.parseJSON(data);//将字符串data解析为标准json对象
说明:在上述代码中,在新增用户页面完成用户编码(user Code)的输入之后,即用户编码输入框中的鼠标失去焦点时,进行Ajax异步验证,请求URL“/ ucexist”,请求参数为用户输入的user Code的值。异步调用请求之后,返回的数据类型为JSON类型,若调用成功,则根据返回的JSON对象,提示相应的信息。
下载My97DatePicker.zip(我的资源文件里面会有压缩包),项目文件里面已经是配套好的了
只需要复制压缩包下的文件到webapp下,然后引入WdatePicker.js即可
<input id="d11" type="text" onClick="WdatePicker({el:this})"/>
保存运行,由于我们修改了js文件,最好先清理一下浏览器的缓存,再重新运行。
用管理员admin登录之后,进入用户管理的用户添加页面,故意添加一个已经存在的用户,比如admin,当光标移走之后,看是否验证成功
数据库也写入了,那么新增用户的功能已经实现了。并且实现了日期插件。
找到common.js找到资格图片路径,修改成自己项目的图片路径即可。
找到useradd.jsp进行如下修改:
并且出生日期这一栏,禁止手动输入,只能通过选择时间来进行输入。
思路原理是:
(1) 根据ID获取用户的数据,将用户原来的数据显示出来。
(2) 用户根据显示的数据进行修改,点保存后将数据存回数据库。
<select id="getUserById" resultMap="UserWithRoleName" parameterType="String">
select u.*,r.*
from user u,role r where u.id=#{id} and u.userRole = r.id
select>
<update id="modify" parameterType="User">
update user
<set>
<if test="userCode != null">userCode=#{userCode},if>
<if test="userName != null">userName=#{userName},if>
<if test="userPassword != null">userPassword=#{userPassword},if>
<if test="gender != null">gender=#{gender},if>
<if test="birthday != null">birthday=#{birthday},if>
<if test="phone != null">phone=#{phone},if>
<if test="address != null">address=#{address},if>
<if test="userRole != null">userRole=#{userRole},if>
<if test="modifyBy != null">modifyBy=#{modifyBy},if>
<if test="modifyDate != null">modifyDate=#{modifyDate}if>
set>
where id = #{id}
update>
注意第一个映射的参数要为String,不能写为int,因为后面需要用它来进行参数传递,网页上获取参数要用String
//根据用户ID获取用户信息
public User getUserById(String id)throws Exception;
//修改用户信息
public int modify(User user)throws Exception;
//根据用户ID获取用户信息
public User getUserById(String id);
//修改用户信息
public boolean modify(User user);
@Override
public User getUserById(String id) {
User user=null;
try{
user=userMapper.getUserById(id);
}
catch (Exception e) {
e.printStackTrace();
user = null;
}
return user;
}
@Override
public boolean modify(User user) {
boolean result=false;
try {
int count=userMapper.modify(user);
if(count>0) //如果添加成功就返回true
return true;
else
return false;//如果添加失败就返回true
}
catch (Exception e) {
e.printStackTrace();
}
return result;
}
@RequestMapping(value="/usermodify")
public String getUserById(@RequestParam String uid,Model model){
User user = userService.getUserById(uid);
model.addAttribute(user);
return "usermodify";
}
@RequestMapping(value="/usermodifysave",method=RequestMethod.POST)
public String modifyUserSave(User user,HttpSession session){
user.setModifyBy(((User)session.getAttribute("user")).getId());
user.setModifyDate(new Date());
if(userService.modify(user)){
return "redirect:/userlist";
}
return "usermodify";
}
代码说明:上述代码中getUserID处理方法主要通过参数uid(用户id)来获取相应的user对象(调用后台user Service的方法实现),并放入Model中,最后返回逻辑视图名“usermodify”,进入到用户修改界面。
modifyUserSave处理方法的入参对象为前台传入的user对象,调用后台userService的modify()进行相应用户信息的修改保存。若保存成功,直接重定向到用户列表页;若保存失败,则返回逻辑视图名“usermodify”,进入到用户修改界面
打开WEB-INF/pages文件夹,添加jsp文件usermodify.jsp
<%--
Created by IntelliJ IDEA.
User: Administrator
Date: 2023/9/20
Time: 14:42
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@include file="/WEB-INF/pages/common/head.jsp"%>
你现在所在的位置是:
用户管理页面 >> 用户修改页面
<%@include file="/WEB-INF/pages/common/foot.jsp" %>
这个的点击事件位于,前端的webapp->statics->js->userlist.js中定义的,因此找到打开。
记得修改后要清除浏览器缓存,重新运行服务。
选择性别为男,点击保存确认更改后,查看是否更改成功。
可以看到正确修改了,并且数据库也能看到。
因为我们外面显示的信息很少,因此要想看到其他更多信息,就得点击进行一个查看。
查看用户的操作跟修改用户差不多,只是去掉保存功能。
前面我们也提及了dao层中的方法最好就复用,因此
//查看用户
@RequestMapping(value="/userview")
public String view(@RequestParam String uid,Model model){
User user = userService.getUserById(uid);
model.addAttribute(user);
return "userview";
}
打开webapp>WEB-INF-jsp文件夹,添加jsp文件userview.jsp
<%--
Created by IntelliJ IDEA.
User: Administrator
Date: 2023/9/17
Time: 9:26
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@include file="/WEB-INF/pages/common/head.jsp"%>
你现在所在的位置是:
注册页面 >> 用户注册
<%@include file="/WEB-INF/pages/common/foot.jsp" %>
这个的点击事件位于,前端的webapp->statics->js->userlist.js中定义的,因此找到打开。
可以看到正确展示了所有的用户信息,但是呢,这一串出生日期是不是看着很怪,这是一种CST格式的展示形式。
我们可以在,userview.jsp中在头部先加入一这串代码
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
然后我们找到出生日期那一栏,将
出生日期:${user.birthday }
修改成如下⬇
出生日期:
然后保存,清理浏览器缓存,重新运行项目即可正常显示。
如我们预期的一样展示了信息。
删除用户我们也使用前后端传递json数据实现
<delete id="deleteUserById" parameterType="int">
delete from user where id=#{id}
delete>
//删除某一用户
public int deleteUserById(int id) throws Exception;
//删除某一用户
public boolean deleteUserById(int id);
@Override
public boolean deleteUserById(int id) {
boolean result = false;
try {
if(userMapper.deleteUserById(id) > 0)
result = true; //删除成功
else
result=false; //删除失败
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
//删除用户数据
@RequestMapping(value="/deluser")
@ResponseBody
public Object deluser(@RequestParam int uid){
String data="{\"delResult\":\"false\"}"; //初始化字符串
boolean result= userService.deleteUserById(uid);
if(result==true)
data="{\"delResult\":\"true\"}"; //删除成功
else
data="{\"delResult\":\"false\"}"; //删除失败
return JSONArray.toJSONString(data);//将data转为json对象,并将结果发回给当前页面
}
进行如下修改,修改链接,并且加上这一行代码
var data=$.parseJSON(data);//将字符串data解析为标准json对象
然后,清理浏览器缓存,重新运行服务查看,是否满足预期需求。
可以看到删除后总数就变成了10条记录,那就是俩页,没有问题。完美解决。
我们今天完成了使用前端和Ajax进行数据传输验证,其他页面基本上功能都是相似的,用作SSM的练手项目。完成了WdatePicker.js时间⽇期插件的引入使用,用户管理功能的增删改查,各个操作按钮的组件绑定对应的网址映射,对应的操作页面,对数据库的查询显示,格式化字符串,如何处理JSON数据等都有了一定的了解。
在这整个JAVA项目的开发中,这个项目属于面向综合项目实战,难度较难,需要用到的知识有:JAVA程序设计,MYSQL数据库开发,网页设计, HTML+CSS+JAVAScript+JQuery响应式开发,JSP开发等知识。通过今天的学习,希望各位读者可以对整体项目开发流程有个大致的了解,为框架开发打下坚实基础。
想要跟着学习的可以去我的资源里面找对应的文件下载,我的md文件也会发上去,项目文件会上传可以自己跟着学习一下。(ps:这个项目的开发应该还有一篇文章需要发布,介绍一个整体的流程)
作者:Stevedash
发表于:2023年9月21日 19点57分