复盘工作-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];
          },
}

 

posted on 2024-05-23 05:28  平凡力量  阅读(23)  评论(0编辑  收藏  举报