在建表时,表名一般以t_
、tb_
、 tbl_
开头
在该项目中,所有的表字段均为字符串,包括数字(在银行等的项目中,字段该是什么类型,就是什么类型)
表中有外键,但是不使用外键约束,即在创建表时,外键的字段同其它字段的创建方式一致。在表的说明文档中,要说明谁是谁的外键
当主键字段属性为 int / long 整型时,可以自动递增
如何确保字符串主键的唯一性?
UUID是未来最常见的主键生成机制,该机制是由java.util包为我们提供的工具类,该形式生成的是由数字
,字母
和-
组成的36位的随机串,这36位的随机串一定是全世界唯一的
-
的位置是固定的,所以可以将-
去掉,即在数据库中使用char(32)
来存储public static String getUUID(){
return UUID.randomUUID().toString().replaceAll("-","");
}
在项目开发中,使用字符串来表示时间,共有两种方式
实体类中的属性名与字段名一致,且类型均为String
public class MD5Util {
public static String getMD5(String password) {
try {
// 得到一个信息摘要器
MessageDigest digest = MessageDigest.getInstance("md5");
byte[] result = digest.digest(password.getBytes());
StringBuffer buffer = new StringBuffer();
// 把每一个byte 做一个与运算 0xff;
for (byte b : result) {
// 与运算
int number = b & 0xff;// 加盐
String str = Integer.toHexString(number);
if (str.length() == 1) {
buffer.append("0");
}
buffer.append(str);
}
// 标准的md5加密后的结果
return buffer.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return "";
}
}
}
动态sql中的
标签中的collection
属性指的是集合的属性,有array
和list
两个值
在字符串数字后+0
或者*1
select * from tbl_dic_value order by typeCode,orderNo+0
Limit 1, 2
后的第一个参数可以简单的记为:略过的记录数
"%"
与#{name}
之间要有空格,相当于字符串拼接中的加号"+"
标签中的条件要用"and"
标签对中的and可有可无,之后的
标签对中的and不能省略<select id="getActivity" resultType="int">
select count(*)
from tbl_activity
<where>
<if test="name!=null and name!=''">
and name like '%' #{name} '%'
if>
where>
select>
当表中存在非必填的外键时,要极其注意外键为null
的情况,使用外连接来避免查不到数据
<%
String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath() + "/";
%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<head>
<base href="<%=basePath%>">
head>
标签一定要加在
标签中的第一行../
,将所有的../
全部去掉/
,对于后端文件,写路径时一律要加/
webapp
的根路径下去除空格:
$.trim("字符串");
如果要在绑定事件中引入外部函数,函数不能写在$( )
中,要写在$( )
之外(为什么?)
get:拿、取
post:邮寄、邮递
网站的初始页面约定是index.html
,但是登录页面在login.jsp
,
index.html
中进行重定向到login.jsp
页面<script type="text/javascript">
document.location.href = "login.jsp";
</script>
在maven中加入任何外部资源时都需要刷新一下maven
登录失败时,直接抛出异常,通过SpringMVC来统一处理异常,在异常中返回ajax请求
如果登录成功后响应为200,但是返回的是空白页,说明拦截器暂时没有设置为true
获取ip地址,如果是自己访问自己,则用的是localhost,则下面的方法返回的是 0:0:0:0:0:0:0:1不是一个有效的ip地址,本地访问要用127.0.0.1
String ip = request.getRemoteAddr();
Session的销毁方式:
session.invalidate();
servlet
的
和该path相同或是它的子路径,servlet才能够访问该Cookie。如果把一个Cookie的path设为项目根目录,那么该项目下的所有servlet都能够访问它Cookie loginActCookie = new Cookie("loginAct", loginAct);
loginActCookie.setMaxAge(60*60*24*10);//设置过期时间
loginActCookie.setPath("/");//设置权限
Cookie loginActCookie = new Cookie("loginAct", null);//Cookie的key一定要与要销毁的Cookie键相同
cookie1.setPath("/");
cookie1.setMaxAge(0);//过期时间设置为0
如果顶层窗口不是当前窗口,则将顶层窗口设置为当前窗口,防止出现登录页显示在标签中的bug
$(function(){
if(window.top != window){
window.top.location = window.location;
}
})
使用标签
<div id="workarea" style="position: absolute; top : 0px; left: 18%; width: 82%; height: 100%;">
<iframe style="border-width: 0px; width: 100%; height: 100%;" name="workareaFrame">iframe>
div>
$(function(){
//在页面加载完成后,默认在工作区中自动打开
//参数1:打开哪个页面
//参数2:在哪儿打开(工作区的name属性)
window.open("workbench/main/toIndex.do","workareaFrame");
})
取得指定模态窗口的jquery对象,由该对象调用modal方法,该modal方法有两种取值
添加操作执行之后,要清空表单,可以在打开的时候清,也可以在点击保存添加成功之后清,为了防止失误操作让表单关闭后填写的数据丢失,应该在处理了添加操作之后清空表单
var attr = "";
var $create = $("#create-form :input");//选中表单下的所有input表单
for (var i = 0; i < $create.length; i++) {
attr += $create[i].name + ":'"+ $.trim($create[i].value) + "',";
}
attr = attr.substr(0, attr.length - 1);//去除最后一位的逗号
var obj = eval("({"+attr+"})");//将JSON字符串转为JS对象,AJAX中的data属性要使用对象,不是字符串
增删改后应该使用重定向,返回修改后的页面,使地址栏中的地址与当前页的地址一致。
EL表达式取值取出NULL
,会自动改为空字符串""
模拟鼠标点击$(“#code”)
元素,click可以换成其它任意事件
$("#code").trigger("click");
给dom对象赋值:
$("#span-code").prop("class", spanError);
失去焦点:blur()
删除时,弹窗用confirm("消息")
el表达式的取值是能够用在js代码中的,只不过需要套用在字符串的引号中
使用JS来实现表单的提交与清空
submit()
是jQuary
提供的,而reset()
是JavaScript
提供的,故他们的使用方法不同:
$("#activitySaveForm").submit();
$("#activitySaveForm")[0].reset();
往前追加同级元素(兄弟标签)用 兄弟元素.before
$("p").before("追加");
$("#remarkDiv").before(html);
结果:
<b>追加b><p>段落p>
父级元素中的最后追加子元素(子标签)用 父级元素.append
$("p").append("追加");
结果:
<p>段落<b>追加b>p>
{"key":[{"id":"001","name":"zhangsan"},{"id":"002","name":"lisi"}]}
可以简写成:[{"id":"001","name":"zhangsan"},{"id":"002","name":"lisi"}]
$("#toSaveActivityBtn").click(function () {
$.ajax({
url: "workbench/activity/getUserList.do",
type: "get",
dataType: "json",//这一步将json字符串转为js对象
success: function (data) {
var html = "";
$.each(data, function (i, n) {
html += "";
});
$("#create-owner").html(html);
//将当前用户默认为被选中的用户
$("#create-owner").val("${user.id}");
//通过js打开模态窗口
//这句话要写在ajax的响应成功函数中
$("#createActivityModal").modal("show");//show打开,hide关闭
}
});
});
点击按钮发送AJAX请求,没有反应,具体排查流程:
先点击F12,再点击"创建"按钮
在你的ajax的回调函数中第一行,加入alert(data)
观察后台
alert("弹框的内容,内容最后不要随便加感叹号,就像这样!!!")
$("#qx").click(function () {
//将多选框的checked属性赋值给单选框
$("input[name=xz]").prop("checked", this.checked);
})
$("input[name=xz]").click(function () {
$("#qx").prop("checked", $("input[name=xz]:checked").length === $("input[name=xz]").length);
});
引入BootStrap的日历控件,给所有class
中带有time
的表单加入日历控件
<link href="jquery/bootstrap_3.3.0/css/bootstrap.min.css" type="text/css" rel="stylesheet"/>
<link href="jquery/bootstrap-datetimepicker-master/css/bootstrap-datetimepicker.min.css" type="text/css" rel="stylesheet"/>
<script type="text/javascript" src="jquery/jquery-1.11.1-min.js"></script>
<script type="text/javascript" src="jquery/bootstrap_3.3.0/js/bootstrap.min.js"></script>
<script type="text/javascript" src="jquery/bootstrap-datetimepicker-master/js/bootstrap-datetimepicker.js"></script>
<script type="text/javascript" src="jquery/bootstrap-datetimepicker-master/locale/bootstrap-datetimepicker.zh-CN.js"></script>
<script type="text/javascript">
$(".time").datetimepicker({
language: "zh-CN",
format: "yyyy-mm-dd",//显示格式
minView: "month",//设置只显示到月份
// initialDate: new Date(),//初始化当前日期
autoclose: true,//选中自动关闭
todayBtn: true, //显示今日按钮
clearBtn : true,//显示游击队按钮
pickerPosition: "bottom-left"//对齐样式
});
</script>
原则:在双引号中如果要再使用引号的话,要使用单引号,在单引号中如果要再使用引号的话,要使用双引号,为了与最外层的双引号做区分,双引号要加上转义"\
"
" ' \" \" ' "
' " \' \' " '
每次在Controller中return值的时候,都要想一下注解是否加全(有一次忘记加@ResponseBody找了一个多小时bug)
Service层使用事务时,Controller层给Service属性自动赋值,属性只能是Service的接口类型
,不能是Service的实现类类型(我和另一个人合伙找了快三个小时bug……)
items属性中的参数一定要从作用域对象中取出来(多次犯错这个错)
<c:forEach items="${dtList}" var="dt" varStatus="i">
c:forEach>
总是在不该加“/
”的地方加上"/
"(要多注意)
from
写成formActivityController
处理请求UserService
来处理业务异常处理方式:在控制层捕获业务层所有的异常,然后抛出自定义异常
@RequestMapping("/saveActivity.do")
@ResponseBody
public Map<String,Object> saveActivity(Activity a)throws AjaxRequestException {
try {
activityService.saveActivity(a);
} catch (Exception e) {
e.printStackTrace();
throw new AjaxRequestException();
}
return HandleFlag.successTrue();
}
标签
type
属性为"hidden
"时,为隐藏域,可以保存一些值,而且不会被浏览器界面看到
<input type="hidden" id="hidden-name"/>
<input type="hidden" id="hidden-owner"/>
应用:
使用的函数:
$(需要绑定的元素的有效的父级元素).on(绑定事件的方式,需要绑定的元素,回调函数)
on
这个方法会为有效的父级元素这个区域添加一个监视器,只要有新的元素进来都会添加上一个事件,如click
等//这里的有效父元素为#activityBody
$("#activityBody").on("click",$("input[name=xz]"),function () {
$("#qx").prop("checked",$("input[name=xz]").length==$("input[name=xz]:checked").length);
});
//另一种绑定方式,与上面的区别是这里用的是CSS选择器
$("#contentRemarkDiv").on("mouseout",".myHref",function(){
$(this).children("span").css("color","#E6E6E6");
});
一个完整的ajax查询显示流程:
//pageNo表示当前页,pageSize表示一页显示几条数据
function pageList(pageNo, pageSize) {
//将全选的复选框的√灭掉,小细节
$("#qx").prop("checked", false);
//将隐藏域中的信息取出,重新赋值给搜索框,前面讲的9-3
$("#search-name").val($.trim($("#hidden-name").val()));
$("#search-owner").val($.trim($("#hidden-owner").val()));
$.ajax({
//这里来发送请求
success: function (data) {
//这里来展现后台返回的数据
//计算总页数
var totalPages = data.total % pageSize == 0 ? data.total / pageSize : parseInt(data.total / pageSize) + 1;
$("#activityPage").bs_pagination({
currentPage: pageNo, // 页码
rowsPerPage: pageSize, // 每页显示的记录条数
maxRowsPerPage: 20, // 每页最多显示的记录条数
totalPages: totalPages, // 总页数
totalRows: data.total, // 总记录条数
visiblePageLinks: 3, // 显示几个卡片(显示几个1,2,3,4...这种的页码)
showGoToPage: true,
showRowsPerPage: true,
showRowsInfo: true,
showRowsDefaultInfo: true,
//该函数的触发时机:在我们点击分页组件的时候(上一页,下一页,首页,尾页,12345...页)
onChangePage: function (event, data) {
/*
data.currentPage:点击分页组件后的当前页码
data.rowsPerPage:点击分页组件后每页展现的记录数
以上这两个值,是分页插件为我们提供的,我们千万不要去改动
*/
pageList(data.currentPage, data.rowsPerPage);
}
});
}
})
}
调用函数时,有两个框架已经提供好的参数,当实参传入即可,根据具体情况进行使用:
$("#activityPage").bs_pagination('getOption', 'currentPage')
:维持当前页$("#activityPage").bs_pagination('getOption', 'rowsPerPage')
:维持每页展现的记录数pageList($("#activityPage").bs_pagination('getOption', 'currentPage'),
$("#activityPage").bs_pagination('getOption', 'rowsPerPage'));
下一层往上一层做值的返回,如果返回的有多个不同类型的值,那么使用的一般都是map
类型来处理,当返回的信息复用率比较高,为了方便可读性以及可维护性,我们也可以使用vo
类技术来代替传统的map
技术来处理
VO:Value Object 用来表现值的对象,用来展现值的类,用法与传统的实体类是一样的,将需要展现的值的信息,一项一项的列在VO类的属性当中,这些属性都是私有的,所有的存取值操作一律使用setter
和getter
来实现;使用泛型式的方式,让每一个模块都能够使用(集合中存不同的实体类)
public class PaginationVo<T> {
private List<T> dataList;
private int total;
//省略getter和setter
}
Map
来接收前端发过来的参数,将前端传过来的所有参数以键值对的形式存储到map中value
属性来给传递过来的参数起别名,功能和@Param
相同,只不过@Param
用在dao
层,而@RequestParam
用在controller
层public PaginationVo<Activity> pageList(@RequestParam Map<String,Object> map){}
textarea
文本域是表单元素,但是他操作值的方式与其他元素有些差别,其他的表单元素都有其value
值,但是文本域没有value
值,而是以textarea
标签对中的信息去操作表单元素的值。
虽然textarea
操作的是标签对中的内容,但是他也是属于表单元素范畴,所以我们必须以val()
方法的方式去操作文本域的值,而不是html()
方法
data属性规定要发送到服务器的数据, 类型可以是:string
,数组,多数是 json
,当有多个徤相同
的值要往后台发送时,就不能使用json
了,而要使用string
,string
的格式"id=A001&id=A002&id=A003
",后台使用string数组接收,变量名与前台发回的名称一样(id
)
public PaginationVo<Activity> pageList2(String[] id){}//id这个变量名要与发送回来的参数名一样
数据库数据的导入与导出
在页面加载完毕后,发出ajax
请求取得备注信息列表,采用这种方式的原因:
增、删、改之后要注意一下要定位到更改的那个元素位置,再单独对它进行刷新。不能全部刷
在js
中用el
表达式一定要加引号,已经在引号中可以直接用(在字符串中)
$.ajax({data : {"activityId" : "${a.id}"})
var html = " ${a.name}"
href="javascript:void(0);"
:禁用超链接,超链接必须以触发(绑定)事件的形式执行操作
目的:将鼠标移到超链接上,鼠标会变成变手形,只有超链接能办到。
如果元素是通过在js
或者java
脚本动态拼接的for
循环中的元素,那么我们一般的做法都是以直接触发事件(例如标签中加入onclick="f('id')"
)的方式来进行操作,而不是绑定事件。
直接触发事件传递的参数(如前面的id
)必须要包含在引号当中
前端设置了浮动的下划线,当后台没有取到数据时,下划线会跑到上面