Ajax + JQuery 实战开发
准备工作:
修改后台表格页面,bootstrap.css
静态资源
在springboot项目中,static是静态资源目录。这个目录在访问时候和在引入的时候都不需要指定。如果你未来的程序调用和执行过程中,如果发现访问不了。或者引入不到。只能说明一个点:
-
要么名字写错,要么引入路径不对
-
更多的可能是:没有编译到target/classes
bootstrap
全局 CSS 样式 · Bootstrap v3 中文文档 | Bootstrap 中文网
Get请求查询 - 非实体参数注入
1: 查询
/** * 用户分页查询 * 接口路径:/admin/user/load * @param pageNo * @param pageSize * @return */ @GetMapping("/user/load") public IPage<User> findUserPages(int pageNo,int pageSize){ // 1: 定义分页 Page<User> page = new Page(pageNo,pageSize); // 2:设置查询条件 LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>(); lambdaQueryWrapper.eq(User::getIsDelete,0); lambdaQueryWrapper.orderByDesc(User::getCreateTime); // 3: 查询分页 return userService.page(page,lambdaQueryWrapper); }
-
请求方式:GET
-
请求参数:
int pageNo int pageSize
注意:如果在什么都不指定的情况下,参数默认是:必填的
因为上面的请求方式是:get请求,根据get请求规则和规范参数是放入在:请求地址后面用以
?name=zzz&age=11&name=2322
格式进行显示的传输和定义。也就就说。你要请求上面的接口:你必须要增加pageNo和pageSize这两个参数可以可以访问,否则拒绝。
解决方案:
-
必填
-
可以使用springmvc的@RequestParams机制,填写默认值。这样在第一次调用的过程中,如果你不填写我就用默认值填充。
@GetMapping("/user/load") public IPage<User> findUserPages( @RequestParam(name="pageNo",defaultValue = "1") int pageNo, @RequestParam(name="pageSize",defaultValue = "10") int pageSize ){
-
-
postman测试
运行结果
-
{ "records": [ { "id": 459, "nickname": "赵彦", "username": "赵彦", "age": 24, "sign": "爱你所爱 行你所行 听从你心 无问东西", "sex": 0, "views": 0, "job": "Java开发", "jobyear": "2", "address": "济南", "country": "中国", "province": null, "city": null, "telephone": "19653166182", "weixincode": "19653166182", "education": null, "birthday": "", "avatar": "/avatar/2.jpg", "bgimg": null, "vip": 2, "vipTime": null, "cron": 50, "studydays": 1, "isDelete": 0, "forbbiden": 1, "qqcode": "1810660001", "code": "0", "role": "normal", "password": "850e96fa21249a4ba972a531d9ae1f37", "openid": null, "unionid": null, "fans": 0, "gznums": 0, "bloglink": null, "giteelink": null, "bilibililink": null, "createTime": "2022-04-08T09:43:28.000+00:00", "updateTime": "2022-04-08T09:43:28.000+00:00" }, { "id": 458, "nickname": "赵赟", "username": "赵赟", "age": 24, "sign": "爱你所爱 行你所行 听从你心 无问东西", "sex": 0, "views": 0, "job": "Java开发", "jobyear": "0", "address": "杭州", "country": "中国", "province": null, "city": null, "telephone": "13116767698", "weixincode": "zy1029495988", "education": null, "birthday": "", "avatar": "/avatar/3.jpg", "bgimg": null, "vip": 2, "vipTime": null, "cron": 50, "studydays": 1, "isDelete": 0, "forbbiden": 1, "qqcode": "1029495988", "code": "0", "role": "normal", "password": "d0a3abf693af15e4b71c29b9a1426af8", "openid": null, "unionid": null, "fans": 0, "gznums": 0, "bloglink": null, "giteelink": null, "bilibililink": null, "createTime": "2022-03-07T05:39:26.000+00:00", "updateTime": "2022-03-07T05:39:26.000+00:00" } ], "total": 441, "size": 2, "current": 1, "orders": [], "optimizeCountSql": true, "searchCount": true, "countId": null, "maxLimit": null, "pages": 221 }
Get请求查询 - 实体对象参数注入
Springmvc本身已经对httpserletRequest和bean的参数的注入已经支持了。但是你必须要遵循一些条件:
-
就是参数的名字必须和bean的属性的名字要一致
-
必须生成getter/setter方法
bean的部分
package com.pug.vo; import lombok.Data; @Data public class UserVo implements java.io.Serializable{ private Integer pageNo = 1; private Integer pageSize = 10; private String keyword; }
请求部分
$.get("/admin/user/load?pageNo="+that.pageNo+"&keyword=12&pageSize="+that.pageSize)
注意:pageNo 和 pageSize 和 keyword必须和Uservo的属性名要一摸一样,注入不进去。
测试
Form表单数据的方式
你必须要知道是事情?
-
在开发中,其实不论用get还是post,form都可以完成数据的传输和注入。只不过有一个差别:get请求的参数是暴露url地址的后面。而post请求是通过请求体进行传输的。
-
所以,get请求的url和参数,每隔浏览器都会限制长度,比如:google 8k~10K .如果超过自动截取丢失。所以get请求不是说做不到数据的传递和注入,是因为长度有限制。post目前可以支持2M。而且不会暴露在url地址后面是通过请求body传输的。
-
也就是告诉你一个道理。在开发中,不要总是纠结于提交表单只能post的这个谬论。
-
但是为安全起见,确实在开发中,我们只要做注册或者添加数据时候都只考虑post。
你必须要知道是事情?-前端部分
-
label 是form表单的关系户标签,只要form元素(input,radio,select.checkbox,textarea)被label包裹的话,文本部分和元素不论你点击元素还是点文档都自动获取焦点。这也为什么说你经常在form表单定义中经常看到label标签的原因。
-
button、submit它们都自动提交form能力
-
form如果不指定method请求方式就是get请求
-
如果你选择用异步去提交了。button和submit这个默认能力你就要去卸载掉。button和submit只用ajax去处理,不用form去处理。
Jquery的异步总结
-
不论你是get还是post在后端,不论你是对象还是单个参数启动都是可以进入注入和获取的。
-
JQuery操作的dom节点,很多时候我们都是先要找到元素,才进行操作(事件处理,加样式,添加内容等)
Vue3+ Axios处理异步请求
vue和jquery的区别
-
vue去dom化
-
jquery围绕dom
Axios的认识
axios也是对XMLHttpRequest的封装,只不过它通过es6的语法Promise(承诺)来进行封装。
-
从浏览器中创建 XMLHttpRequests
-
从 node.js 创建 http 请求
-
支持 Promise API
-
拦截请求和响应
-
转换请求数据和响应数据
-
取消请求 (timeout 10s)
-
自动转换 JSON 数据
-
客户端支持防御 XSRF
如何使用Axios
-
使用自带
-
Promise
axios#request(config) axios#get(url[, config]) axios#delete(url[, config]) axios#head(url[, config]) axios#options(url[, config]) axios#post(url[, data[, config]]) axios#put(url[, data[, config]]) axios#patch(url[, data[, config]])
常用就是: get 和 post
-
-
自己创建axios对象
-
什么情况会去创建呢?未来如果你异步请求需要有拦截器机制或者通用处理。肯定自己去创建会更好一些。
-
request.js
const request = axios.create({ baseURL: 'https://api.example.com', timeout: 1000, headers: {'X-Custom-Header': 'foobar'} }); // 添加请求拦截器 request.interceptors.request.use(function (config) { var token = cache.getToken(); // 在发送请求之前做些什么 config.headers = { 'X-Requested-With': 'XMLHttpRequest', 'token':token }; return config; }, function (error) { // 对请求错误做些什么 return Promise.reject(error); }); // 添加响应拦截器 request.interceptors.response.use(function (response) { if(res.data.code == 500){ alert("服务器错误....") return; } // 对响应数据做点什么 return response.data; }, function (error) { // 对响应错误做点什么 return Promise.reject(error); }); export default request;
index.vue <template> <div v-for="(user,user) in users">{{user.username}}</div> </template> <scrcipt setup> import request from '@/utils/request.js' import axios from 'axios' var users = reactive([]); onMounted(()=>{ request.get("/admin/user/list").then(res=>{ users = res.data; }) }); </script>
-
Axios 的请求配置
axios.post(“http://localhost:8699/admin/”)
{ // `url` 是用于请求的服务器 URL url: '/user', // `method` 是创建请求时使用的方法 method: 'get', // default // `baseURL` 将自动加在 `url` 前面,除非 `url` 是一个绝对 URL。 // 它可以通过设置一个 `baseURL` 便于为 axios 实例的方法传递相对 URL baseURL: 'https://some-domain.com/api/', // `transformRequest` 允许在向服务器发送前,修改请求数据 // 只能用在 'PUT', 'POST' 和 'PATCH' 这几个请求方法 // 后面数组中的函数必须返回一个字符串,或 ArrayBuffer,或 Stream transformRequest: [function (data, headers) { // 对 data 进行任意转换处理 return data; }], // `transformResponse` 在传递给 then/catch 前,允许修改响应数据 transformResponse: [function (data) { // 对 data 进行任意转换处理 return data; }], // `headers` 是即将被发送的自定义请求头 headers: {'X-Requested-With': 'XMLHttpRequest'}, // `params` 是即将与请求一起发送的 URL 参数 // 必须是一个无格式对象(plain object)或 URLSearchParams 对象 params: { ID: 12345 }, // `paramsSerializer` 是一个负责 `params` 序列化的函数 // (e.g. https://www.npmjs.com/package/qs, http://api.jquery.com/jquery.param/) paramsSerializer: function(params) { return Qs.stringify(params, {arrayFormat: 'brackets'}) }, // `data` 是作为请求主体被发送的数据 // 只适用于这些请求方法 'PUT', 'POST', 和 'PATCH' // 在没有设置 `transformRequest` 时,必须是以下类型之一: // - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams // - 浏览器专属:FormData, File, Blob // - Node 专属: Stream data: { firstName: 'Fred' }, // `timeout` 指定请求超时的毫秒数(0 表示无超时时间) // 如果请求话费了超过 `timeout` 的时间,请求将被中断 timeout: 1000, // `withCredentials` 表示跨域请求时是否需要使用凭证 withCredentials: false, // default // `adapter` 允许自定义处理请求,以使测试更轻松 // 返回一个 promise 并应用一个有效的响应 (查阅 [response docs](#response-api)). adapter: function (config) { /* ... */ }, // `auth` 表示应该使用 HTTP 基础验证,并提供凭据 // 这将设置一个 `Authorization` 头,覆写掉现有的任意使用 `headers` 设置的自定义 `Authorization`头 auth: { username: 'janedoe', password: 's00pers3cret' }, // `responseType` 表示服务器响应的数据类型,可以是 'arraybuffer', 'blob', 'document', 'json', 'text', 'stream' responseType: 'json', // default // `responseEncoding` indicates encoding to use for decoding responses // Note: Ignored for `responseType` of 'stream' or client-side requests responseEncoding: 'utf8', // default // `xsrfCookieName` 是用作 xsrf token 的值的cookie的名称 xsrfCookieName: 'XSRF-TOKEN', // default // `xsrfHeaderName` is the name of the http header that carries the xsrf token value xsrfHeaderName: 'X-XSRF-TOKEN', // default // `onUploadProgress` 允许为上传处理进度事件 onUploadProgress: function (progressEvent) { // Do whatever you want with the native progress event }, // `onDownloadProgress` 允许为下载处理进度事件 onDownloadProgress: function (progressEvent) { // 对原生进度事件的处理 }, // `maxContentLength` 定义允许的响应内容的最大尺寸 maxContentLength: 2000, // `validateStatus` 定义对于给定的HTTP 响应状态码是 resolve 或 reject promise 。如果 `validateStatus` 返回 `true` (或者设置为 `null` 或 `undefined`),promise 将被 resolve; 否则,promise 将被 rejecte validateStatus: function (status) { return status >= 200 && status < 300; // default }, // `maxRedirects` 定义在 node.js 中 follow 的最大重定向数目 // 如果设置为0,将不会 follow 任何重定向 maxRedirects: 5, // default // `socketPath` defines a UNIX Socket to be used in node.js. // e.g. '/var/run/docker.sock' to send requests to the docker daemon. // Only either `socketPath` or `proxy` can be specified. // If both are specified, `socketPath` is used. socketPath: null, // default // `httpAgent` 和 `httpsAgent` 分别在 node.js 中用于定义在执行 http 和 https 时使用的自定义代理。允许像这样配置选项: // `keepAlive` 默认没有启用 httpAgent: new http.Agent({ keepAlive: true }), httpsAgent: new https.Agent({ keepAlive: true }), // 'proxy' 定义代理服务器的主机名称和端口 // `auth` 表示 HTTP 基础验证应当用于连接代理,并提供凭据 // 这将会设置一个 `Proxy-Authorization` 头,覆写掉已有的通过使用 `header` 设置的自定义 `Proxy-Authorization` 头。 proxy: { host: '127.0.0.1', port: 9000, auth: { username: 'mikeymike', password: 'rapunz3l' } }, // `cancelToken` 指定用于取消请求的 cancel token // (查看后面的 Cancellation 这节了解更多) cancelToken: new CancelToken(function (cancel) { }) }
Axios 响应结构
{ // `data` 由服务器提供的响应 data: { code:200, message:"success", data:{} }, // `status` 来自服务器响应的 HTTP 状态码 status: 200, // `statusText` 来自服务器响应的 HTTP 状态信息 statusText: 'OK', // `headers` 服务器响应的头 headers: {}, // `config` 是为请求提供的配置信息 config: {}, // 'request' // `request` is the request that generated this response // It is the last ClientRequest instance in node.js (in redirects) // and an XMLHttpRequest instance the browser request: {} }
Axios的完整写法如下
-
axios(config)
// 发送 POST 请求 axios({ method: 'post', url: '/user/12345', data: { firstName: 'Fred', lastName: 'Flintstone' } }); // 获取远端图片 axios({ method:'get', url:'http://bit.ly/2mTM3nY', responseType:'stream' }) .then(function(response) { response.data.pipe(fs.createWriteStream('ada_lovelace.jpg')) });
-
axios(url[, config])
// 发送 GET 请求(默认的方法) axios('/user/12345');
axios变体
axios#request(config) axios#get(url[, config]) axios#delete(url[, config]) axios#head(url[, config]) axios#options(url[, config]) axios#post(url[, data[, config]]) axios#put(url[, data[, config]]) axios#patch(url[, data[, config]]
Axios.propertype.get = function(url,params){ return axios({method:'get',url:url,params}); } Axios.propertype.post = function(url,data){ return axios({method:'post',url:url,data}); } ["get","post","delete","patch"].forEach(m=>{ Axios.propertype[m] = function(url,data){ return axios({method:m,url:url,data}); } }) var axios = new Axios(); var request = new Axios(); var xiyuan = new Axios();
Axios的get请求传递参数的两种方式
1:直接拼接
// 记住?记得加哦!!! var params = "? pageNo="+this.pageNo+"&pageSize="+this.pageSize+"&keyword="+this.keyword; request.get("/admin/v/user/load"+params).then((res)=>{ this.userList = res.data.records; this.total = res.data.total; this.pages = res.data.pages; })
2:使用params
request.get("/admin/v/user/load",{ params:{ pageNo:this.pageNo, pageSize:this.pageSize, keyword:this.keyword } }).then((res)=>{ this.userList = res.data.records; this.total = res.data.total; this.pages = res.data.pages; }) ## 或者 var params = { pageNo:this.pageNo, pageSize:this.pageSize, keyword:this.keyword }; request.get("/admin/v/user/load",{params:params}).then((res)=>{ this.userList = res.data.records; this.total = res.data.total; this.pages = res.data.pages; })
请求的过程:
服务端代码:
对象写法:
/** * 用户分页查询 * 接口路径:/admin/user/load * * @param userVo * @param userVo * @return */ @GetMapping("/v/user/load") public IPage<UserBo> findUserPages(UserVo userVo, HttpServletRequest request, HttpServletResponse response) { System.out.println(request.getHeader("token")); System.out.println(request.getHeader("X-Custom-Header")); // 1: 定义分页 Page<User> page = new Page(userVo.getPageNo(), userVo.getPageSize()); // 2:设置查询条件 LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>(); lambdaQueryWrapper.like(!StringUtils.isEmpty(userVo.getKeyword()), User::getNickname, userVo.getKeyword()); lambdaQueryWrapper.eq(User::getIsDelete, 0); lambdaQueryWrapper.orderByDesc(User::getCreateTime); // 3: 查询分页 Page<User> page1 = userService.page(page, lambdaQueryWrapper); List<User> records = page1.getRecords(); // 4 : 返回的数据 Page<UserBo> page2 = new Page<>(); List<UserBo> userBoList = records.stream().map(user -> { UserBo userBo = new UserBo(); BeanUtils.copyProperties(user, userBo); return userBo; }).collect(Collectors.toList()); page2.setRecords(userBoList); page2.setTotal(page.getTotal()); page2.setSize(page.getSize()); page2.setPages(page.getPages()); page2.setCurrent(page.getCurrent()); response.setHeader("token","00000000"); return page2; }
非对象写法:
@GetMapping("/v/user/load") public IPage<UserBo> findUserPages(Integer pageNo , Integer pageSize, String keyword, HttpServletRequest request, HttpServletResponse response) { System.out.println(request.getHeader("token")); System.out.println(request.getHeader("X-Custom-Header")); UserVo userVo = new UserVo(); userVo.setKeyword(keyword); userVo.setPageNo(pageNo); userVo.setPageSize(pageSize); // 1: 定义分页 Page<User> page = new Page(userVo.getPageNo(), userVo.getPageSize()); // 2:设置查询条件 LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>(); lambdaQueryWrapper.like(!StringUtils.isEmpty(userVo.getKeyword()), User::getNickname, userVo.getKeyword()); lambdaQueryWrapper.eq(User::getIsDelete, 0); lambdaQueryWrapper.orderByDesc(User::getCreateTime); // 3: 查询分页 Page<User> page1 = userService.page(page, lambdaQueryWrapper); List<User> records = page1.getRecords(); // 4 : 返回的数据 Page<UserBo> page2 = new Page<>(); List<UserBo> userBoList = records.stream().map(user -> { UserBo userBo = new UserBo(); BeanUtils.copyProperties(user, userBo); return userBo; }).collect(Collectors.toList()); page2.setRecords(userBoList); page2.setTotal(page.getTotal()); page2.setSize(page.getSize()); page2.setPages(page.getPages()); page2.setCurrent(page.getCurrent()); response.setHeader("token","00000000"); return page2; }
Axios的Post请求的唯一方式
1: jquery的post传递参数
var params = this.user; $.post("/admin/v/user/save",params);
所以在后台的时候,我们不论是单个定义还是对象对应,都可以注入参数对对应的属性中。也不限制请求方式、
2:axios的post传递参数
var params = this.user; request.post("user/save",params).then(res=>{ console.log("服务器返回的数据是:",res) alert("注册成功") }).catch(err=>{ console.log(err); })
服务端代码如下:
@PostMapping("/v/user/save") public String findUserPages(@RequestBody UserRegVo userRegVo) { User user = new User(); BeanUtils.copyProperties(userRegVo, user); user.setForbbiden(1); user.setIsDelete(0); return userService.saveOrUpdate(user) ? "success" : "fail"; }