怎么做一个小管理系统的CRUD及登录展示
准备一个后台管理的主页面
整体业务逻辑
查询:写一个查询条件的类,从数据库将查询条件选项展示到前台,将所有请求数据发送给后台,后台根据条件执行查询
删除:前台获取到该动态创建的删除请求的ID,绑定一个确定删除事件的请求,将ID传给后台,后台通过ID删除整条数据
修改/添加:点击添加按钮,通过之前查询的后台传来的所有数据,展示到模态框,打开模态框,点击保存按钮,发送请求,将form表单的所有数据发送给后台,后台根据传过来的表单中的所有数据通过判断是否有ID,判断是添加还是修改,执行对应的操作
前台页面的JS代码
<script type="text/javascript">
//GridManager发送请求
document.querySelector('#table-demo-ajaxPageCode').GM({
gridManagerName: 'demo-ajaxPageCode',
ajaxData: '/system/article/list',
ajaxType: 'POST',
supportAjaxPage: true, //是否分页
currentPageKey: "localPage", //修改当前页请求为,默认是cPage
pageSizeKey: "pageSize", //修改当前页条数为,默认是pSize
sizeData: [5,10,15,20], //配置每页显示条数的下拉项
pageSize: 5, //初次进行页面的每页条数(不写默认20)
height:"100%",
columnData: [
{
key: 'title',
align:'center',
text: '文章标题'
},{
key: 'url',
align:'center',
text: 'url'
},{
key: 'type',
align:'center',
text: '文章类型',
template: function(cell, row, index, key){
//console.debug(cell) //后台的当前key的数据
//console.debug(row) //后台的所有数据
//console.debug(index) //下标
//console.debug(key) //上面的key值
return cell.name;
}
},{
key: 'clickCount',
align:'center',
text: '点击次数'
},{
key: 'content',
align:'center',
text: '文章内容'
},{
key: 'createDate',
align:'center',
text: '创建时间'
},{
key: 'enable',
align:'center',
text: '是否启用',
template: function(cell, row, index, key){
return cell?"启用":"禁用";
}
},{
key: 'id',
align:'center',
text: '操作  <a id="addBtn" style="color:green" href="javascript:;">添加</a>',
template: function(cell, row, index, key){
//当前row是对象,调用此方法将row转换成json串
var rows = JSON.stringify(row)
return "<a data-id="+cell+" style='color:red' href='javascript:;'>删除</a> <a data-obj='"+rows+"' style='color:blue' href='javascript:;'>修改</a>";
}
}
]
});
//页面加载
$(function(){
//高级查询
$("#queryButton").on("click",function(){
//获取所有查询条件的请求
var formData = $('#queryForm').serializeObject();
//发送demo-ajaxPageCode请求,将demo-ajaxPageCode请求数据和条件数据传给后台
GridManager.setQuery('demo-ajaxPageCode', formData);
})
//添加
$("body").on("click","#addBtn",function(){
//清空缓存
$("#saveForm")[0].reset()
//清空隐藏域
$("#hid").val("")
//打开模态框
$("#saveModel").modal("show")
})
//修改
$("body").on("click","a[data-obj]",function(){
//获取后台传来的所有数据
var objs = $(this).data("obj")
//回显后台数据给弹出的模态框
$("#saveForm").setForm(objs)
//弹出模态框
$("#saveModel").modal("show")
})
//保存
$("#saveButton").on("click",function(){
$.ajax({
type:"post",
url:"/system/article/save",
//将form表单的所有数据转换成k:v&k:v格式发送给后台
data:$("#saveForm").serialize(),
dataType:"json",
success:function(msg){
if (msg.result) {
//关闭模态框
$("#saveModel").modal("hide")
//刷新表格,默认为false,改为true刷新后跳转到第一页
GridManager.refreshGrid('demo-ajaxPageCode')
} else {
alert(msg.error)
}
}
})
})
//删除操作
$("body").on("click","a[data-id]",function(){
//获取请求的id
var id = $(this).data("id")
//打开模态框
$("#delModel").modal("show")
//解绑确认删除按钮单击事件缓存
$("#delModelButton").off("click")
//绑定确认删除按钮
$("#delModelButton").on("click",function(){
$.ajax({
type:"post",
url:"/system/article/del",
data:{"id":id},
dataType:"json",
success:function(m){
if (m.result) {
//关闭模态框
$("#delModel").modal("hide")
//刷新表格,默认为false,改为true刷新后跳转到第一页
GridManager.refreshGrid('demo-ajaxPageCode',true)
} else {
alert(m.error)
}
}
})
})
})
})
</script>
后台业务逻辑
@Controller
@RequestMapping("/system/article")
public class ArticleController {
@Autowired
private IArticleService service;
@Autowired
private IArticleTypeService typeService;
/**
*
* @Description:(条件查询)
*
*/
@RequestMapping("/list")
@ResponseBody
public PageBean<Article> findAll(ArticleQuery query){
System.out.println(query);
return service.findAll(query);
}
/**
*
* @Description:(删除)
*
*/
@RequestMapping("/del")
@ResponseBody
public AjaxBean del(Long id){
try {
service.del(id);
return new AjaxBean();
} catch (Exception e) {
return new AjaxBean(false, "删除失败");
}
}
/**
*
* @Description:(保存)
*/
@RequestMapping("/save")
@ResponseBody
public AjaxBean save(Article article){
try {
service.save(article);
return new AjaxBean();
} catch (Exception e) {
e.printStackTrace();
return new AjaxBean(false, "保存失败");
}
}
/**
*
* @Description:(跳转到文章展示页面)
*/
@RequestMapping("/article")
public String goArticle(Map<String, Object> map){
//查询type表的所有数据
List<ArticleType> list = typeService.findAll();
//将查询的数据放入list中,返回给前台页面
map.put("list", list);
return "article/article";
}
}
@Service
public class ArticleServiceImpl implements IArticleService {
@Autowired
private ArticleMapper mapper;
@Autowired
private ArticleTypeMapper TypeMapper;
@Override
public PageBean<Article> findAll(ArticleQuery query) {
// 总条数
Integer count = mapper.findCount(query);
if(count==0){
return new PageBean<>();
}
// 查询每页数据
List<Article> list = mapper.findAll(query);
for (Article article : list) {
Long typeId = article.getTypeId();
ArticleType articleType = TypeMapper.findById(typeId);
article.setType(articleType);
}
return new PageBean<>(count,list);
}
@Override
public void del(Long id) {
//删除
mapper.del(id);
}
@Override
public void save(Article article) {
if (article.getId()==null) {
//执行添加
mapper.add(article);
} else {
//执行修改
mapper.update(article);
}
}
}
后台操作数据库
<mapper namespace="cn.itsource.mapper.ArticleMapper">
<!-- 写Sql语句
List<Article> findAll(ArticleQuery query);
Integer findCount(ArticleQuery query);
-->
<select id="findAll" resultType="cn.itsource.domain.Article">
select * from t_article
<include refid="tiaojian"></include>
limit #{begin},#{pageSize}
</select>
<select id="findCount" resultType="int">
select count(id) from t_article
<include refid="tiaojian"></include>
</select>
<!-- void del(Long id); -->
<delete id="del">
delete from t_article where id=#{id}
</delete>
<!-- void add(Article article); -->
<insert id="add">
insert into t_article (title,url,typeId,clickCount,content,createDate,enable)
values(#{title},#{url},#{typeId},#{clickCount},#{content},#{createDate},#{enable})
</insert>
<!-- void update(Article article); -->
<update id="update">
update t_article set title=#{title},typeId=#{typeId},enable=#{enable},content=#{content}
where id=#{id}
</update>
<sql id="tiaojian">
<where>
<if test="typeId!=null">
and typeId=#{typeId}
</if>
<if test="enable!=null">
and enable=#{enable}
</if>
<if test="title!=null and ''!=title.trim()">
and title like concat('%',trim(#{title}),'%')
</if>
</where>
</sql>
</mapper>
写一个登录界面
是管理员才能登陆成功操作数据库
回车登录: 用keypress事件监听键盘,回车对应13,当keyCode==13就是回车,发送登录请求
登陆拦截: 在mvc.xml文件中配置拦截器,新建一个类,实现HandlerInterceptor接口,重写prehandle方法,拿到之前登陆过的用户信息,如果为空,就表示没有登陆过,就拦截,跳转到登录界面
登录: 前台点击登录,发送登录请求,后台在数据库中查询,判断是否是管理员,并给出对应的提示,当前台勾选记住我选项时,将账号密码用cookie添加到浏览器中保存,没有勾选就得到当前浏览器中的所有cookie,如果当前cookie等于账号或者密码就在任意路径下都删除该cookie,将删除完的空cookie保存到浏览器中,前台拿到所有cookie,如果cookie不为空,且某一个cookie中有账号或者密码参数,就拿到value值,并将此value值回显到账号密码的文本框中,设置记住我框默认为勾上。如果cookie为空,就将账号密码的文本框value值设置为空,再设置记住我框默认为不勾选
前台JS代码
//拿到页面所有cookie
var cookies = document.cookie
//console.debug(cookies) username=root; password=123
//如果有cookies
if (cookies!=null) {//实现记住我
//将cookie按照;分割
var arr = cookies.split(";")
//遍历分割后的数组
$.each(arr,function(i,obj){
//判断如果cookie中包含了username
if (obj.indexOf("username")!=-1) {
//就截取username的值
var username = obj.substring(obj.indexOf("=")+1)
//将username的值回显
$("#username").val(username)
}
//判断如果cookie中包含了password
if (obj.indexOf("password")!=-1) {
//就截取password的值
var password = obj.substring(obj.indexOf("=")+1)
//将password的值回显
$("#password").val(password)
//就默认把记住我勾上
$("#remember").prop("checked",true)
}
})
} else {//取消记住我
//将username,password的值回显为空
$("#username").val("")
$("#password").val("")
//就默认不勾记住我
$("#remember").prop("checked",false)
}
//设置按回车登录
//作用范围为document整个页面,keypress监听键盘,e代表每一个按键对应的值
$(document).on("keypress",function(e){
//回车键对应的值是13,当==13时就登录,发送请求
if (e.keyCode==13) {
login()
}
})
//抽取登录公共请求
function login(){
//发送异步请求
$("#loginForm").ajaxSubmit({
//后台返回的数据
success:function(msg){
if (msg.result) {
//如果成功就跳转到后台管理界面
location.href="/system/index"
} else {
//如果是失败就弹出后台抛出打印的异常
alert(msg.error)
}
}
})
}
XML中配置拦截器
<!-- 配置拦截器组 -->
<mvc:interceptors>
<!-- 拦截器 -->
<mvc:interceptor>
<!-- 要拦截的配置,该配置必须写在不拦截的上面,/*拦截一级请求,/**拦截多级请求 -->
<mvc:mapping path="/system/**" />
<!-- 设置不拦截的配置 -->
<mvc:exclude-mapping path="/system/login"/>
<!-- 配置拦截器 -->
<bean class="cn.itsource.interceptor.LoginInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
实现HandlerInterceptor接口
public class LoginInterceptor implements HandlerInterceptor{
//preHandle()方法在业务处理器处理请求之前被调用
@Override
public boolean preHandle(HttpServletRequest req, HttpServletResponse resp, Object arg2) throws Exception {
//通过session得到该用户信息
Object user = req.getSession().getAttribute("USER_IN_SESSION");
if (user==null) {
//如果没有登录就跳回登录页面
resp.sendRedirect("/system/login");
return false;
}
return true;
}
后台业务代码
//当路径相同时,用value,post区分
//处理登录请求
@RequestMapping(value="/login",method=RequestMethod.POST)
@ResponseBody
public AjaxBean login(Integer remember,String username,String password,
HttpSession session,HttpServletResponse resp,HttpServletRequest req){
try {
//通过前台登录的参数查询到user表中的数据
User user = service.login(username,password);
//将查到的数据设置到session中(服务器端)保存
session.setAttribute("USER_IN_SESSION", user);
//当前台勾选记住我选项时
if (remember!=null) {
//创建一个账号密码的cookie对象
Cookie c1 = new Cookie("username", username);
Cookie c2 = new Cookie("password", password);
//设置路径
c1.setPath("/");
c2.setPath("/");
//设置存活时间
c1.setMaxAge(7*24*60*60);
c2.setMaxAge(7*24*60*60);
//将cookie对象添加到浏览器中保存
resp.addCookie(c1);
resp.addCookie(c2);
}else {//取消记住我
//得到保存在cookie中的所有数据
Cookie[] cookies = req.getCookies();
//遍历
for (Cookie cookie : cookies) {
//如果该cookie中有之前设置的username或者password
if ("username".equals(cookie.getName()) || "password".equals(cookie.getName())) {
//删除当前cookie
cookie.setMaxAge(0);
//设置当前的cookie路径
cookie.setPath("/");
//将cookie添加到浏览器
resp.addCookie(cookie);
}
}
}
return new AjaxBean();
} catch (Exception e) {
e.printStackTrace();
//e.getMessage()存储自己设置的异常
return new AjaxBean(false, e.getMessage());
}
}
@Service
public class UserServiceImpl implements IUserService {
@Autowired
private UserMapper mapper;
/**
* 登录后台
*/
@Override
public User login(String username, String password) throws Exception {
//通过前台传的用户名查找user表
User user = mapper.findByName(username);
//如果没有找到,打印抛出一个异常
if (user==null) {
throw new Exception("找不到该用户");
}else {
//找到了再判断,如果前台传过来的密码不等于表中的密码,打印抛出一个异常
if (!password.equals(user.getPassword())) {
throw new Exception("密码输入错误");
}else {
//如果等于就返回这个数据
return user;
}
}
}
管理系统的CRUD
现在很多管理系统的CRUD差不多都是这个思路,只要把此CRUD逻辑理清楚,自己可以写图片,视频等,各种类型的CRUD