public class Person {
private String name;
public void setName(String newName) {
this.name = newName;
}
public String getName() {
return this.name;
}
}
一个名为 Person 的类中包含私有的属性 name 和公共的方法 setName() 和 getName(),其他类只能通过公共的方法来访问和修改 name 属性,而无法直接访问它。
public class Animal {
public void eat() {
// 吃东西的行为
}
public void sleep() {
// 睡觉的行为
}
}
public class Dog extends Animal {
public void bark() {
// 狗叫的行为
}
}
假设有一个 Animal 类作为父类,其中包含 eat() 和 sleep() 方法,然后有一个 Dog 类作为子类继承自 Animal类。Dog 类可以继承 eat() 和 sleep() 方法,并且可以添加新的方法 bark()。
public void makeSound(Animal animal) {
animal.makeNoise();
}
使用动物类的例子,可以有一个方法接受 Animal 对象作为参数,当传入 Dog 对象时,调用 bark() 方法,当传入 Cat 对象时,调用 meow() 方法。
在 Java 8 之后,接口也可以包含默认方法和静态方法的实现。
抽象类用于表示 is-a 关系,而接口用于表示 has-a 关系。抽象类更关注于共享代码和数据,而接口更关注于定义行为。
在Java中,表示价格可以使用BigDecimal类型来更好地处理精确的十进制数值。BigDecimal提供了高精度的数学运算和舍入规则,适用于表示货币和其他需要精确计算的场景。
方法 | 介绍 |
---|---|
length() | 返回字符串的长度 |
charAt(int index) | 返回指定索引位置的字符 |
substring(int beginIndex) | 返回从指定索引开始到字符串末尾的子字符串 |
substring(int beginIndex, int endIndex) | 返回指定索引范围内的子字符串(不包括 endIndex 处的字符) |
equals(Object anObject) | 比较字符串内容是否相等 |
equalsIgnoreCase(String anotherString) | 忽略大小写,比较字符串内容是否相等 |
indexOf(int ch) | 返回指定字符在字符串中第一次出现的位置 |
indexOf(int ch, int fromIndex) | 从指定位置开始,返回指定字符在字符串中第一次出现的位置 |
indexOf(String str) | 返回子字符串在字符串中第一次出现的位置 |
indexOf(String str, int fromIndex) | 从指定位置开始,返回子字符串在字符串中第一次出现的位置 |
lastIndexOf(int ch) | 返回指定字符在字符串中最后一次出现的位置 |
lastIndexOf(int ch, int fromIndex) | 从指定位置开始,返回指定字符在字符串中最后一次出现的位置 |
lastIndexOf(String str) | 返回子字符串在字符串中最后一次出现的位置 |
lastIndexOf(String str, int fromIndex) | 从指定位置开始,返回子字符串在字符串中最后一次出现的位置 |
replace(char oldChar, char newChar) | 将字符串中所有匹配的旧字符替换为新字符 |
replaceAll(String regex, String replacement) | 使用给定的替换字符串替换所有与给定的正则表达式匹配的子字符串 |
toLowerCase() | 将字符串转换为小写形式 |
toUpperCase() | 将字符串转换为大写形式 |
trim() | 去除字符串两端的空白符 |
split(String regex) | 根据给定的正则表达式拆分字符串 |
startsWith(String prefix) | 判断字符串是否以指定前缀开头 |
endsWith(String suffix) | 判断字符串是否以指定后缀结尾 |
在Java中,反射机制提供了一组类用于在运行时动态地操作类的成员。
public class MyThread extends Thread {
public void run() {
// 线程执行的任务代码
System.out.println("线程执行任务");
}
public static void main(String[] args) {
MyThread myThread = new MyThread(); // 创建线程对象
myThread.start(); // 启动线程
}
}
public class MyRunnable implements Runnable {
public void run() {
// 线程执行的任务代码
System.out.println("线程执行任务");
}
public static void main(String[] args) {
MyRunnable myRunnable = new MyRunnable(); // 创建实现了Runnable接口的对象
Thread thread = new Thread(myRunnable); // 创建线程对象,并将Runnable对象作为参数传递
thread.start(); // 启动线程
}
}
两个或多个线程在互相等待对方释放资源的情况下,导致它们无法继续执行
synchronized (lock) {
lock.notify(); // 唤醒一个等待在lock对象上的线程
}
synchronized (lock) {
lock.notifyAll(); // 唤醒所有等待在lock对象上的线程
}
new 一个 Thread,线程进入了新建状态。调用 start()方法,会启动一个线程并使线程进入了就绪状态,当分配到时间片后就可以开始运行了。 start() 会执行线程的相应准备工作,然后自动执行 run() 方法的内容,这是真正的多线程工作。 但是,直接执行 run() 方法,会把 run() 方法当成一个 main 线程下的普通方法去执行,并不会在某个线程中执行它,所以这并不是多线程工作。
线程锁就是一种同步机制,用于保护共享资源,确保在同一时刻只有一个线程可以访问它,从而避免数据的混乱和不一致。
public synchronized void synchronizedMethod() {
// 同步方法体
}
ReentrantLock lock = new ReentrantLock();
lock.lock();
try {
// 执行需要同步的代码块
} finally {
lock.unlock(); // 在finally块中释放锁,确保锁的释放
}
对于HashMap而言,如果在多线程环境下使用,可以考虑使用ConcurrentHashMap来替代,因为它提供了更好的并发性能。另外,也可以通过Collections.synchronizedMap来将HashMap包装成线程安全的Map
在 Java 中,ArrayList 是最常用的 List 实现之一。当向 ArrayList 中添加元素时,如果当前元素个数已经达到了内部数组的容量上限,就会触发扩容操作。ArrayList 会创建一个新的更大的数组,并将所有元素从旧数组复制到新数组中。默认情况下,新数组的大小是原数组容量的 1.5 倍(可以通过 ensureCapacity 方法或者在构造函数中设置初始容量来进行调整)。
HashMap 使用了链表和红黑树(JDK 8+)来解决哈希冲突,同时也使用了扩容来保证性能。当 HashMap 中的元素个数超过负载因子(默认为 0.75 )与容量的乘积时,HashMap 会进行扩容操作。扩容操作包括创建一个新的数组,将所有的元素重新计算哈希值后放入新的数组中。默认情况下,新数组的大小是原数组容量的两倍。
同步(Synchronous): 在同步模式下,客户端发起一个请求后,必须等待服务器返回响应后才能继续执行后续操作。这意味着当发出请求时,客户端处于阻塞状态,直到收到服务器的响应后才能解除阻塞。
异步(Asynchronous): 在异步模式下,客户端发起一个请求后,不必等待服务器的响应,而是可以继续执行后续操作。当服务器返回响应时,客户端会通过回调函数或事件处理程序来处理响应数据,从而实现页面内容的更新或其他操作。
同步和异步的区别在于是否需要等待服务器的响应。在同步模式下,客户端需要等待服务器响应;而在异步模式下,客户端可以继续执行其他操作,待服务器响应后再处理数据。
GET请求用于获取数据,安全性较低;而POST请求用于提交数据,安全性较高。
在Vue项目中,可以通过在vue.config.js中配置proxy来实现跨域请求。
// vue.config.js
module.exports = {
devServer: {
proxy: {
'/api': {
target: 'http://localhost:3000', // 要代理到哪个域名下
changeOrigin: true, // 允许跨域
pathRewrite: {
'^/api': '', // 将请求路径中的/api替换为空
},
},
},
},
};
@Configuration
public class GlobalCorsConfig {
@Bean
public CorsFilter corsFilter() {
//1. 添加 CORS配置信息
CorsConfiguration config = new CorsConfiguration();
//放行哪些原始域
config.addAllowedOrigin("*");
//放行哪些请求方式
config.addAllowedMethod("*");
//放行哪些原始请求头部信息
config.addAllowedHeader("*");
//暴露哪些头部信息
config.addExposedHeader("*");
//2. 添加映射路径
UrlBasedCorsConfigurationSource corsConfigurationSource = new UrlBasedCorsConfigurationSource();
corsConfigurationSource.registerCorsConfiguration("/**",config);
//3. 返回新的CorsFilter
return new CorsFilter(corsConfigurationSource);
}
}
@Bean
public WebMvcConfigurer MyWebMvcConfigurer(){
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
//放行哪些原始域
.allowedOrigins("*")
.allowedMethods(new String[]{
"GET", "POST", "PUT", "DELETE"})
.allowedHeaders("*")
.exposedHeaders("*");
}
};
@Component
public class CrosFiter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
Filter.super.init(filterConfig);
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) servletResponse;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "x-requested-with,content-type");
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {
Filter.super.destroy();
}
}
@CrossOrigin
//@CrossOrigin(value = "http://localhost:8001") //单独作用在url上
@GetMapping("/Axios")
public String axios(){
return "hello,world";
}
四大特性保证了数据库操作的可靠性和可恢复性。
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
READ-UNCOMMITTED | |||
READ-COMMITTED | × | ||
REPEATABLE-READ | × | × | |
SERIALIZABLE | × | × | × |
重复语句是指代码中多次出现的相同的语句。重复语句可能导致代码冗余,降低代码的可读性和可维护性。检查重复语句可以通过代码重构来消除重复,使代码更加简洁和易于理解。
使用 GROUP BY 和 HAVING 子句进行分组统计
SELECT column, COUNT(*)
FROM table
GROUP BY column
HAVING COUNT(*) > 1;
查找表中某一列包含空值(NULL)的记录的 SQL 查询语句。可以使用 WHERE 子句和 IS NULL 条件来筛选出某一列为空值的记录,也可以使用 COALESCE 函数将空值替换为其他数值进行查询。
SELECT *
FROM table
WHERE column IS NULL;
可以在姓名上建立索引
CREATE INDEX idx_name ON employee (name);
使用SQL语句中的GROUP BY和HAVING子句来实现
sql
SELECT name, COUNT(*) AS count
FROM employee
GROUP BY name
HAVING COUNT(*) > 1;
也可以采用分批次处理的方式,比如每次查询部分数据,然后合并结果,以减少单次查询的数据量
使用游标(cursor)来实现
使用 SELECT DISTINCT 语句可以对结果集进行去重,确保查询结果中的行是唯一的。
SELECT
DISTINCT column
FROM table;
通过将结果集分组并使用聚合函数(如 COUNT、SUM 等),可以去除重复的行。
SELECT
column, COUNT(*)
FROM table
GROUP BY column;
如果数据库支持窗口函数(如 ROW_NUMBER()),可以使用它来对结果集进行编号,然后选择编号为 1 的行,达到去重的效果。
SELECT
column, ROW_NUMBER() OVER (PARTITION BY column ORDER BY some_column) AS rn
FROM table
WHERE rn = 1;
通过使用子查询和 NOT IN 或者 NOT EXISTS 来过滤掉重复的行。
SELECT column
FROM table t1
WHERE column
NOT IN (
SELECT column
FROM table t2
WHERE t1.id <> t2.id);
SELECT *
FROM 左表
LEFT JOIN 右表
ON 左表.关联字段 = 右表.关联字段;
SELECT *
FROM 左表
RIGHT JOIN 右表
ON 左表.关联字段 = 右表.关联字段;
注解 | 介绍 |
---|---|
@Component | 用于标识一个普通的Java类为Spring的组件,可以被自动扫描并装配到Spring容器中。 |
@Controller | 用于标识一个类为Spring MVC的控制器,处理请求并返回响应。 |
@Service | 用于标识一个类为服务层组件,通常用于定义业务逻辑。 |
@Repository | 用于标识一个类为数据访问层(DAO)组件,用于操作数据库或其他持久化存储。 |
@Autowired | 用于自动装配依赖,通过类型匹配,在Spring容器中查找匹配的Bean,并将其注入到目标对象中。 |
@Qualifier | 与@Autowired一起使用,用于指定具体的Bean名称进行装配。 |
@Value | 用于注入配置文件中的值或者表达式到目标对象中。 |
@RequestMapping | 用于映射请求路径和处理方法,通常在控制器类或方法上使用。 |
@PathVariable | 用于获取URL路径中的变量值。 |
@RequestParam | 用于获取请求参数的值。 |
@ResponseBody | 用于将方法返回的对象作为响应内容返回给客户端。 |
@Configuration | 用于标识一个类为Spring的配置类,替代传统的XML配置文件。 |
@Bean | 用于将方法返回的对象注册为Spring的Bean。 |
@Aspect | 用于定义切面,结合其他注解如@Before、@After等来实现面向切面编程。 |
IOC(Inversion of Control,控制反转)将对象的创建、管理和依赖注入的控制权从应用程序代码中转移到外部容器中。
IOC核心概念:
AOP(Aspect-Oriented Programming,面向切面编程)将跨越多个不同模块的功能进行分离,并将这些功能横切的关注点(cross-cutting concerns)模块化。
AOP术语:
@Service
public class UserService {
@Autowired
private UserDao userDao;
@Transactional
public void updateUser(User user) {
// 更新用户信息的业务逻辑
}
}
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<aop:config>
<aop:pointcut id="serviceMethods" expression="execution(* com.example.*Service.*(..))"/>
<aop:advisor pointcut-ref="serviceMethods" advice-ref="txAdvice"/>
</aop:config>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="get*" read-only="true"/>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
<bean id="log4jInitialization" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetClass" value="org.springframework.util.Log4jConfigurer"/>
<property name="targetMethod" value="initLogging"/>
<property name="arguments">
<list>
<value>classpath:log4j.properties</value>
</list>
</property>
</bean>
Spring 使用了三级缓存和前期引用解决循环依赖的问题。当发现循环依赖时,Spring 会进行以下处理:
Spring 的单例 Bean 在多线程环境下是共享的,因此可能存在线程安全问题。当多个线程同时访问同一个单例 Bean 时,如果该 Bean 的状态会被修改,就有可能导致线程安全问题。
解决方法:
见题目1.10
public interface UserMapper {
User selectUserByIdAndName(@Param("id") Long id, @Param("name") String name);
}
public interface UserMapper {
User selectUserByMap(Map<String, Object> map);
}
public class UserQuery {
private Long id;
private String name;
// 省略 getter 和 setter
}
public interface UserMapper {
User selectUserByQuery(UserQuery query);
}
在MyBatis中,执行批量操作可以通过使用SqlSession的批量处理方法来实现。
List<User> userList = new ArrayList<>();
// 填充userList...
// "com.example.UserMapper.insertBatch"是对应的Mapper中定义的批量插入方法
sqlSession.insert("com.example.UserMapper.insertBatch", userList);
List<User> userList = new ArrayList<>();
// 填充userList...
sqlSession.getConfiguration().getEnvironment().getTransactionFactory().newTransaction(sqlSession.getConnection()).getConnection().setAutoCommit(false);
BatchExecutor batchExecutor = (BatchExecutor) sqlSession.getExecutor();
try {
for (User user : userList) {
batchExecutor.doUpdate(mappedStatement, user);
}
batchExecutor.doFlushStatements(false);
sqlSession.getConfiguration().getEnvironment().getTransactionFactory().newTransaction(sqlSession.getConnection()).getConnection().commit();
} finally {
sqlSession.getConfiguration().getEnvironment().getTransactionFactory().newTransaction(sqlSession.getConnection()).getConnection().rollback();
}
<insert id="insertUser" parameterType="User" useGeneratedKeys="true" keyProperty="id">
INSERT INTO user (name, age) VALUES (#{name}, #{age})
</insert>
<insert id="insertUser" parameterType="User">
<selectKey resultType="Long" keyProperty="id" order="AFTER">
SELECT LAST_INSERT_ID()
</selectKey>
INSERT INTO user (name, age) VALUES (#{name}, #{age})
</insert>
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
sqlSession.insert("com.example.UserMapper.insertUser", user);
sqlSession.commit();
Long generatedKey = sqlSession.getGeneratedKeys().getLong(1);
user.setId(generatedKey);
}
动态SQL的主要用途:
MyBatis的动态SQL的执行原理:
常见的动态SQL:
<select id="findUsers" parameterType="map" resultType="User">
SELECT * FROM users
<where>
<if test="name != null">
AND name = #{name}
</if>
<if test="age != null">
AND age = #{age}
</if>
</where>
</select>
<select id="findUsers" parameterType="map" resultType="User">
SELECT * FROM users
<where>
<choose>
<when test="name != null">
AND name = #{name}
</when>
<when test="age != null">
AND age = #{age}
</when>
<otherwise>
AND status = 'ACTIVE'
</otherwise>
</choose>
</where>
</select>
<update id="updateUser" parameterType="User">
UPDATE users
<set>
<if test="name != null">name = #{name},</if>
<if test="age != null">age = #{age},</if>
</set>
WHERE id = #{id}
</update>
MyBatis 提供了一些分页插件,比如 MyBatis 分页插件 PageHelper。
分页插件的原理可以简单描述为:
控制层
//设置每页储存几条数据
private static final int PAGE_SIZE = 3;
@RequestMapping("list")
public String list(Integer page, HttpSession session, Items items){
Integer p = 1;
if(page != null){
p = page;
}else {
page = p;
}
//调用方法来获取分页后的数据
PageInfo pageInfo = itemsService.itemsPage(page, PAGE_SIZE, items);
session.setAttribute("pb",pageInfo);
session.setAttribute("items", items);
return "list";
}
业务逻辑实现类
public PageInfo itemsPage(Integer page, int pageSize, Items items) {
//使用分页插件PageHelper(告诉 PageHelper 应该对接下来的查询进行分页处理)
PageHelper.startPage(page, pageSize);
//查询列表
List<Items> itemsList = itemsMapper.selectConList(items);
PageInfo pageInfo = new PageInfo<>(itemsList);
return pageInfo;
}
注解 | 作用 |
---|---|
@Controller | 用于标识一个类是 Spring MVC 中的 Controller,处理客户端的请求。 |
@RequestMapping | 用于将请求映射到对应的处理方法,并可以用在类级别和方法级别上。 |
@PathVariable | 用于将 URL 模板变量绑定到方法参数上。 |
@RequestParam | 用于将请求参数绑定到方法参数上。 |
@ResponseBody | 用于将方法的返回值直接作为 HTTP 响应的内容返回给客户端,通常用于返回 JSON 或 XML 格式的数据。 |
@ModelAttribute | 用于将方法的返回值添加到模型中,在渲染视图时可以使用。 |
@SessionAttributes | 用于指定哪些模型属性需要存储到会话中,通常配合 @ModelAttribute 使用。 |
@InitBinder | 用于初始化数据绑定器,通常用于定制数据绑定规则。 |
@ExceptionHandler | 用于标识异常处理方法,当控制器中抛出指定类型的异常时,会调用对应的异常处理方法进行处理。 |
@RequestMapping 注解是 Spring MVC 中的一个核心注解,它用于将请求映射到对应的处理方法。
//当请求路径为 "/users/list" 时,会调用 userList() 方法进行处理。
@Controller
@RequestMapping("/users")
public class UserController {
@RequestMapping("/list")
public String userList() {
// 处理 "/users/list" 请求
return "userList";
}
}
//只有当请求路径为 "/users/create" 并且 HTTP 方法为 POST 时,才会调用 createUser() 方法进行处理。
@Controller
@RequestMapping("/users")
public class UserController {
@RequestMapping(value = "/create", method = RequestMethod.POST)
public String createUser() {
// 处理 POST 请求
return "createSuccess";
}
}
//结合 @RequestParam 注解可以将请求参数绑定到方法的参数上
//当请求路径为 "/users/info" 并且包含名为 "id" 的请求参数时,会将该参数绑定到 userId 参数上。
@Controller
@RequestMapping("/users")
public class UserController {
@RequestMapping("/info")
public String userInfo(@RequestParam("id") int userId) {
// 使用 id 参数进行处理
return "userInfo";
}
}
Spring MVC 中的 Controller 默认是单例模式。当使用 @Controller 注解标记一个类时,Spring 会自动将该类注册为一个 Bean,并且默认情况下使用单例模式管理这个 Bean。这意味着在整个应用程序的生命周期中,只会创建一个该 Controller 类的实例。
如果需要让 Controller 不使用单例模式,可以使用 Spring 的作用域注解(如 @Scope(“prototype”))来修改默认的单例配置,使其每次请求都创建一个新的实例。
由于 Controller 是单例模式,默认情况下所有请求都会共享同一个实例,这意味着多个请求可能同时访问和修改这些共享的成员变量,存在线程安全问题。
Spring MVC 拦截器是一种可以拦截请求的组件,它可以在请求到达 Controller 之前或者之后执行一些操作,比如日志记录、权限检查、国际化处理等。拦截器可以用于对请求进行预处理和后处理,而不影响 Controller 的实际处理过程。
要配置 Spring MVC 拦截器步骤:
<!-- com.example.MyInterceptor 是自定义的拦截器类-->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.example.MyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
// addPathPatterns("/**") 用于指定拦截的路径
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**");
}
}
SpringBoot的核心注解是**@SpringBootApplication**,它是由以下3个注解组成:
区别:
见题目5.5
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
热部署前提条件:
在 Spring Boot 中,可以通过使用@ControllerAdvice、@ExceptionHandler和自定义异常类来实现异常处理。
public class CustomException extends RuntimeException {
public CustomException(String message) {
super(message);
}
}
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public ResponseEntity<String> handleException(Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("An internal server error occurred");
}
@ExceptionHandler(CustomException.class)
public ResponseEntity<String> handleCustomException(CustomException e) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(e.getMessage());
}
}
@RestController
public class MyController {
@GetMapping("/hello")
public String hello() {
// 模拟抛出自定义异常
throw new CustomException("Something went wrong");
}
}
在 Spring Boot 中,可以使用 Spring Data JPA 和 Pageable 接口来实现分页和排序功能。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
// 省略其他字段、构造方法和 getter/setter 方法
}
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
}
@RestController
public class UserController {
@Autowired
private UserRepository userRepository;
@GetMapping("/users")
public Page<User> getUsers(@PageableDefault(size = 10, sort = "name") Pageable pageable) {
return userRepository.findAll(pageable);
}
}
在Spring Boot中实现定时任务可以使用@Scheduled注解和@EnableScheduling注解来实现。
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling //开启定时任务的支持
public class MyApp {
public static void main(String[] args) {
SpringApplication.run(MyApp.class, args);
}
}
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class MyTask {
@Scheduled(fixedRate = 5000) // 每隔5秒执行一次任务
public void myTaskMethod() {
// 定时任务的逻辑代码
}
}
@Scheduled注解支持多种属性来定义定时任务的执行规则:
注意事项:
string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)
Redis提供了集群模式来实现高可用和横向扩展。Redis集群通过分片(Sharding)和复制(Replication)的方式来存储和复制数据,以实现数据的高可用性和负载均衡。
rm: 用于删除文件或目录。语法为:rm [option] file1 file2 …。常用选项包括:
-r:递归删除目录及其内容。
-f:强制删除,不提示用户确认。
find: 用于在指定目录下搜索文件。语法为:find /path/to/search -options [expression]。常用选项包括:
-name:按照文件名进行搜索。
-type:按照文件类型进行搜索(如f表示普通文件,d表示目录)。
-exec:对搜索到的文件执行指定的命令。
ps:显示与当前终端会话相关的进程。它会列出进程的PID(进程ID)、TTY(终端)、STAT(状态)、TIME(CPU占用时间)等信息
top:实时显示系统中各个进程的运行情况,包括进程的PID、用户、CPU占用率、内存占用率等。按下"q"键可以退出top命令。
htop:是top命令的增强版,提供了更加直观和友好的界面,能够方便地查看进程的运行情况。它也显示了CPU和内存的使用情况,以及进程的详细信息。
df:用于报告文件系统的磁盘空间利用情况。加上"-h"选项可以以人类可读的方式显示磁盘空间大小,以便更容易理解。
du:用于估算文件或目录的磁盘使用情况。加上"-h"选项可以以人类可读的方式显示文件或目录的磁盘使用量。
top:实时显示系统中各个进程的运行情况,包括进程的PID、用户、CPU占用率、内存占用率等。按下"q"键可以退出top命令。
htop:是top命令的增强版,提供了更加直观和友好的界面,能够方便地查看进程的运行情况。它也显示了CPU和内存的使用情况,以及进程的详细信息。
mpstat:用于报告多处理器系统中每个处理器的统计信息。它可以显示每个CPU核心的使用率、上下文切换次数、中断次数等。
sar:用于收集、报告和存储系统活动信息。通过添加"-u"选项可以查看CPU使用情况。上述命令中的数字1表示每秒采样一次。
cat:用于连接文件并打印到标准输出设备。通过指定文件名作为参数,你可以查看文件的内容。cat命令将整个文件的内容输出到终端。
less:用于按页显示文件内容,并允许向上或向下浏览文件。它适用于大型文件,可以方便地查看文件的内容。使用箭头键进行浏览,按q键退出less命令。
more:也用于按页显示文件内容,类似于less命令。使用空格键向下滚动一页,按q键退出more命令。
head:用于显示文件的开头部分,默认情况下会显示文件的前10行内容。你可以使用"-n"选项来指定显示的行数,例如"head -n 20 filename"将显示文件的前20行。
tail:用于显示文件的最后几行,默认情况下显示文件的最后10行。你可以使用"-n"选项来指定显示的行数,例如"tail -n 20 filename"将显示文件的后20行。
文章浏览阅读645次。这个肯定是末尾的IDAT了,因为IDAT必须要满了才会开始一下个IDAT,这个明显就是末尾的IDAT了。,对应下面的create_head()代码。,对应下面的create_tail()代码。不要考虑爆破,我已经试了一下,太多情况了。题目来源:UNCTF。_攻防世界困难模式攻略图文
文章浏览阅读2.9k次,点赞3次,收藏10次。偶尔会用到,记录、分享。1. 数据库导出1.1 切换到dmdba用户su - dmdba1.2 进入达梦数据库安装路径的bin目录,执行导库操作 导出语句:./dexp cwy_init/[email protected]:5236 file=cwy_init.dmp log=cwy_init_exp.log 注释: cwy_init/init_123..._达梦数据库导入导出
文章浏览阅读1.9k次。1. 在官网上下载KindEditor文件,可以删掉不需要要到的jsp,asp,asp.net和php文件夹。接着把文件夹放到项目文件目录下。2. 修改html文件,在页面引入js文件:<script type="text/javascript" src="./kindeditor/kindeditor-all.js"></script><script type="text/javascript" src="./kindeditor/lang/zh-CN.js"_kindeditor.js
文章浏览阅读2.3k次,点赞6次,收藏14次。SPI的详情简介不必赘述。假设我们通过SPI发送0xAA,我们的数据线就会变为10101010,通过修改不同的内容,即可修改SPI中0和1的持续时间。比如0xF0即为前半周期为高电平,后半周期为低电平的状态。在SPI的通信模式中,CPHA配置会影响该实验,下图展示了不同采样位置的SPI时序图[1]。CPOL = 0,CPHA = 1:CLK空闲状态 = 低电平,数据在下降沿采样,并在上升沿移出CPOL = 0,CPHA = 0:CLK空闲状态 = 低电平,数据在上升沿采样,并在下降沿移出。_stm32g431cbu6
文章浏览阅读1.2k次,点赞2次,收藏8次。数据链路层习题自测问题1.数据链路(即逻辑链路)与链路(即物理链路)有何区别?“电路接通了”与”数据链路接通了”的区别何在?2.数据链路层中的链路控制包括哪些功能?试讨论数据链路层做成可靠的链路层有哪些优点和缺点。3.网络适配器的作用是什么?网络适配器工作在哪一层?4.数据链路层的三个基本问题(帧定界、透明传输和差错检测)为什么都必须加以解决?5.如果在数据链路层不进行帧定界,会发生什么问题?6.PPP协议的主要特点是什么?为什么PPP不使用帧的编号?PPP适用于什么情况?为什么PPP协议不_接收方收到链路层数据后,使用crc检验后,余数为0,说明链路层的传输时可靠传输
文章浏览阅读587次。软件测试工程师移民加拿大 无证移民,未受过软件工程师的教育(第1部分) (Undocumented Immigrant With No Education to Software Engineer(Part 1))Before I start, I want you to please bear with me on the way I write, I have very little gen...
文章浏览阅读304次。Thinkpad X250笔记本电脑,装的是FreeBSD,进入BIOS修改虚拟化配置(其后可能是误设置了安全开机),保存退出后系统无法启动,显示:secure boot failed ,把自己惊出一身冷汗,因为这台笔记本刚好还没开始做备份.....根据错误提示,到bios里面去找相关配置,在Security里面找到了Secure Boot选项,发现果然被设置为Enabled,将其修改为Disabled ,再开机,终于正常启动了。_安装完系统提示secureboot failure
文章浏览阅读10w+次,点赞93次,收藏352次。1、用strtok函数进行字符串分割原型: char *strtok(char *str, const char *delim);功能:分解字符串为一组字符串。参数说明:str为要分解的字符串,delim为分隔符字符串。返回值:从str开头开始的一个个被分割的串。当没有被分割的串时则返回NULL。其它:strtok函数线程不安全,可以使用strtok_r替代。示例://借助strtok实现split#include <string.h>#include <stdio.h&_c++ 字符串分割
文章浏览阅读2.3k次。1 .高斯日记 大数学家高斯有个好习惯:无论如何都要记日记。他的日记有个与众不同的地方,他从不注明年月日,而是用一个整数代替,比如:4210后来人们知道,那个整数就是日期,它表示那一天是高斯出生后的第几天。这或许也是个好习惯,它时时刻刻提醒着主人:日子又过去一天,还有多少时光可以用于浪费呢?高斯出生于:1777年4月30日。在高斯发现的一个重要定理的日记_2013年第四届c a组蓝桥杯省赛真题解答
文章浏览阅读851次,点赞17次,收藏22次。摘要:本文利用供需算法对核极限学习机(KELM)进行优化,并用于分类。
文章浏览阅读1.1k次。一、系统弱密码登录1、在kali上执行命令行telnet 192.168.26.1292、Login和password都输入msfadmin3、登录成功,进入系统4、测试如下:二、MySQL弱密码登录:1、在kali上执行mysql –h 192.168.26.129 –u root2、登录成功,进入MySQL系统3、测试效果:三、PostgreSQL弱密码登录1、在Kali上执行psql -h 192.168.26.129 –U post..._metasploitable2怎么进入
文章浏览阅读257次。本文将为初学者提供Python学习的详细指南,从Python的历史、基础语法和数据类型到面向对象编程、模块和库的使用。通过本文,您将能够掌握Python编程的核心概念,为今后的编程学习和实践打下坚实基础。_python人工智能开发从入门到精通pdf