先看數據庫的代碼:
-- 創建數據庫
create database musicdb
use musicdb
-- 創建表
-- 用戶表
create table [user](
uid int primary key identity(1,1),
name varchar(20) not null,
pwd varchar(20) not null,
[desc] varchar(50)
)
create table music(
mid int primary key identity(101,1),
musicName varchar(50) not null,
singer varchar(20) not null, --歌手
album varchar(20) not null, --專輯
timer varchar(20), --時長
position varchar(100), --位置
)
select * from music
select * from [user]
然后vs2019 創建AspNet Web項目,添加Default.aspx
有一定基礎的同學,應該知道,AspNet 分兩部分,一部分是前臺界面,另一部分是后臺代碼,Aspnet使用了CodeBehind 代碼后置的技術
Default.aspx 前臺設計界面:
<div class="row">
<h3 class="text-center" style="color: orange">音樂庫 管理</h3>
</div>
<div class="row">
<asp:GridView ID="GridView1" runat="server" CssClass="table table-hover table-striped" AutoGenerateColumns="False" OnRowCommand="GridView1_RowCommand" OnRowDeleting="GridView1_RowDeleting" OnRowEditing="GridView1_RowEditing" DataKeyNames="mid" OnRowUpdating="GridView1_RowUpdating" OnRowCancelingEdit="GridView1_RowCancelingEdit">
<Columns>
<asp:BoundField DataField="mid" HeaderText="序號" />
<asp:BoundField DataField="musicName" HeaderText="歌曲名" />
<asp:BoundField DataField="singer" HeaderText="歌手" />
<asp:BoundField DataField="album" HeaderText="專輯" />
<asp:BoundField DataField="timer" HeaderText="時長" />
<asp:BoundField DataField="position" HeaderText="存儲位置" />
<asp:TemplateField HeaderText="操作" ShowHeader="False">
<EditItemTemplate>
<asp:LinkButton ID="LinkButton1" runat="server" CausesValidation="True" CommandName="Update" Text="更新"></asp:LinkButton>
<asp:LinkButton ID="LinkButton2" runat="server" CausesValidation="False" CommandName="Cancel" Text="取消"></asp:LinkButton>
</EditItemTemplate>
<ItemTemplate>
<asp:LinkButton ID="LinkButton3" runat="server" CausesValidation="False" CommandName="Edit" Text="修改"></asp:LinkButton>
<asp:LinkButton ID="LinkButton1" runat="server" CausesValidation="False" CommandName="Delete" Text="刪除"></asp:LinkButton>
<a href="/add.aspx">插入</a>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</div>
Default.aspx.cs 后臺代碼
public partial class _Default : Page
{
public string name = "";
protected void Page_Load(object sender, EventArgs e) // 首次加載
{
if (!IsPostBack) {
if (Session["userName"]==null)
{
Response.Redirect("~/login.aspx");
}
else
{
name = Session["userName"].ToString();
LoadMusic();
}
}
}
protected void GridView1_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
string id = GridView1.Rows[e.RowIndex].Cells[0].Text;
string sql = $"delete from music where mid='{id}'";
if (DBHelper.Update(sql))
{
LoadMusic();
}
else {
Response.Write("<script>alert('刪除失敗!')</script>");
}
}
protected void GridView1_RowEditing(object sender, GridViewEditEventArgs e)
{
//string mid = e.CommandArgument.ToString();
name = Session["userName"].ToString();
GridView1.EditIndex = e.NewEditIndex;
LoadMusic();
}
private void LoadMusic()
{
this.GridView1.DataSource = DBHelper.Select("select * from music");
this.GridView1.DataBind();
}
protected void GridView1_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
string id = this.GridView1.DataKeys[e.RowIndex].Value.ToString();
string name = ((TextBox)(GridView1.Rows[e.RowIndex].Cells[1].Controls[0])).Text;
string signer= ((TextBox)(GridView1.Rows[e.RowIndex].Cells[2].Controls[0])).Text;
string album= ((TextBox)(GridView1.Rows[e.RowIndex].Cells[3].Controls[0])).Text;
string timer= ((TextBox)(GridView1.Rows[e.RowIndex].Cells[4].Controls[0])).Text;
string p= ((TextBox)(GridView1.Rows[e.RowIndex].Cells[5].Controls[0])).Text;
string sql = $"update music set musicName='{name}',singer='{signer}',album='{album}',timer='{timer}',position='{p}' where mid='{id}'";
if (DBHelper.Update(sql)) {
Response.Write("<script>alert('修改成功!')</script>");
LoadMusic();
}
}
protected void GridView1_RowCancelingEdit(object sender, GridViewCancelEditEventArgs e)
{
name = Session["userName"].ToString();
GridView1.EditIndex = -1;
LoadMusic();
}
}
效果圖
以上就是首頁完成的顯示的功能,篇幅有限,需要源碼的朋友私聊我噢
千山萬水總是情,打賞一元也是情
和老段一起終身學習,我們一起做自己的CEO!
?有用嗎?對于學完Spring、SpringMVC、Mybatis還無從下手的同學來說這是一個很好引子。對于正在學習同一個案例的同學,可能解決一些問題。對于需要這個案例的同學可以直接獲取。
??有什么?:xml配置文件編寫,引入一個簡單的前端框架,使用MyBatis Generator逆向工程生成一些代碼,使用框架簡單快速搭建一個頁面,好用的分頁工具PageHelper,簡單的前后端分離,發送ajax請求,利用json傳遞數據,增、刪、改、查的簡單實現。
??簡單嗎?內容很簡單,涉及Java代碼不多,但是對于新手來說,最困難的部分是各種環境搭建、配置文件、版本沖突,如果能夠根據錯誤提示動手解決,那就是一大進步。
??怎么學?如果有時間可以在B站搜索:ssm整合crud,雷豐陽講的。如果想看到每個功能的實現過程和源碼,可以在這里學習,每個步驟都有注釋。也可以作為復習快速瀏覽。
前端格式校驗、用戶名校驗、后端校驗、JSR303校驗,效果如圖
使用彈出模態框作為新增模塊,參考Bootstrap代碼
<!-- 為新增按鈕增加模態框 ,利用按鈕綁定單擊事件-->
<!-- Modal -->
<div class="modal fade" id="empAddModal" tabindex="-1" role="dialog"
aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"
aria-label="Close">
<span aria-hidden="true">×</span>
</button>
<h4 class="modal-title" id="myModalLabel">員工添加</h4>
</div>
<div class="modal-body">
<!-- 添加表單 -->
<form class="form-horizontal" id="model-form">
<!-- 姓名 -->
<div class="form-group">
<label for="empName_add_input" class="col-sm-2 control-label">EmpName</label>
<div class="col-sm-10">
<input type="text" class="form-control" name="empName" id="empName_add_input"
placeholder="empName">
<!-- 用來顯示錯誤提示 -->
<span class="help-block"></span>
</div>
</div>
<!-- 郵箱 -->
<div class="form-group">
<label for="email_add_input" class="col-sm-2 control-label">Email</label>
<div class="col-sm-10">
<input type="email" class="form-control" name="email" id="email_add_input"
placeholder="empName@123.com">
<!-- 用來顯示錯誤提示 -->
<span class="help-block"></span>
</div>
</div>
<!-- 性別 -->
<div class="form-group">
<label class="col-sm-2 control-label">Gender</label>
<div class="col-sm-10">
<!-- 單選 -->
<label for="gender1_add_input"> <input type="radio"
name="gender" id="gender1_add_input"
name="gender" value="M" checked>
男
</label>
<label for="gender2_add_input"> <input type="radio"
name="gender" id="gender2_add_input"
name="gender" value="F">
女
</label>
</div>
</div>
<!-- 部門下拉框 -->
<div class="form-group">
<label class="col-sm-2 control-label">DeptName</label>
<div class="col-sm-10">
<!-- 部門下拉列表使用ajax查詢出來的動態拼接,值為部門id -->
<select class="form-control" name="dId" id="deptName_add_select"></select>
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">關閉</button>
<button type="button" class="btn btn-primary" id="emp_save_btn">保存</button>
</div>
</div>
</div>
</div>
//添加模態欄 $("#emp_add_modal_btn").click(function() {
//顯示模態框
$("#empAddModal").modal({
//模態框參數,點擊背景不關閉
backdrop : "static"
});
});
//新增模態框 $("#emp_add_modal_btn").click(function() {
//添加模態欄之前將所表單信息清空,包括兩項驗證的css樣式,顯示模態欄之后就是空的
//reset()方法是dom下的,使用[0]
$("#empAddModal form")[0].reset();
//清空輸入格式、重名校驗的css樣式
reset_form("#empAddModal form");
//獲取所有部門信息
getDepts("#deptName_add_select");
//添加模態框,在模態框中需要所有部門,所以需要查詢所有部門信息
$("#empAddModal").modal({
//模態框參數,點擊背景不關閉
backdrop : "static"
});
});
//后面用
//新增模態框--清除表單數據,樣式
function reset_form(ele) {
$(ele)[0].reset();
//該元素下所有css清除
$(ele).find("*").removeClass("has-error has-success");
//顯示警告信息部分清空
$(ele).find(".help-block").text("");
}
//新增模態框--請求所有部門信息 function getDepts(ele){
//---注意這里要清空---
$(ele).empty();
$.ajax({
url:"${PATH}/depts",
type:"GET",
success:function(result){
//console.log(result);
//動態拼接
}
});
}
package com.ssm.controller;
import com.ssm.bean.Department;
import com.ssm.bean.Msg;
import com.ssm.service.DepartmentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.List;
/**
* 部門信息
*/
@Controller
public class DepartmentController {
@Autowired
private DepartmentService departmentService;
/**
* 獲取所有部門信息
* @return
*/
@ResponseBody
@RequestMapping("/depts")
public Msg getDepts() {
List<Department> depts = departmentService.getDepts();
return Msg.success().add("depts", depts);
}
}
package com.ssm.service;
import com.ssm.bean.Department;
import com.ssm.dao.DepartmentMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 部門信息
*/
@Service
public class DepartmentService {
@Autowired
DepartmentMapper departmentMapper;
/**
* 查詢所有部門
*/
public List<Department> getDepts(){
//方法本身可以添加查詢條件,如果為null代表查所有
List<Department> list = departmentMapper.selectByExample(null);
return list;
}
}
//新增模態框--請求所有部門信息 function getDepts(ele){
//---注意這里要清空---
$(ele).empty();
$.ajax({
url:"${PATH}/depts",
type:"GET",
success:function(result){
//console.log(result);
$.each(result.extend.depts,function(index,item){
//創建出option并添加到select中
var optionEle = $("<option></option>").append(item.deptName).attr("value",item.deptId);
optionEle.appendTo(ele);
});
}
});
}
效果
綁定保存按鈕
//------------------增刪改查都使用REST風格------------------- //新增保存信息
$("#emp_save_btn").click(function(){
//1、模態框中填寫的表單數據提交給服務器進行保存
//2、發送ajax請求保存員工
$.ajax({
url:"${PATH}/saveemp",
type:"POST",
data:$("#empAddModal form").serialize(),
//.serialize()方法能將表單中數據序列化,直接發送給controll封裝成Bean
//console.log($("#empAddModal form").serialize());
//empName=Tom&email=Tom%40123.com&gender=M&dId=1
success:function(result){
//1.添加成功,關閉模態框
$("#empAddModal").modal("hide");
//2.來到最后一頁,顯示插入的數據,可以直接跳到一個很大的頁數,因為
//合理性,所以不會超出,這里使用全局參數,數據總條數
to_page(totalRecord+1);
}
});
EmployeeController
@ResponseBody @RequestMapping(value = "/saveemp",method = RequestMethod.POST)
public Msg saveEmp(Employee employee, BindingResult result) {
employeeService.saveEmp(employee);
return Msg.success();
}
EmployeeService
/**
* 保存emp員工,insert
* @param employee
*/
public void saveEmp(Employee employee) {
//這個是有選擇插入,insert()全插入,包括id
employeeMapper.insertSelective(employee);
}
一共有兩種驗證方式 1.輸入框焦點單獨驗證 2.提交按鈕總驗證,為了不兩種方式的css樣式相互覆蓋,每種方式都驗兩遍,格式在前,用戶名在后
(內部Java格式驗證)+ ajax用戶名驗證(實現方法看下一小節)
//1.(內部Java格式驗證)+ ajax用戶名驗證 //新增保存信息--ajax用戶名校驗
//由于在java內又做了一次格式驗證,所以這個方法相當于即驗證了格式,又驗證了重名
$("#empName_add_input").blur(function () {
//發送ajax請求,驗證用戶名是否可用
var empName = this.value;
$.ajax({
url: "${PATH}/checkname",
data: "empName=" + empName,
type: "POST",
success: function (result) {
console.log(result);
//獲取到返回值,Msg中的狀態碼
if (result.code == 2333) {
show_validate_msg("#empName_add_input", "success", "用戶名可用");
//因為使用了兩種方式驗證,格式和重名,會有css樣式沖突覆蓋,所以再加一次驗證
//自定義屬性,或全局變量
//給添加按鈕添加自定義屬性,在提交時判斷是否通過兩項驗證。
$("#emp_save_btn").attr("ajax-vl", "success");
} else if (result.code == 5555) {
show_validate_msg("#empName_add_input", "error", result.extend.msg);
$("#emp_save_btn").attr("ajax-vl", "error");
}
}
});
});
郵箱格式獨立校驗
//2. 郵箱獨立驗證 //新增保存信息--獨立郵箱格式驗證
$("#email_add_input").blur(function () {
var email = $("#email_add_input").val();
var regEmail = /^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$/;
if (!regEmail.test(email)) {
//alert("郵箱格式不正確");
show_validate_msg("#email_add_input", "error", "郵箱格式不正確");
//return false;
} else {
show_validate_msg("#email_add_input", "success", "");
}
//最后方法通過
//return true;
})
格式+用戶名驗證+提交保存請求
//3. 格式+用戶名驗證+提交保存請求,一共有兩種驗證方式 1.輸入框焦點單獨驗證 2.提交按鈕總驗證, //為了不兩種方式的css樣式相互覆蓋,每種方式都驗兩遍,格式在前,用戶名在后
//新增保存信息--請求
$("#emp_save_btn").click(function () {
//點擊就發送請求,保存使用POST請求
//1.先驗證ajax重名校驗,防止用戶輸入重復用戶名之后,直接輸入正確的郵箱,點擊提交,重名的驗證提示會被覆蓋
//ajax-vl是ajax重名校驗之后添加的自定義屬性,用于表示提交按鈕是否可用
if ($(this).attr("ajax-vl") == "error") {
return false;
}
//2.點擊保存按鈕請求之前完整驗證一遍輸入格式
//JQuery格式總驗證
if (!validate_add_form()) {
return false;
}
//3.重名驗證
//ajax重名校驗
if ($(this).attr("ajax-vl") == "error") {
return false;
}
//1、模態框中填寫的表單數據提交給服務器進行保存
//2、發送ajax請求保存員工
$.ajax({
url: "${PATH}/saveemp",
type: "POST",
data: $("#empAddModal form").serialize(),
//.serialize()方法能將表單中數據序列化,直接發送給controll封裝成Bean
//console.log($("#empAddModal form").serialize());
//empName=Tom&email=Tom%40123.com&gender=M&dId=1
success: function (result) {
//1.添加成功,關閉模態框
$("#empAddModal").modal("hide");
//2.來到最后一頁,顯示插入的數據,可以直接跳到一個很大的頁數,因為
//合理性,所以不會超出,這里使用全局參數,參數值在上面分頁時獲取的,數據總條數+1保證不出現極端情況
to_page(totalRecord + 1);
}
});
});
請求按鈕JQuery格式總校驗方法
//新增保存信息--請求按鈕JQuery格式總校驗方法 function validate_add_form() {
console.log("validate_add_form()")
//1.拿到校驗的數據,使用正則表達式
//根據bootstrap提供的組件
//校驗用戶名
var empName = $("#empName_add_input").val();
var regName = /(^[a-zA-Z0-9_-]{2,8}$)|(^[\u2E80-\u9FFF]{2,5})/;
if (!regName.test(empName)) {
//alert("用戶名可以是2-5位中文或者2-8位英文和數字的組合");
show_validate_msg("#empName_add_input", "error", "用戶名可以是2-5位中文或者2-8位英文和數字的組合");
return false;
} else {
show_validate_msg("#empName_add_input", "success", "");
}
//2、校驗郵箱信息
var email = $("#email_add_input").val();
var regEmail = /^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$/;
if (!regEmail.test(email)) {
//alert("郵箱格式不正確");
show_validate_msg("#email_add_input", "error", "郵箱格式不正確");
return false;
} else {
show_validate_msg("#email_add_input", "success", "");
}
//最后方法通過
return true;
}
添加樣式方法
//新增保存信息--添加css樣式 //show_validate_msg顯示校驗狀態,通過添加樣式,ele表示被選擇元素,status狀態
//用來判斷是用什么樣式,綠色、紅色,msg提示信息
function show_validate_msg(ele, status, msg) {
//判斷之前先清空之前樣式
$(ele).parent().removeClass("has-success has-error");
$(ele).next("span").text("");
if ("success" == status) {
$(ele).parent().addClass("has-success");
$(ele).next("span").text(msg)
} else if ("error" == status) {
$(ele).parent().addClass("has-error");
$(ele).next("span").text(msg)
}
}
如果添加相同的用戶名會造成混淆,所以在輸入用戶名之后立即進行校驗
發送ajax請求(與上一節相同)
$("#empName_add_input").blur(function () {
//發送ajax請求,驗證用戶名是否可用
var empName = this.value;
$.ajax({
url: "${PATH}/checkname",
data: "empName=" + empName,
type: "POST",
success: function (result) {
console.log(result);
//獲取到返回值,Msg中的狀態碼
if (result.code == 2333) {
show_validate_msg("#empName_add_input", "success", "用戶名可用");
//因為使用了兩種方式驗證,格式和重名,會有css樣式沖突覆蓋,所以再加一次驗證
//自定義屬性,或全局變量
//給添加按鈕添加自定義屬性,在提交時判斷是否通過兩項驗證。
$("#emp_save_btn").attr("ajax-vl", "success");
} else if (result.code == 5555) {
show_validate_msg("#empName_add_input", "error", result.extend.msg);
$("#emp_save_btn").attr("ajax-vl", "error");
}
}
});
});
EmployeeController
/**
* 用戶名查重
* 前端校驗,在失去焦點,保存之前都校驗
* @param empName
* @return
*/
@ResponseBody
@RequestMapping("/checkname")
public Msg checkEmpName(@RequestParam("empName")String empName) {
//用戶名格式校驗
String regx = "(^[a-zA-Z0-9_-]{2,8}$)|(^[\\u2E80-\\u9FFF]{2,5})";
if(!empName.matches(regx)){
return Msg.fail().add("msg", "用戶名可以是2-5位中文或者2-8位英文和數字的組合");
}
//返回查詢統計結果,true說明沒有重名
boolean b = employeeService.checkEmpName(empName);
if(b) {
return Msg.success();
}else {
return Msg.fail().add("msg", "用戶名已存在");
}
}
EmployeeService
/**
* 查詢用戶是否存在
* 使用Example復雜查詢
*
* @param name
* @return
*/
public boolean checkEmpName(String name) {
//Example用法
EmployeeExample example = new EmployeeExample();
//創建查詢條件
EmployeeExample.Criteria criteria = example.createCriteria();
//我的理解:這一句相當于添加了一個條件 where empName=name
criteria.andEmpNameEqualTo(name);
//統計查詢結構
long count = employeeMapper.countByExample(example);
//返回true(0)說明沒有重復用戶名
return count == 0;
}
前面是前端校驗,現在是后端校驗,針對Java
添加JSR303依賴
<!-- JSR303校驗 -->
<!-- https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator -->
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.1.0.Final</version>
</dependency>
在JavaBean上添加注解
public class Employee {
private Integer empId;
//JSR303自定義校驗規則
@Pattern(regexp = "(^[a-zA-Z0-9_-]{2,8}$)|(^[\\u2E80-\\u9FFF]{2,5})", message = "用戶名可以是2-5位中文或者2-8位英文和數字的組合")
private String empName;
private String gender;
@Pattern(regexp = "^([a-z0-9_\\.-]+)@([\\da-z\\.-]+)\\.([a-z\\.]{2,6})$",message = "郵箱格式不正確")
private String email;
//...
在Controller方法中使用,在參數前添加注解,在參數后面添加結果參數
/**
* 新增,保存用戶,并驗證
*
* 添加JSR303校驗
* @Valid表示校驗下一個對象
* BindingResult緊跟被校驗對象,接收結果
*
* @param employee
* @return
*/
@ResponseBody
@RequestMapping(value = "/saveemp",method = RequestMethod.POST)
public Msg saveEmp(@Valid Employee employee, BindingResult result) {
if(result.hasErrors()) {
//格式校驗失敗,返回信息
Map<String ,Object> map = new HashMap<>();
List<FieldError> fieldErrors = result.getFieldErrors();
for(FieldError error : fieldErrors) {
System.out.println("錯誤的字段名:" + error.getField());
System.out.println("錯誤信息:" + error.getDefaultMessage());
//將錯誤信息放到map中
map.put(error.getField(), error.getDefaultMessage());
}
return Msg.fail().add("errorFields", map);
}else if(!employeeService.checkEmpName(employee.getEmpName())){
//后端在保存的時候再次驗證是否存在用戶名---有點 重復的感覺???
//因為是在一起接收所以錯誤信息一定要一樣,empName手動寫上
return Msg.fail().add("empName", "用戶名已存在");
}else {
employeeService.saveEmp(employee);
//不用這種:獲取總頁數,用在新增完之后跳轉到最后一頁,不過這樣就會多查一次數據庫
//PageInfo<Employee> pageInfo = employeeService.getPage(null);
//return Msg.success().add("pageInfo", pageInfo);
return Msg.success();
}
}
在index.jsp提交按鈕中處理返回結果
//3. 格式+用戶名驗證+提交保存請求,一共有兩種驗證方式 1.輸入框焦點單獨驗證 2.提交按鈕總驗證, //為了不兩種方式的css樣式相互覆蓋,每種方式都驗兩遍,格式在前,用戶名在后
//新增保存信息--請求
$("#emp_save_btn").click(function () {
//點擊就發送請求,保存使用POST請求
//1.先驗證ajax重名校驗,防止用戶輸入重復用戶名之后,直接輸入正確的郵箱,點擊提交,重名的驗證提示會被覆蓋
if ($(this).attr("ajax-vl") == "error") {
return false;
}
//2.點擊保存按鈕請求之前完整驗證一遍輸入格式
console.log("JQuery格式總驗證")
//方法一:JQuery格式總驗證
if (!validate_add_form()) {
return false;
}
//3.重名驗證
console.log("ajax重名校驗")
//ajax重名校驗
if ($(this).attr("ajax-vl") == "error") {
return false;
}
//1、模態框中填寫的表單數據提交給服務器進行保存
//2、發送ajax請求保存員工
$.ajax({
url: "${PATH}/saveemp",
type: "POST",
data: $("#empAddModal form").serialize(),
//.serialize()方法能將表單中數據序列化,直接發送給controll封裝成Bean
//console.log($("#empAddModal form").serialize());
//empName=Tom&email=Tom%40123.com&gender=M&dId=1
success: function (result) {
//清除模態框和提示信息
$("#empAddModal form").find("*").removeClass("has-error has-success");
$("#empAddModal form").find(".help-block").text("");
//在這里判斷后端JSR303校驗結果,最后一次!!!!!!!!!真的
//前后端驗證可以獨立運行,注釋前端后端也能實現一樣效果
if(result.code == 2333){
//alert(result.msg);
//1.添加成功,關閉模態框
$("#empAddModal").modal("hide");
//2.來到最后一頁,顯示插入的數據,可以直接跳到一個很大的頁數,因為
//合理性,所以不會超出,這里使用全局參數,數據總條數+1保證不出現極端情況
to_page(totalRecord + 1);
}else{
//失敗,顯示信息,有幾個就顯示幾個
//undefined 就是沒找到這個錯誤,說明正確,可用alert(result.extend.errorFields.empName)驗證
//用戶名格式
//alert(result.extend.errorFields.empName)
//用戶名格式和查重,因為查重的屬性格式和格式驗證不同,所以不能分開
//result.extend.errorFields.empName 格式驗證
//result.extend.empName 查重驗證
if(undefined != result.extend.errorFields ){
//格式錯誤
if(undefined != result.extend.errorFields.empName){
show_validate_msg("#empName_add_input","error",result.extend.errorFields.empName);
}
}else{
if(undefined != result.extend.empName){
//查重錯誤
show_validate_msg("#empName_add_input","error",result.extend.empName);
}
}
//郵箱格式判斷
if(undefined != result.extend.errorFields){
if(undefined != result.extend.errorFields.email){
show_validate_msg("#email_add_input","error",result.extend.errorFields.email);
}
}
}
}
});
});
模態框
<!-- 為新增按鈕增加模態框 ,利用按鈕綁定單擊事件-->
<!-- Modal -->
<div class="modal fade" id="empAddModal" tabindex="-1" role="dialog"
aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"
aria-label="Close">
<span aria-hidden="true">×</span>
</button>
<h4 class="modal-title" id="myModalLabel">員工添加</h4>
</div>
<div class="modal-body">
<!-- 添加表單 -->
<form class="form-horizontal" id="model-form">
<!-- 姓名 -->
<div class="form-group">
<label for="empName_add_input" class="col-sm-2 control-label">EmpName</label>
<div class="col-sm-10">
<input type="text" class="form-control" name="empName" id="empName_add_input"
placeholder="empName">
<!-- 用來顯示錯誤提示 -->
<span class="help-block"></span>
</div>
</div>
<!-- 郵箱 -->
<div class="form-group">
<label for="email_add_input" class="col-sm-2 control-label">Email</label>
<div class="col-sm-10">
<input type="email" class="form-control" name="email" id="email_add_input"
placeholder="empName@123.com">
<!-- 用來顯示錯誤提示 -->
<span class="help-block"></span>
</div>
</div>
<!-- 性別 -->
<div class="form-group">
<label class="col-sm-2 control-label">Gender</label>
<div class="col-sm-10">
<!-- 單選 -->
<label for="gender1_add_input"> <input type="radio"
name="gender" id="gender1_add_input"
name="gender" value="M" checked>
男
</label>
<label for="gender2_add_input"> <input type="radio"
name="gender" id="gender2_add_input"
name="gender" value="F">
女
</label>
</div>
</div>
<!-- 部門下拉框 -->
<div class="form-group">
<label class="col-sm-2 control-label">DeptName</label>
<div class="col-sm-10">
<!-- 部門下拉列表使用ajax查詢出來的動態拼接,值為部門id -->
<select class="form-control" name="dId" id="deptName_add_select"></select>
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">關閉</button>
<button type="button" class="btn btn-primary" id="emp_save_btn">保存</button>
</div>
</div>
</div>
</div>
請求和方法
<script type="text/javascript">
//------------------增刪改查都使用REST風格-------------------
//1.(內部Java格式驗證)+ ajax用戶名驗證
//新增保存信息--ajax用戶名校驗
//由于在java內又做了一次格式驗證,所以這個方法相當于即驗證了格式,又驗證了重名
$("#empName_add_input").blur(function () {
//發送ajax請求,驗證用戶名是否可用
var empName = this.value;
$.ajax({
url: "${PATH}/checkname",
data: "empName=" + empName,
type: "POST",
success: function (result) {
console.log(result);
//獲取到返回值,Msg中的狀態碼
if (result.code == 2333) {
show_validate_msg("#empName_add_input", "success", "用戶名可用");
//因為使用了兩種方式驗證,格式和重名,會有css樣式沖突覆蓋,所以再加一次驗證
//自定義屬性,或全局變量
//給添加按鈕添加自定義屬性,在提交時判斷是否通過兩項驗證。
$("#emp_save_btn").attr("ajax-vl", "success");
} else if (result.code == 5555) {
show_validate_msg("#empName_add_input", "error", result.extend.msg);
$("#emp_save_btn").attr("ajax-vl", "error");
}
}
});
});
//2. 郵箱獨立驗證
//新增保存信息--獨立郵箱格式驗證
$("#email_add_input").blur(function () {
var email = $("#email_add_input").val();
var regEmail = /^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$/;
if (!regEmail.test(email)) {
//alert("郵箱格式不正確");
show_validate_msg("#email_add_input", "error", "郵箱格式不正確");
//return false;
} else {
show_validate_msg("#email_add_input", "success", "");
}
//最后方法通過
//return true;
})
//3. 格式+用戶名驗證+提交保存請求,一共有兩種驗證方式 1.輸入框焦點單獨驗證 2.提交按鈕總驗證,
//為了不兩種方式的css樣式相互覆蓋,每種方式都驗兩遍,格式在前,用戶名在后
//新增保存信息--請求
$("#emp_save_btn").click(function () {
//點擊就發送請求,保存使用POST請求
//1.先驗證ajax重名校驗,防止用戶輸入重復用戶名之后,直接輸入正確的郵箱,點擊提交,重名的驗證提示會被覆蓋
if ($(this).attr("ajax-vl") == "error") {
return false;
}
//2.點擊保存按鈕請求之前完整驗證一遍輸入格式
console.log("JQuery格式總驗證")
//方法一:JQuery格式總驗證
if (!validate_add_form()) {
return false;
}
//3.重名驗證
console.log("ajax重名校驗")
//ajax重名校驗
if ($(this).attr("ajax-vl") == "error") {
return false;
}
//1、模態框中填寫的表單數據提交給服務器進行保存
//2、發送ajax請求保存員工
$.ajax({
url: "${PATH}/saveemp",
type: "POST",
data: $("#empAddModal form").serialize(),
//.serialize()方法能將表單中數據序列化,直接發送給controll封裝成Bean
//console.log($("#empAddModal form").serialize());
//empName=Tom&email=Tom%40123.com&gender=M&dId=1
success: function (result) {
//清除模態框和提示信息
$("#empAddModal form").find("*").removeClass("has-error has-success");
$("#empAddModal form").find(".help-block").text("");
//在這里判斷后端JSR303校驗結果,最后一次!!!!!!!!!真的
//前后端驗證可以獨立運行,注釋前端后端也能實現一樣效果
if(result.code == 2333){
//alert(result.msg);
//1.添加成功,關閉模態框
$("#empAddModal").modal("hide");
//2.來到最后一頁,顯示插入的數據,可以直接跳到一個很大的頁數,因為
//合理性,所以不會超出,這里使用全局參數,數據總條數+1保證不出現極端情況
to_page(totalRecord + 1);
}else{
//失敗,顯示信息,有幾個就顯示幾個
//undefined 就是沒找到這個錯誤,說明正確,可用alert(result.extend.errorFields.empName)驗證
//用戶名格式
//alert(result.extend.errorFields.empName)
//用戶名格式和查重,因為查重的屬性格式和格式驗證不同,所以不能分開
//result.extend.errorFields.empName 格式驗證
//result.extend.empName 查重驗證
if(undefined != result.extend.errorFields ){
//格式錯誤
if(undefined != result.extend.errorFields.empName){
show_validate_msg("#empName_add_input","error",result.extend.errorFields.empName);
}
}else{
if(undefined != result.extend.empName){
//查重錯誤
show_validate_msg("#empName_add_input","error",result.extend.empName);
}
}
//郵箱格式判斷
if(undefined != result.extend.errorFields){
if(undefined != result.extend.errorFields.email){
show_validate_msg("#email_add_input","error",result.extend.errorFields.email);
}
}
}
}
});
});
//新增保存信息--請求按鈕JQuery格式總校驗方法
function validate_add_form() {
console.log("validate_add_form()")
//1.拿到校驗的數據,使用正則表達式
//根據bootstrap提供的組件
//校驗用戶名
var empName = $("#empName_add_input").val();
var regName = /(^[a-zA-Z0-9_-]{2,8}$)|(^[\u2E80-\u9FFF]{2,5})/;
if (!regName.test(empName)) {
//alert("用戶名可以是2-5位中文或者2-8位英文和數字的組合");
show_validate_msg("#empName_add_input", "error", "用戶名可以是2-5位中文或者2-8位英文和數字的組合");
return false;
} else {
show_validate_msg("#empName_add_input", "success", "");
}
//2、校驗郵箱信息
var email = $("#email_add_input").val();
var regEmail = /^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$/;
if (!regEmail.test(email)) {
//alert("郵箱格式不正確");
show_validate_msg("#email_add_input", "error", "郵箱格式不正確");
return false;
} else {
show_validate_msg("#email_add_input", "success", "");
}
//最后方法通過
return true;
}
//新增保存信息--添加css樣式
//show_validate_msg顯示校驗狀態,通過添加樣式,ele表示被選擇元素,status狀態
//用來判斷是用什么樣式,綠色、紅色,msg提示信息
function show_validate_msg(ele, status, msg) {
//判斷之前先清空之前樣式
$(ele).parent().removeClass("has-success has-error");
$(ele).next("span").text("");
if ("success" == status) {
$(ele).parent().addClass("has-success");
$(ele).next("span").text(msg)
} else if ("error" == status) {
$(ele).parent().addClass("has-error");
$(ele).next("span").text(msg)
}
}
</script>
__EOF__
本文作者: 蔚然丶丶
本文鏈接: https://www.cnblogs.com/wei-ran/p/16131419.html
頁篡改是最為常見的一種黑客攻擊形式。網頁篡改是一種通過網頁應用中的漏洞獲取權限,非法篡改Web應用中的內容、植入暗鏈、傳播惡意信息,危害社會安全并牟取暴利的網絡攻擊行為。
近些年來,網頁篡改攻擊事件層出不窮,且具有以下四個特點:篡改網站頁面傳播速度快、閱讀人群多;篡改頁面容易,預先檢查、實時防范、事后消除影響難;網絡環境復雜,追查責任難;攻擊工具簡單,并且向智能化趨勢發展。
零時代:人工對比檢測
人工對比檢測,其實就是一種專門指派網絡管理人員,人工監控需要保護的網站,一旦發現被篡改,然后以人力對其修改還原的手段。嚴格說來,人工對比檢測不能算是一種網頁防篡改系統采用的技術,而只能算是一種原始的應對網頁被篡改的手段。但是其在網頁防篡改的技術發展歷程中存在一段相當久的時間。
這種手段非常原始且效果不佳,且不說人力成本較高,其最致命的缺陷在于人力監控不能達到即時性,也就是不能在第一時間發現網頁被篡改,也不能在第一時間做出還原,當管理人員發現網頁被篡改再做還原時,被篡改的網頁已在互聯網存在了一段時間,可能已經被一定數量的網民瀏覽,造成一定的負面影響。
第一代:時間輪詢技術
時間輪詢技術,也稱“外掛輪詢技術”。從這一代開始,網頁防篡技術已經擺脫了以人力檢測恢復為主體的原始手段,而是作為一種自動化的技術形式出現。時間輪詢技術是利用一個網頁檢測程序,以輪詢方式讀出要監控的網頁,與真實網頁相比較后,進行判斷網頁內容的完整性,對于被篡改的網頁進行報警和恢復。
采用時間輪詢式的網頁防篡改系統,對每個網頁來說,輪詢掃描存在著時間間隔,一般為數十分鐘。所以,在這數十分鐘的間隔中,黑客可以攻擊系統并使訪問者訪問到被篡改的網頁。
此類應用在過去網頁訪問量較少,具體網頁應用較少的情況下適用,目前網站頁面通常少則上百頁,檢測輪詢時間更長,且占用系統資源較大,該技術逐漸被淘汰。
第二代:事件觸發+核心內嵌技術
將事件觸發技術與核心內嵌技術兩種技術放在同一代來說,是因為這兩種網頁防篡改技術出現的時間差距不大,而且兩種技術常常被結合使用。
所謂核心內嵌技術,即密碼水印技術,最初先將網頁內容采取非對稱加密存放,在外來訪問請求時將經過加密驗證過的,進行解密對外發布,若未經過驗證,則拒絕對外發布,調用備份網站文件進行驗證解密后對外發布。此種技術通常要結合事件觸發機制對文件的部分屬性進行對比,如大小、頁面生成時間等做判斷,無法更準確的進行其它屬性的判斷。其最大的特點就是相對外掛輪詢技術安全性大大提高,但其美中不足是加密計算會占用大量服務器資源,系統反映較慢。
核心內嵌技術避免了時間輪詢技術的輪詢間隔這個缺點。但是由于這種技術是對每個流出網頁都進行完整檢查,占用巨大的系統資源,給服務器造成較大負載。而且,因為對網頁正常發布流程作了更改,整個網站需要重新架構,增加新的發布服務器替代原先的服務器。
隨著IT技術發展以及網上各類應用的增多,對服務器的負載資源簡直可以用“苛刻”來形容,任何占用服務器資源的部分都要淘汰,來確保網站的高效率訪問和網頁防篡改技術追蹤率,如此一來,內嵌技術最終也被淘汰。
第三代:過濾驅動+事件觸發技術
技術發展到二十一世紀初,第三代文件網頁防篡技術:過濾驅動+事件觸發技術應運而生。
文件過濾驅動技術的最初應用于保密系統,作為文件保護技術和各類審計技術,甚至被應用于“流氓軟件”。在網頁防篡改技術革新當中,該技術找到了其發展的空間。與事件觸發技術結合,形成了第三代網頁防篡改保護技術。
其原理是將篡改監測的核心程序,利用微軟文件底層驅動技術應用到Web服務器中,通過事件觸發方式,對文件夾的所有文件內容,對照其底層文件屬性,經過內置散列快速算法,實時進行監測。若發現屬性變更,則通過非協議方式,將純文件安全拷貝,備份路徑文件夾內容拷貝到監測文件夾相應文件位置,通過底層文件驅動技術,整個文件復制過程毫秒級,使得公眾無法看到被篡改頁面,其運行性能和檢測實時性都達到較高水準。該頁面防篡改模塊采用Web服務器底層文件過濾驅動級保護技術,與操作系統緊密結合,所監測的文件類型不限,可以是一個html文件,也可以是一段動態代碼,執行準確率較高。
這樣就不僅完全杜絕了輪詢掃描式頁面,防篡改軟件的掃描間隔中被篡改內容被訪問的可能,其所消耗的內存和CPU占用率也遠遠低于文件輪詢掃描式或核心內嵌式的同類軟件。可以說是一種簡單、高效、安全性又極高的防篡改技術。
第四代:“五重防護”技術
目前,國內專注于保密與非密領域的分級保護、等級保護、業務連續性安全和大數據安全產品解決方案與相關技術研究開發的領軍企業——國聯易安更是基于“高效同步”、“安全傳輸”兩項技術,研發出了具備獨特的“五重防護”新特性,支持網頁的全自動發布、網頁監控、報警和自動恢復,提供強大的網頁安全管理維護功能的網頁防篡改保護系統。
一重防護:實時阻斷。系統能夠阻斷對受保護網頁的非法操作,此項技術有效地甄別合法進程和非法進程,阻斷非法進程對網頁的篡改,將非法進程直接阻斷。
二重防護:事件觸發。系統具備觸發式檢驗引擎,針對受保護的文件增刪改操作,一觸即發,校驗修改的合法性,瞬間清除被非法篡改的網頁,實時恢復合法網頁。
三重防護:核心內嵌。系統內嵌式篡改檢測引擎運行于Web服務器內部,與Web服務器無縫結合。系統檢測每一個Web請求訪問頁面,進行水印校驗,確保發送網頁的正確性。
四重防護:主動阻斷。當網站受到持續性攻擊時,系統會自動啟動積極防御機制,從根本上阻斷來自外部的攻擊。
五重防護:木馬檢測與查殺。系統提供對被保護網頁是否已經中木馬的檢測能力,如果已經中木馬可以查殺清除。對未中木馬的網頁,能提供防止掛木馬的防護能力。
結語
網頁防篡改主要有兩大功能:一是對攻擊事件進行監測與防護,二是網頁被篡改后實現快速恢復。
網頁相當于是一個組織機構的臉面,如果發生了黑客惡意篡改網頁,造成惡性事件,將對組織機構形象造成嚴重負面影響。因此,無論在日常的網絡安全加固,還是在等保評測過程中,網頁防篡改防護均被提到重要高度,成為一個政府、企事業單位必須采購的網絡安全產品。
值得一提的是,雖然Web防火墻WAF也能夠在日常的安全運營中發揮作用,但WAF不能替代網頁防篡改產品。因為有黑客有太多的辦法可以繞過WAF,造成網站被攻擊。惟有網頁防篡改產品才能真正防止網頁篡改惡性事件發生,或者在事后對網頁快速恢復。
關于國聯易安
北京國聯易安信息技術有限公司(原北京智恒聯盟科技有限公司)簡稱“國聯易安”,成立于2006年,擁有“國聯易安”和“智恒聯盟”兩個品牌,是國內專注于保密與非密領域的分級保護、等級保護、業務連續性安全和大數據安全產品解決方案與相關技術研究開發的領軍企業。公司多項安全技術補了國內技術空白,并且在政府、金融、保密、電信運營商、軍隊軍工、大中型企業、能源、教育、醫療電商等領域得到廣泛應用。
國聯易安除研發生產專業安全產品外,還為客戶提供全面的檢測與防護方案專家咨詢、源代碼安全評估、安全運維值守、智能終端安全評估、安全滲透測試、專業安全培訓等專業安全服務。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。