复盘工作-2024-05
2024-05-22
1.java break continue
String[] arr = {"2", "4", "6", "8"}; for (int i = 0; i < arr.length; i++) { if (i != 1) { System.out.println(arr[i]); } else { // break 直接终止并跳出当前这个(最内层循环),继续执行这个循环块后面的代码(如果有的话) // 即最终输出2 break; } } List<String> list = new ArrayList<>(Arrays.asList("2", "4", "6", "8")); for (int i = 0; i < list.size(); i++) { if (i != 1) { System.out.println(list.get(i)); } else { // continue 终止本次循环,继续执行下一次循环,即执行下一次i+1循环体 // 即最终输出2,6,8 continue; } }
2.js遍历数组
let arr = [2, 4, 6, 8]; for (let i = 0; i < arr.length; i++) { console.log(arr[i]); } for (let item of arr) { console.log(item); }
3.jrxml文件格式是xml文件的一种,可以理解为是xml的一个子集。
4.spring-mvc-timeTask.xml是springmvc配置文件之一。
5.设置方法为异步方法:
spring配置文件spring-mvc-timeTask.xml中配置:
<task:annotation-driven executor="executor"/> <task:excutor id="executor" pool-size="5"/>
service层方法加注解:
@Service("smiService") public class SmiServiceImpl extends CommonServiceImpl implements SmiServiceI { @Async @Override public void addS() { // 方法体 } }
测试:
异步方法里:
System.out.println("start async: " + System.currentTimeMillis()); try { // 需要catch InterruptedException Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("end async: " + System.currentTimeMillis());
主方法里:
System.out.println("main query: " + System.currentTimeMillis());
最终尽管异步方法写在代码前面,但最终主方法先打印,业务完成后,异步方法执行完,证明异步没问题:
main query: 1716382319640 start async: 1716382319640 end async: 1716382324652
2024-05-23
1.@Async加在服务层方法上,指示Spring容器在单独的线程中异步执行该方法。
2.js判断是否含有子串
let str = 'Hello, World!'; let subStr = 'World'; if (str.includes(subStr)){ console.log("含有子串"); } else { console.log("不含子串"); }
3.oracle 清空表数据,但不清空表结构:
truncate table SYS_USER_TEST;
oracle 清空表数据,同时清空表结构:
drop table SYS_USER_TEST;
4.Lambda表达式 /ˈlæmdə/
Runnable接口写法
public class RunnableTest1 { public static void main(String[] args) { new Thread(new Runnable() { @Override public void run() { System.out.println("thread begin: " + System.currentTimeMillis()); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("thread end: " + System.currentTimeMillis()); } }).start(); System.out.println("main: " + System.currentTimeMillis()); } }
Lambda表达式写法
() -> {} Lambda表达式,是 一个实现了Runnable接口的匿名类的实例的简写,即 创建了一个无参数(由()标识),且无返回值(由没有指定返回类型以及没有return语句的{}块表示)的匿名函数
public class LambdaTest1 { public static void main(String[] args) { // () -> {} Lambda表达式,是 一个实现了Runnable接口的匿名类的实例的简写, // 即 创建了一个无参数(由()标识),且无返回值(由没有指定返回类型以及没有return语句的{}块表示)的匿名函数 new Thread(() -> { System.out.println("thread begin: " + System.currentTimeMillis()); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("thread end: " + System.currentTimeMillis()); }).start(); System.out.println("main: " + System.currentTimeMillis()); } }
2024-05-25
1.Stream()相关API
public class StreamTest1 { public static void main(String[] args) { List<Integer> l1 = Arrays.asList(7, 2, 1, 3, 5, 9); List<Integer> l2 = new ArrayList<>(); // filter()和collect()是Stream接口定义的方法 l2 = l1.stream().filter(item -> item > 5).collect(Collectors.toList()); // l2=[7, 9] System.out.println("l2=" + l2); List<Object> l3 = new ArrayList<>(); l1.stream().forEach(item -> { if (item > 3) { l3.add(item); } }); // l3=[7, 5, 9] System.out.println("l3=" + l3); List<String> l4 = Arrays.asList("7", "2", "1"); List<Integer> l5 = new ArrayList<>(); l5 = l4.stream() .map(s -> Integer.parseInt(s)) // Integer.parseInt(String s) 返回值int .filter(i -> i % 2 == 0) // 过滤出偶数 .collect(Collectors.toList()); // 输出l5:[2] System.out.println("l5:" + l5); } }
2024-05-25
1.stream api学习
public class StreamTest2 { public static void main(String[] args) { // map 映射 List<String> strings = Arrays.asList("a1", "b2", "c3"); List<Integer> integers = strings.stream() // String api .substring(int index)返回index这个索引开始的子串 .map(s -> s.substring(1)) .map(s -> Integer.parseInt(s)) .collect(Collectors.toList()); // map test: integers: [1, 2, 3] System.out.println("map test: integers: " + integers); // filter 过滤 List<String> startsWithB = strings.stream() .filter(s -> s.startsWith("b")) .collect(Collectors.toList()); // filter: startsWithB: [b2] System.out.println("filter: startsWithB: " + startsWithB); // sort 排序 // sorted默认自然排序,对字符串就是字典排序 List<String> fruits = Arrays.asList("orange", "apple", "banana"); List<String> ascFruits = fruits.stream() .sorted() .collect(Collectors.toList()); // asc sort: ascFruits: [apple, banana, orange] System.out.println("asc sort: ascFruits: " + ascFruits); // 使用比较器降序 List<String> usingComparatorReverseOrderMethodList = fruits.stream() .sorted(Comparator.reverseOrder()) .collect(Collectors.toList()); // sort: usingComparatorReverseOrderMethodList: [orange, banana, apple] System.out.println("sort: usingComparatorReverseOrderMethodList: " + usingComparatorReverseOrderMethodList); // 自定义实现降序 List<String> descFruits = fruits.stream() .sorted((s1, s2) -> s2.compareTo(s1)) .collect(Collectors.toList()); // sort: descFruits: [orange, banana, apple] System.out.println("sort: descFruits: " + descFruits); // reduce 规约 int test67 = Integer.sum(6, 7); // Integer.sum: 13 System.out.println("Integer.sum: " + test67); // 使用Integer类的sum静态方法 List<Integer> testReduceList = Arrays.asList(5, -3, 10, -2); Integer sum = testReduceList.stream() .reduce(0, Integer::sum); // reduce: sum: 10 System.out.println("reduce: sum: " + sum); // match 匹配 boolean anyStartsWitha = fruits.stream() .anyMatch(s -> s.startsWith("a")); // match: anyStartsWitha: true System.out.println("match: anyStartsWitha: " + anyStartsWitha); boolean allMatchStartsWitha = fruits.stream() .allMatch(s -> s.startsWith("a")); // match: allMatchStartsWitha: false System.out.println("match: allMatchStartsWitha: " + allMatchStartsWitha); boolean noneMatchStartsWitha = fruits.stream() .noneMatch(s -> s.startsWith("a")); // match: noneMatchStartsWitha: false System.out.println("match: noneMatchStartsWitha: " + noneMatchStartsWitha); } }
2.js初始化数组及箭头函数=>
let oriArr = [6, 5, 4, 3]; let bigger4 = oriArr.filter(item => item > 4); // [6, 5] console.log(bigger4);
3.android studio打包打不出apk:提示:Build APK(s):APK(s) generated successfully for 0 modules:
看项目MainActivity.java报错Cannot resolve symbol 'ActivityCompat':
分析:缺少依赖库,ActivityCompat是AndroidX库的一部分,看app模块build.gradle有修改,点击工具栏“sync project with gradle files”,报错解决,然后可以正常打包了。
4.vue,v-if前不应该有:,分析:
:是用来绑定一个元素属性到一个表达式的结果的。而v-if是一个指令,指令不应该有:前缀。
5.spring的@Autowired注入时一定要是接口类型
/* * 这里注入时,一定是TestUserServiceI即接口, * 而不能是实现类 * * 因为TestServiceImpl类上会加@Service("testUserService")注解 * spring自动装配(Autowiring)根据TestUserServiceI, * 就能查找到并注入实现了TestUserServiceI的合格Bean(即TestServiceImpl实现类) */ @Autowired private TestUserServiceI testUserService;
这里注入时,一定是TestUserServiceI即接口,而不能是实现类 因为TestServiceImpl类上会加@Service("testUserService")注解 spring自动装配(Autowiring)根据TestUserServiceI, 就能查找到并注入实现了TestUserServiceI的合格Bean(即TestServiceImpl实现类)
service接口:
public interface TestUserServiceI extends CommonService { public void sayHello(); }
serviceImpl接口实现:
@Service("testUserService") public class TestUserServiceImpl extends CommonServiceImpl implements TestUserServiceI { @Override public void sayHello() { System.out.println("hello, world!"); } }
controller层:
/* * 这里注入时,一定是TestUserServiceI即接口, * 而不能是实现类 * * 因为TestServiceImpl类上会加@Service("testUserService")注解 * spring自动装配(Autowiring)根据TestUserServiceI, * 就能查找到并注入实现了TestUserServiceI的合格Bean(即TestServiceImpl实现类) */ @Autowired private TestUserServiceI testUserService; // 然后具体业务方法里调用testUserService.sayHello();
2024-05-26
1.前端请求后端时使用模版字符串:增强代码可读性且更简便。以反引号·来定义开始和结束,用${变量名}来直接取值组装字符串
const _self = this; let readStatus = 'WD'; let username = 'test'; // 前端请求后端时使用“模版字符串”:增强代码可读性且更简便。以反引号·来定义开始和结束,用${变量名}来直接取值组装字符串 // 代码目前前后端暂时未调通(正在调试),可能有误 let url = `testUserController.do?getUsers&readStatus=${readStatus}&username=${username}`;
2.后端controller的请求路径一定是写在@RequestMapping上,而不是@Controller上
/** * 代码目前前后端暂时未调通(正在调试),可能有误 * @Controller注解后面不能接("testUserController"),这个要跟在@RequestMapping后面 */ @RequestMapping("api/testUserController") @Controller public class TestUserController {}
2024-05-27
1.前端请求后端url分析:
url分析
1.1 “/“是“路径分隔符”,testUser和getUsers是路径的两个部分。 在HTTP请求中,路径部分通常用来定位服务器上的资源 本例子中对应两个资源:controller的mapping“testUser”和方法的mapping“getUser” 本例子中,资源指服务器上能处理特定请求的代码(即controller中的方法)
1.2 ”?“是“查询参数分隔符”,用来分隔url中的路径部分和查询参数部分
1.3 ”&“是“查询参数间的分隔符”,每个参数都是“键=值”对,键和值之间以=分隔
前端请求:
getUsers() { const _self = this; let readStatus = 'WD'; let username = 'tom'; // 前端请求后端时使用模版字符串:增强代码可读性且更简便。以反引号·来定义开始和结束,用${变量名}来直接取值组装字符串 // url分析: // /是“路径分隔符”,testUser和getUsers是路径的两个部分。 // 在HTTP请求中,路径部分通常用来定位服务器上的资源 // 本例子中对应两个资源:controller的mapping“testUser”和方法的mapping“getUser” // 本例子中,资源指服务器上能处理特定请求的代码(即controller中的方法) // ?是“查询参数分隔符”,用来分隔url中的路径部分和查询参数部分 // &是“查询参数间的分隔符”,每个参数都是“键=值”对,键和值之间以=分隔 let url = `testUser/getUsers?readStatus=${readStatus}&username=${username}`; _self.request.getList({ url: url }) .then((response) => { if (response && response.data && response.data.result && response.data.result.records && response.data.result.records.list && response.data.result.records.readStatus && response.data.result.records.username) { let resArr = response.data.result.records.list let resReadStatus = response.data.result.records.readStatus let resUsername = response.data.result.records.username console.log('resArr: ' + resArr); console.log('resReadStatus: ' + resReadStatus); console.log('resUsername: ' + resUsername); } }) .catch(error => { console.log('error: ' + error); }) },
后端:
/** * @Controller注解后面不能接("testUserController"),这个要跟在@RequestMapping后面 */ @RequestMapping("/api/testUser") @Controller public class TestUserController extends BaseController { @RequestMapping(value = "/getUsers", method = RequestMethod.GET) @ResponseBody public Result getUsers(@RequestParam("readStatus") String readStatus, @RequestParam("username") String username) { List<String> users = Arrays.asList("zhangsan", "lisi", "wangwu"); Map<String, Object> map = new HashMap<>(); Map<String, Object> records = new HashMap<>(); records.put("list", users); records.put("readStatus", readStatus); records.put("username", username); map.put("records", records); Result result = new Result(); result.setResult(map); return result; } }
2024-05-28
1.后端报错“org.hibernate.hql.internal.ast.QuerySyntaxException: SmiEntity is not mapped”:
解决:先检查实体上是否有@Entity注解;有注解继续排查:原因是新建的包下的SmiEntity类并没有被扫描到,需要修改hibernate配置文件。
2.springmvc后端接收复杂对象参数
@RequestParam适合接收简单类型,例如String int boolean
对象等复杂类型可用@RequestBody来接收
封装DTO接收
前端请求:
updateStatus() { const _self = this; let userIds = new Array(); userIds.push('id1'); userIds.push('id2'); userIds.push('id3'); let status = 'BLOCKED'; let url = 'testRequestBody/updateStatusByIds'; _self.request.post({ url: url, data: { userIds: userIds, status: status } }).then(response => { // }).catch(error => { console.log(error); }) },
后端接收请求:
controller:
/** * @RequestParam适合接收简单类型,例如String int boolean * * 对象等复杂类型可用@RequestBody来接收 * 封装DTO接收 */ @Controller @RequestMapping("/api/testRequestBody") public class TestRequestBodyController extends BaseController { @RequestMapping(value = "/updateStatusByIds", method= RequestMethod.POST) @ResponseBody public void updateStatusByIds(@RequestBody TestUserDTO dto) { List<String> userIds = dto.getUserIds(); String status = dto.getStatus(); // dto.getUserIds: [id1, id2, id3] System.out.println("dto.getUserIds: " + userIds); // dto.getStatus: BLOCKED System.out.println("dto.getStatus: " + status); } }
DTO:
public class TestUserDTO { private List<String> userIds; private String status; public List<String> getUserIds() { return userIds; } public void setUserIds(List<String> userIds) { this.userIds = userIds; } public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } }
2024-05-29
1.理解mysql的longtext类型:用于存储大量的文本数据(最大4GB),当要存储超过text(最大65536字节即64KB)、mediumtext(最大16MB)时可以用longtext。
2.关于java定义常量时的static:
static定义静态的,若不加此定义,则常量类的每个实例对象都要有自己的这个属性,浪费内存资源
加上static后该常量属性对整个类共享,从而避免浪费内存资源,
且使用更简便直接”xxxConstant.常量名“即可访问
/** * static定义静态的,若不加此定义,则常量类的每个实例对象都要有自己的这个属性,浪费内存资源 * 加上static后该常量属性对整个类共享,从而避免浪费内存资源, * 且使用更简便直接”xxxConstant.常量名“即可访问 */ public static final String MSG_TYPE_GZ = "故障";
3.对input框加上disabled属性,禁用输入框。input自闭合标签,不能写成<input></input>
<input id="testInput" disabled>
4.jsp控制是否显示的c:if的test的表达式,判断一定是写在${}里面
<c:if test="${sMiPage.xxx == '测试'}" >66666</c:if>
2024-05-30
1.<textarea>${smiInfo.xxx}</textarea>,<textarea>标签没有value属性。这点不同于<input>标签。
<!-- td: table data 表格数据项 --> <!-- align="right" 左对齐 --> <td align="right"> <!-- label标签 --> <label>测试文本域:</label> </td> <!-- colspan设置跨多少列 --> <td colspan="5"> <!-- textarea文本域,设置id便于js等通过id定位元素,name用于表单提交时定位属性,rows设置默认跨多少行,style设置宽度为父组件的98% --> <textarea id="messageContent" name="messageContent" rows="3" style="width: 98%;">${smiInfo.messageContent}</textarea> </td>
2.在js中定义函数一定要加function关键词,至于vue的method里面不加function其实是一种语法糖
<script type="text/javascript"> // 这个关键词function一定不能省略 function sayHelloButtonClick() { alert('hello, world!'); } </script>
3.Ajax请求格式
<script type="text/javascript"> function saveSmi() { let formdata = { // id选择器获取值 'title': $("#title").val(), 'content': $("#content").val() } $.ajax({ // 获取id为form的表单的action属性 // 即为形如"smi.do?doSaveOrUpdate"的表单提交方法 // 这里注意,.attr()获取的是属性值即一个字符串, // 不是对象了,所以.attr()后面不能再跟什么.val()了 url: $("#form").attr("action"), // 设置请求格式为post请求 type: "post", data: formdata, // 设置后端响应格式为json dataType: "json", // 请求后端成功时的处理函数 success: function (data) { let d = data; if (d.success && d.obj) { // 逻辑处理 let busiObj = d.obj; tip(d.msg); // 自定义提示 } else { tip(d.msg); } } // 请求后端失败时的处理函数 error: function (jqXHR, textStatus, errorThrown) { console.log('error: ' + textStatus, errorThrown); } }) // 结束$.ajax } </script>
2024-05-31
1.java List判断是否含某元素:.contains方法
List<String> fruits = Arrays.asList("apple", "banana", "orange"); // java List判断是否含某元素:.contains方法 if (fruits.contains("apple")) { // fruits contains apple! System.out.println("fruits contains apple!"); } else { System.out.println("fruits don't contains apple"); }
2.vue子组件watch监听父组件传参变化
子组件ShowUpCaseComponent.vue:
<template> <div> <input :value="resultWord"></input> </div> </template> <script> export default { name: "ShowUpCaseComponent", props: { word: { type: String, // 我一开始写的defaultValue: 'java'有误, // 是错误语法,导致没有默认值, // 若父组件不传word,_self.word.toUpperCase()会报错vue.esm.js:1896 // TypeError: Cannot read properties of undefined (reading 'toUpperCase') // 正确写法是default: 'java' default: 'java' } }, data() { return { resultWord: 'vue' } }, mounted() { debugger; this.changeUpCase(); }, // 这里一定是methods: {} // 我一开始写为method: {},则会报错TypeError: // this.changeUpCase is not a function // methods: {} 定义组件中可用的方法 methods: { changeUpCase() { debugger; const _self = this; // 我最早写作_self.word = 'HELLO, ' + _self.word.toUpCase() + '!'; // 有两个错误: // 1.报错TypeError: _self.word.toUpCase is not a function // 实际应该是 toUpperCase()、toLowerCase() // 2.报错You may have an infinite update loop in watcher with expression "word" // 潜在的无限更新循环 // 第二个错误是把父组件传来的值给更新了,这是不允许的 _self.resultWord = 'HELLO, ' + _self.word.toUpperCase() + '!'; } }, watch: { // 我一开始写作function(oldVal, newVal)其实是有误的 // 因为打断点调试可以发现,当指定两个参数时, // 第一个参数是新的newVal,第二个参数是老的oldVal word: function(newVal, oldVal) { debugger; const _self = this; // 使用!==进行严格比较,区分null、undefined和空字符串情况 if (newVal !== oldVal) { _self.changeUpCase(); } } // 当function只指定一个参数val时,function(val) // 监听到时,val就是指的新值 // word: function(val) { // debugger; // const _self = this; // if (val) { // _self.changeUpCase(); // } // } } } </script> <style scoped> </style>
父组件:
<show-up-case-component :word="testWord"></show-up-case-component> <!-- 我一开始写作:<button onclick="setTestWord()">666666</button> --> <!-- 报错Uncaught ReferenceError: setTestWord is not defined --> <!-- 解释: 为什么onclick不好使?@click就好使? --> <!-- 在vue.js中,onclick是原生js处理器, 而@click是vue的事件监听指令。 两者有根本性区别。主要体现在作用域和上下文环境上。 1.作用域问题: 1.1在使用原生onclick属性时, 它期望在全局作用域中找到一个名为“setTestWord"的函数。 1.2但是在vue组件中定义的methods并不是全局的, 它们是组件实例的方法, 无法全局直接访问 2.上下文问题: 2.1在原生js中this的指向取决于函数如何被调用。 如果你在onclick中直接使用setTestWord, 那么当函数被执行时, this可能不会指向你的vue组件实例, 导致你无法访问vue实例的数据和方法 2.2在vue的@click中, vue自动处理了this的指向问题, 确保this总是指向当前的vue组件实例。 --> <!-- 即onclick="setTestWord()"时, 浏览器在全局作用域查找setTestWord, 未定义。因为其只存在于vue组件局部作用域中, 所以抛出Uncaught ReferenceError: setTestWord is not defined --> <button @click="setTestWord()">测试</button> import ShowUpCaseComponent from '@/views/apptabbar/ShowUpCaseComponent'; // 我一开始没写components: {} // 报错[Vue warn]: Unknown custom element: <show-up-case-component> - did you register the component correctly? // For recursive components, make sure to provide the "name" option. // coponents: {} 在父组件中注册子组件 components: {ShowUpCaseComponent}, data() { return{ indexForTest: 0, testWord: 'pen' } }, methods: { // 最终效果是初始化子组件默认显示“HELLO,PEN!" // 然后随着每次点击“测试”, // 后续从HELLO,BANANA->HELLO,ORANGE->....->HELLO,APPLE, // 反复循环遍历数组展示 setTestWord(){ debugger; const _self = this; let arr = ['apple', 'banana', 'orange', 'pear', 'water']; let index = (_self.indexForTest + 1) % 5; _self.indexForTest = _self.indexForTest + 1; _self.testWord = arr[index]; }, }