SSM实战之商品信息管理系统《二》
1.前言
本系统属于SSM的常用功能整合使用练习。
涉及到SSM框架整合+前端框Bootstrap+Ajax校验+登录拦截器+图片文件上传+日期类型转换器+json格式传参等常用功能的使用。
上一篇点这里 完成了ssm的整合以及写了一个login.jsp页面,引入了Bootstrap和jquery。
下面开始完善登录功能。
使用ajax提交json数据,使用date日期类型转换器来完成登录功能。
2.SSM实战之登录功能完善
- 登录原理:我们在登录的时候,前端需要让你输入账户和密码,然后后台接收到这个数据以后,通过一层一层的传递,最后传到数据库当中,跟存储的数据进行对比。如果正确,那么你就登录成功。如果错误那么返回给你错误提示。
那么既然要跟数据库打交道了,我们就需要从底往上写。
不懂的可以参考:SSM框架下web项目运行流程
实现登录模块:
一. entity实体类:对应数据库表的字段,
生成getset方法并且写重定向tostring和重构父类。
二. Dao层接口:声明数据库操作方法
查询登录账户CheckLoginAndPwd方法
添加账号addUser方法。
三. mapper映射文件-写sql语句。
Id对应dao方法名:一个增加语句一个查询语句的sql。
四. service服务层:实现业务逻辑控制。
继续声明dao层的方法名。
五. Impl实现层:实现服务层里面的方法。
注解为service,实现接口,声明dao层对象,
写对应方法的返回值,dao对象来调用自身的方法。
六. Controller控制层:实现业务流程控制
声明注解controller,添加映射注解@RequestMapping,
指明当前路径URL。声明实体类对象。写对应的路径下的实现方法和控制信息。
七. 写前端view视图:login.jsp文件
引用json和ajax传递登录参数。
八. 写一个日期转换的工具类。
让涉及到日期的地方有一个固定格式显示。
好了,整理好了流程,我们就开始一一实现对应的代码。
首先要保证你的项目结构跟我的一样:
缺少的话,你就自己创建对应的包名.
一. 在entity包下新建一个User.java实体类:
代码如下:
package com.aaa.entity;
import java.util.Date;
/**
* @class_name:User
* @param: 1.User表
* @return: 用户实体类
* @author:Zoutao
* @createtime:2018年3月21日
*/
public class User {
private int id; // id
private String username; // 用户名
private String password; // 密码
private Date birthday; // 注册日期
private int sex; // 性别
private String address; // 地址
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public int getSex() {
return sex;
}
public void setSex(int sex) {
this.sex = sex;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "User [id=" + id + ", username=" + username + ", password=" + password + ", birthday=" + birthday
+ ", sex=" + sex + ", address=" + address + "]";
}
}
二. Dao层接口:
在mapper包下新建一个UserMapper.java接口类:
代码如下:
package com.aaa.mapper;
import org.apache.ibatis.annotations.Param;
import com.aaa.entity.User;
/**
* @class_name:UserMapper
* @param: 2.dao层接口
* @return: 数据持久化
* @author:Zoutao
* @createtime:2018年3月21日
*/
public interface UserMapper {
// 查询登录账户-用户密码为参数
public User CheckLoginAndPwd(@Param("username") String name, @Param("password") String pwd);
// 注册用户
public void addUser(User user);
}
三. 在mapper包下新建一个UserMapper.xml:
代码如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- 1.指定映射的对象是usermapper类 -->
<mapper namespace="com.aaa.mapper.UserMapper">
<!-- 查询,写定义的方法对应的sql操作 -->
<select id="CheckLoginAndPwd" resultType="user" parameterType="user">
select*from user where username=#{username} and password=#{password}
</select>
<!-- 增加,性别以数字替代1=男 0=女 -->
<insert id="addUser" parameterType="user">
insert into user
values(default,#{username},#{password},#{birthday},1,#{address})
</insert>
</mapper>
四. 在biz包下新建一个UserBiz.java接口类:
代码如下:
package com.aaa.biz;
import com.aaa.entity.User;
/**
* @class_name:UserBiz
* @param: 4.service层接口
* @return: 业务逻辑层
* @author:Zoutao
* @createtime:2018年3月21日
*/
public interface UserBiz {
// 登录查询
public User CheckLoginAndPwd(String name, String pwd);
// 注册用户
public void addUser(User user);
}
五. 在com.aaa.biz.impl包下新建一个UserBizImpl.java实现类类:
代码如下:
package com.aaa.biz.impl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.aaa.biz.UserBiz;
import com.aaa.entity.User;
import com.aaa.mapper.UserMapper;
/**
* @class_name:UserBizImpl
* @param: 5.impl层实现接口
* @return: 实现service接口
* @author:Zoutao
* @createtime:2018年3月21日
*/
@Service
public class UserBizImpl implements UserBiz {
@Autowired
private UserMapper userMapper;
@Override
public User CheckLoginAndPwd(String name, String pwd) {
// TODO Auto-generated method stub
return userMapper.CheckLoginAndPwd(name, pwd);
}
@Override
public void addUser(User user) {
// TODO Auto-generated method stub
userMapper.addUser(user);
}
}
六.在controller包下新建一个UserController.java控制类:
代码如下:
package com.aaa.controller;
import java.util.List;
import javax.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import com.aaa.biz.UserBiz;
import com.aaa.entity.Items;
import com.aaa.entity.User;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
/**
* @class_name:UserController
* @param:6.控制层controller
* @return: 逻辑控制层
* @author:Zoutao
* @createtime:2018年3月21日
*/
// 设置默认先映射到("/user")路径下
@Controller
@RequestMapping("/user")
public class UserController {
@Autowired
private UserBiz userBiz;
// 设置映射路径和以json格式传送参数
@RequestMapping(value = "/checkLogin", produces = { "application/json;charset=UTF-8" })
public @ResponseBody User checkLogin(@RequestBody User user, Model model, HttpSession session) {
User user1 = userBiz.CheckLoginAndPwd(user.getUsername(), user.getPassword());
// 登录以后添加到session中
session.setAttribute("user1", user1);
return user1;
}
@RequestMapping("/queryItems")
public String queryItems(Model model) {
System.out.println("欢迎登录!");
return "showItems";
}
}
七.在WebRoot文件夹下的Login.jsp中添加登录功能。
代码如下:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort()
+ path + "/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>登录页-qxb</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="登录,ssm练习,web项目">
<meta http-equiv="description" content="This is login page">
<!-- 引入css和js -->
<link rel="stylesheet" href="css/bootstrap.min.css" />
<link rel="stylesheet" href="css/bootstrap-datetimepicker.min.css" />
<script type="text/javascript" src="js/jquery-3.2.1.min.js"></script>
<script type="text/javascript" src="js/bootstrap.min.js"></script>
<script type="text/javascript" src="js/bootstrap-datetimepicker.min.js"></script>
<script type="text/javascript"
src="js/bootstrap-datetimepicker.zh-CN.js"></script>
</head>
<!-- ajax提交方式 -->
<script type="text/javascript">
/* Js控制通过#myModal的状态:*/
$("#myModal").modal({
keyboard : false,
backdrop : false
});
/* Js控制注册日期的状态:*/
$(function() {
$(".form_datetime").datetimepicker({
format : "yyyy-mm-dd hh:ii",
autoclose : true,
todayBtn : true,
todayHighlight : true,
showMeridian : true,
pickerPosition : "bottom-left",
language : 'zh-CN', //中文,需要引用zh-CN.js包
startView : 2, //月视图
minView : 2
//日期时间选择器所能够提供的最精确的时间选择视图
});
/* 以json的格式提交登录传参 */
$("#lo")
.click(
function() {
$
.ajax({
type : 'post',
//提交路径
url : '${pageContext.request.contextPath}/user/checkLogin.action',
//声明为json格式
contentType : 'application/json;charset=utf-8',
//转为json格式
data : JSON.stringify({
"username" : $("#loginusername")
.val(),
"password" : $("#loginpassword")
.val()
}),
//点击登录以后拿到数据
success : function(data) {
//判断
if (data == "" || data == null) {
$("#message").html("用户名或密码错误!");
} else {
//正常跳转--已修改
window.location.href = "${pageContext.request.contextPath}/user/queryItems.action";
}
}
});
});
});
</script>
<style>
#login {
width: 450px;
height: 100px;
margin: 50px auto;
}
</style>
<body>
<div class="container">
<div id="login">
<!-- 登录模块,以json提交from就可以不写action -->
<form class="form-horizontal" role="form">
<div class="form-group">
<label for="inputEmail3" class="col-sm-2 control-label">用户名:</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="loginusername"
name="username" placeholder="请输入用户名" required autofocus>
</div>
</div>
<div class="form-group">
<label for="inputPassword3" class="col-sm-2 control-label">密 码:</label>
<div class="col-sm-10">
<input type="password" class="form-control" id="loginpassword"
name="password" placeholder="请输入密码" required> <label
class="control-label" for="inputSuccess1" style="color: red;"
id="message"></label>
</div>
</div>
<!-- 登录注册按钮 -->
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="button" class="btn btn-info" id="lo">登录</button>
<button type="button" class="btn btn-danger" data-toggle="modal"
data-target="#myModal">注册</button>
</div>
</div>
</form>
</div>
</div>
</body>
</html>
login.jsp中用到的技术点相关说明:
可以不看跳过。
登录模块,以json提交from就可以不写action
其中:required autofocus分别表示:
Required:html5属性,表示required 属性规定必需在提交之前填写输入字段。如果使用该属性,则字段是必填(或必选)的。
Autofocus:html5属性,表示当设置该属性后,它规定在页面加载后文本区域自动获得焦点。
Bootstrap中的data-target和data-toggle:
data-toggle:以什么事件触发,如modal,popover,tooltips等;
data-target:事件的目标;
HTML5允许开发者自由为其标签添加属性,这种自定义属性一般用“data-”开头。
data-target指事件的目标,
<button type="button" class="btn btn-danger" data-toggle="modal"
data-target="#myModal">注册</button>
这段代码的意思就是指将#myModal这个DOM元素的内容以模态框(modal)的形式展示。
tabindex="-1"
tabindex 属性规定元素的 tab 键控制次序(当 tab 键用于导航时)。
若把tabIndex属性设为一个负值(如tabIndex="-1"),那么这个链接将被排除在TAB键的序列之外。 如果最初选择了[Tab]键,带这个输入栏的网页会将光标移动到firstName栏。
如果一个元素同时有aria-labelledby和aria-label,读屏软件会优先读出aria-labelledby的内容
<input type=”text” aria-labelledby=”用户名”/>
此时,当焦点落到该输入框时,读屏软件就会读出aria-label里的内容,即“用户名”。
当想要的标签文本已在其他元素中存在时,可以使用aria-labelledby,并将其值为所有读取的元素的id。如下:
当ul获取到焦点时,屏幕阅读器是会读:“选择用户名”
aria-hidden="true"
为了避免 屏幕识读设备抓取非故意的和可能产生混淆的输出内容。为这些图标设置了 aria-hidden="true" 属性,这样就表示图标有可访问性。
注册以表单提交,提交到注册的url下。
Js控制通过#myModal的状态:
keyboard : false, 设置键盘关闭模态框 (当设置为true时,按下 esc 键时关闭模态框,设置为 false 时则按键无效。)
backdrop : false:一个对话框背景元素. 另外 static(false情况) 背景下, 点击对话框外的区域不会关闭对话框。为true时,显示对话框的遮蔽背景,鼠标点击背景即可关闭对话框。
为false时,无背景。
到了这里,我们的登录模块的流程就完成了,但是当输入正确的账户密码时候,我们是不是应该跳转到某个界面或者是有什么反应?
所以我们在登录的ajax提交方式下写得是:
以id的名称来提交触发
url:’${pageContext.request.contextPath}/user/checkLogin.action’,
提交到/user/checkLogin下,转到控制层:
然后后面的判断,如果登录账户正确以后,跳转到:showItems.jsp
八.在WEB-INF文件夹下新建一个jsp文件夹,在建立一个showItems.jsp页面,来显示登录以后的显示页面。
代码如下:
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>欢迎页面</title>
</head>
<body>
<div class="container">
<!-- 标题 -->
<div class="row">
<div class="col-md-7">
<h2>SSM的CRUD+分页+拦截器+日期转换+</h2>
<span>柒晓白</span>
</div>
</div>
</div>
</body>
</html>
最后右键运行项目:
输入账户密码:
admin+admin
登录成功跳转如图:
输入错误账户提示如图:
运行没有报错也就表示SSM登录模块成功。
报错的话,请评论贴出错误信息。
下一篇将完善登录以后的商品显示模块。
You got a dream, you gotta protect it.
如果你有梦想的话,就要去捍卫它 。 ——《当幸福来敲门》