HTML&CSS
如何防止表单的重复提交
1.通过js代码,当用户点击提交按钮后,屏蔽提交按钮使用户无法点击提交按钮或点击无效,从而实现防止表单重复提交。【不推荐】通过刷新或者绕过前段页面后仍然能够重复提交表单
2.给数据库增加唯一键约束【不推荐】,重复访问数据库带来额外的负担
alter table tableName_xxx add unique key uniq_xxx(field1, field2)
3.利用Session防止表单重复提交【推荐,但是刷新的话是否会获得一个新的token】
服务器返回表单页面时,会先生成一个subToken保存于session,并把该subToen传给表单页面。当表单提交时会带上subToken,服务器拦截器Interceptor会拦截该请求,拦截器判断session保存的subToken和表单提交subToken是否一致。若不一致或session的subToken为空或表单未携带subToken则不通过。
@RequestMapping("/form")
//开启一个Token
@SubToken(saveToken = true)
public String form() {
return "/test/form";
}
@RequestMapping(value = "/postForm", method = RequestMethod.POST)
@ResponseBody
//开启Token验证,并且成功之后移除当前Token
@SubToken(removeToken = true)
public String postForm(String userName) {
System.out.println(System.currentTimeMillis());
try{
System.out.println(userName);
Thread.sleep(1500);//暂停1.5秒后程序继续执行
}catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(System.currentTimeMillis());
return "1";
}
首次提交表单时session的subToken与表单携带的subToken一致走正常流程,然后拦截器内会删除session保存的subToken。当再次提交表单时由于session的subToken为空则不通过。从而实现了防止表单重复提交。
Title
4.使用AOP自定义切入实现
import java.lang.annotation.*;
/**
* 避免重复提交
* @author hhz
* @version
* @since
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AvoidRepeatableCommit {
/**
* 指定时间内不可重复提交,单位毫秒
* @return
*/
long timeout() default 30000 ;
}
自定义切入点
@Aspect
@Component
public class AvoidRepeatableCommitAspect {
@Autowired
private RedisTemplate redisTemplate;
/**
* @param point
*/
@Around("@annotation(com.xwolf.boot.annotation.AvoidRepeatableCommit)")
public Object around(ProceedingJoinPoint point) throws Throwable {
HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes()).getRequest();
String ip = IPUtil.getIP(request);
//获取注解
MethodSignature signature = (MethodSignature) point.getSignature();
Method method = signature.getMethod();
//目标类、方法
String className = method.getDeclaringClass().getName();
String name = method.getName();
String ipKey = String.format("%s#%s",className,name);
int hashCode = Math.abs(ipKey.hashCode());
String key = String.format("%s_%d",ip,hashCode);
log.info("ipKey={},hashCode={},key={}",ipKey,hashCode,key);
AvoidRepeatableCommit avoidRepeatableCommit = method.getAnnotation(AvoidRepeatableCommit.class);
long timeout = avoidRepeatableCommit.timeout();
if (timeout < 0){
//过期时间5分钟
timeout = 60*5;
}
String value = (String) redisTemplate.opsForValue().get(key);
if (StringUtils.isNotBlank(value)){
return "请勿重复提交";
}
redisTemplate.opsForValue().set(key, UUIDUtil.uuid(),timeout,TimeUnit.MILLISECONDS);
//执行方法
Object object = point.proceed();
return object;
}
}
CSS选择器
通配符选择器:用*来表示,可以选择所有元素
*{marigin: 0;
padding: 0;
font-size: 14px;
}
类选择器 :类选择器根据类名来选择,前面以”.”来标志,是以一独立于文档元素的方式来指定样式
.demo {
width: 200px;
height: 200px;
margin: 50px auto;
background: #2DC4CB;
}
元素选择器:元素选择器(标签名选择器),是css3选择器中最常见而且最基本的选择器。元素选择器其实就是文档的元素,如html,body,p,div等等下下面例子中选择了span元素,并设置了字体颜色为红色。
ID选择器:我们在类使用时是在相对应的类名前加上一个“.”号
#demo {
width: 200px;
height: 200px;
margin: 50px auto;
background: #FF0000;
}
HTML常用标签:
1.段落、标题 ...
用来定义网页中的一段文本,段落与段落之间换行。
属性:align:定义段落中的文本水平方向的对齐方式。
属性值:left左对齐、right右对齐、center居中对齐
2.换行标签:
指行与行之间换行,他是一个单标签。
3.文字段落缩进
4.列表:无需ul、有序ol
- 列表项
- 列表项
circle空心圆、disc实心圆、square实心方块
5.特殊样式
加粗
倾斜
下划线
删除线
放大
缩小
加强强调
强调倾斜
6.
图片标签
属性:
src:指定图片源文件;
alt :图片未加载成功的提示文字;
width:指定图片的宽度;
height:指定图片的高度;
border:指定图片的边框样式;
alghr:top/bottom/middle;图片位于两端文字在垂直方向的一个上/中/下的对齐方式;
7.超链接
属性:
href:连接地址;空连接可以用"#"代替;
target :_self/_blank;打开方式;_self在当前页面中打开,_blank在新的空白窗口打开
8.可定义文档中的分区或节
标签被用来组合文档中的行内元素
表格设置与样式:
:表格基本结构
表格标题
我是第一行的第一个单元格
我是第一行的第二个单元格
我是第二行的第一个单元格
我是第二行的第二个单元格
table的属性:width:表格的宽度 height:表格的高度 align:表格的对齐方式
tr的属性:height:行的高度 bordercolor:边框的颜色
表单内置部件:
单选按钮 (checked默认)
复选按钮 (checked默认)
列表框
单行文本框
文件域