越来越多的非业务需求(日志和验证等)加入后, 原有的业务方法急剧膨胀. 每个方法在处理核心逻辑的同时还必须兼顾其他多个关注点
1. 使用动态代理解决
代理设计模式的原理: 使用一个代理将对象包装起来, 然后用该代理对象取代原始对象. 任何对原始对象的调用都要通过代理. 代理对象决定是否以及何时将方法调用转到原始对象上
JDK
Main
package com.spring.aop.helloworld;
public class Main {
public static void main(String[] args) {
ArithmeticCalculcator target = new ArithmeticCalculcatorImpl();
ArithmeticCalculcator proxy = new ArithmeticCalculcatorLoggingProxy(target).getLoggingProxy();
System.out.println(proxy.getClass().getName());
System.out.println(proxy.add(1, 3));
System.out.println(proxy.div(7, 3));
}
}
/*
com.sun.proxy.$Proxy0
The method add beagins with[1, 3]
The method add ends with4
4
The method div beagins with[7, 3]
The method div ends with2
2
*/
ArithmeticCalculcator
package com.spring.aop.helloworld;
public interface ArithmeticCalculcator {
int add(int i,int j);
int sub(int i,int j);
int mul(int i,int j);
int div(int i,int j);
}
ArithmeticCalculcatorImpl
package com.spring.aop.helloworld;
public class ArithmeticCalculcatorImpl implements ArithmeticCalculcator{
@Override
public int add(int i, int j) {
int result = i + j;
return result;
}
@Override
public int sub(int i, int j) {
int result = i - j;
return result;
}
@Override
public int mul(int i, int j) {
int result = i * j;
return result;
}
@Override
public int div(int i, int j) {
int result = i / j;
return result;
}
}
ArithmeticCalculcatorLoggingProxy
package com.spring.aop.helloworld;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.XsiNilLoader.Array;
public class ArithmeticCalculcatorLoggingProxy {
//要代理的对象
private ArithmeticCalculcator target;
public ArithmeticCalculcatorLoggingProxy(ArithmeticCalculcator target) {
this.target = target;
}
public ArithmeticCalculcator getLoggingProxy() {
ArithmeticCalculcator proxy = null;
//代理对象由哪一个类加载器负责加载
ClassLoader loader = target.getClass().getClassLoader();
//代理对象的类型,即其中有哪些方法
Class[] interfaces = new Class[] {ArithmeticCalculcator.class};
//当调用代理对象其中的方法时,该执行的代码
InvocationHandler h = new InvocationHandler() {
/**
* proxy:正在返回的那个代理对象,一般情况下在invoke方法中都不使用该对象。
* method:正在被调用的方法
* args:调用方法时传入的参数
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String methodName = method.getName();
System.out.println("The method "+methodName+" beagins with"+Arrays.asList(args));
//执行方法
Object result = null;
try {
//前置通知
result = method.invoke(target, args);
//返回通知,可以访问到方法返回值
} catch (Exception e) {
// 异常通知,
}
//后置通知,发生异常时访问不到方法的返回值
System.out.println("The method "+methodName+" ends with"+result);
return result;
}
};
proxy = (ArithmeticCalculcator)Proxy.newProxyInstance(loader, interfaces, h);
return proxy;
}
}
2. Spring AOP
AOP(Aspect-Oriented Programming, 面向切面编程 ): 是一种新的方法论, 是对传统OOP(Object-Oriented Programming, 面向对象编程) 的补充。
2.1AOP术语
切面(Aspect): 横切关注点
通知(Advice): 切面必须要完成的工作
目标(Target): 被通知的对象
代理(Proxy): 向目标对象应用通知之后创建的对象
连接点(Joinpoint):程序执行的某个特定位置:如类某个方法调用前、调用后、方法抛出异常后等。连接点由两个信息确定:方法表示的程序执行点;相对点表示的方位。
切点(pointcut):每个类都拥有多个连接点:例如 ArithmethicCalculator 的所有方法实际上都是连接点,即连接点是程序类中客观存在的事务。AOP 通过切点定位到特定的连接点。类比:连接点相当于数据库中的记录,切点相当于查询条件。切点和连接点不是一对一的关系,一个切点匹配多个连接点,切点通过 org.springframework.aop.Pointcut 接口进行描述,它使用类和方法作为连接点的查询条件。
2.2AspectJ
Java 社区里最完整最流行的 AOP框架.
在 Spring 中启用AspectJ 注解支持
1)要在 Spring 应用中使用 AspectJ 注解, 必须在classpath 下包含 AspectJ 类库:aopalliance.jar、aspectj.weaver.jar 和 spring-aspects.jar
2)将 aop Schema 添加到 根元素中.
3)要在 Spring IOC 容器中启用 AspectJ 注解支持, 只要在Bean 配置文件中定义一个空的 XML 元素
当 Spring IOC 容器侦测到Bean 配置文件中的 元素时, 会自动为与 AspectJ 切面匹配的 Bean 创建代理.
用 AspectJ 注解声明切面
切面只是一个带有 @Aspect 注解的 Java 类.
AspectJ 支持 5 种类型的通知注解:
@Before: 前置通知, 在方法执行之前执行
@After: 后置通知, 在方法执行之后执行
@AfterRunning: 返回通知,在方法返回结果之后执行
@AfterThrowing: 异常通知, 在方法抛出异常之后
@Around: 环绕通知, 围绕着方法执行
可以在通知方法中声明一个类型为 JoinPoint 的参数. 然后就能访问链接细节. 如方法名称和参数值.
对于环绕通知来说, 连接点的参数类型必须是 ProceedingJoinPoint . 它是 JoinPoint 的子接口, 允许控制何时执行, 是否执行连接点.
切面的优先级可以通过实现 Ordered 接口或利用 @Order 注解指定.
在 AspectJ 切面中, 可以通过 @Pointcut 注解将一个切入点声明成简单的方法. 切入点的方法体通常是空的
Main
package com.spring.aop.impl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
//1.创建spring IOC 容器
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
//2.从IOC容器中获取bean的实例
ArithmeticCalculcator a = (ArithmeticCalculcator)ac.getBean("arithmeticCalculcatorImpl");
//3.使用bean
int result = a.add(3, 1);
System.out.println(result);
System.out.println(a.div(9, 3));
}
}
/*
validate:[3, 1]
around:The method add begins with [3, 1]
before:The method add begins with[3, 1]
around:The method add ends with4
around: The method add ends
after:The method add ends
afterReturn:The method add ends with4
4
validate:[9, 3]
around:The method div begins with [9, 3]
before:The method div begins with[9, 3]
around:The method div ends with3
around: The method div ends
after:The method div ends
afterReturn:The method div ends with3
3
*/
applicationContext.xml
ArithmeticCalculcator
package com.spring.aop.impl;
public interface ArithmeticCalculcator {
int add(int i,int j);
int sub(int i,int j);
int mul(int i,int j);
int div(int i,int j);
}
ArithmeticCalculcatorImpl
package com.spring.aop.impl;
import org.springframework.stereotype.Component;
@Component
public class ArithmeticCalculcatorImpl implements ArithmeticCalculcator{
@Override
public int add(int i, int j) {
int result = i + j;
return result;
}
@Override
public int sub(int i, int j) {
int result = i - j;
return result;
}
@Override
public int mul(int i, int j) {
int result = i * j;
return result;
}
@Override
public int div(int i, int j) {
int result = i / j;
return result;
}
}
LogginAspect
package com.spring.aop.impl;
import java.util.Arrays;
import java.util.List;
import org.aopalliance.intercept.Joinpoint;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
/**
2.1加入jar包
aopalliance-alpha1.jar
aspectjweaver.jar
spring-aop-4.3.2.RELEASE.jar
spring-aspects-4.3.2.RELEASE.jar
commons-logging-1.2.jar
spring-beans-4.3.2.RELEASE.jar
spring-context-4.3.2.RELEASE.jar
spring-core-4.3.2.RELEASE.jar
spring-expression-4.3.2.RELEASE.jar
2.2配置文件中加入aop命名空间
2.3基于注解的方式
2.3.1在配置文件中加入如下配置:
2.3.2把横切关注点的代码抽象到切面的类中
i.切面首先是一个IOC中的bean,即加入@Component注解
ii.切面还需加入@Aspect注解
2.3.3在类中声明各种通知
i.声明一个方法
ii.在方法前加入@Before注解
2.3.4可以在通知方法中声明一个类型为JoinPoint的参数,然后就能访问链接细节,如方法名称和参数值
@Aspect
@Component
public class LogginAspect {
//声明目标方法是一个前置通知:在目标方法开始之前通知
@Before("execution(public int com.spring.aop.impl.ArithmeticCalculcator.*(int, int ))")
public void beforeMethod(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
List args = Arrays.asList(joinPoint.getArgs());
System.out.println("The method "+methodName+" begins with"+args);
}
}
*
*/
/**
* 把这个类声明为一个切面
* 1.把该类放在IOC容器中
* 2.声明为一个切面
*
*/
@Order(2)
@Aspect
@Component
public class LogginAspect {
//声明目标方法是一个前置通知:在目标方法开始之前通知
@Before("ValidaAspect.declareJoinPointExpression()")
public void beforeMethod(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
List args = Arrays.asList(joinPoint.getArgs());
System.out.println("before:The method "+methodName+" begins with"+args);
}
//后置通知:目标方法执行后执行的通知,无论方法是否出现异常
//还不能对目标方法的返回值进行访问
@After(value="ValidaAspect.declareJoinPointExpression()")
public void afterMethod(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
System.out.println("after:The method "+methodName+" ends");
}
//返回通知:目标方法正常返回后执行的通知
//可以访问目标方法的返回值
@AfterReturning(value="ValidaAspect.declareJoinPointExpression()",
returning="result")
public void afterReturningMethod(JoinPoint joinPoint,Object result) {
String methodName = joinPoint.getSignature().getName();
System.out.println("afterReturn:The method "+methodName+" ends with"+result);
}
//异常通知:目标方法出现异常时执行的通知
//可以访问到异常对象,可以指定出现特定异常时在执行代码
@AfterThrowing(value="ValidaAspect.declareJoinPointExpression()",
throwing="ex")
public void afterThrowingMethod(JoinPoint joinPoint,Exception ex) {
String methodName = joinPoint.getSignature().getName();
System.out.println("afterThrow:The method "+methodName+" occurs "+ex);
}
//环绕通知需要携带ProceedingJoinPoint类型的参数
//环绕通知类似于动态代理的全过程:ProceedingJoinPoint类型的参数可以决定是否执行目标方法
//环绕通知必须有返回值,返回值是目标方法的返回值
@Around(value="ValidaAspect.declareJoinPointExpression()")
public Object aroundMethod(ProceedingJoinPoint pjp) {
Object result = null;
String methodName = pjp.getSignature().getName();
//执行目标方法
try {
//前置通知
System.out.println(" around:The method "+methodName+" begins with "+Arrays.asList(pjp.getArgs()));
result = pjp.proceed();
//返回通知
System.out.println(" around:The method "+methodName+" ends with"+result);
} catch (Throwable e) {
//异常通知
System.out.println(" around: The method "+methodName+" occurs "+e);
}
//后置通知
System.out.println(" around: The method "+methodName+" ends");
return result;
}
}
ValidaAspect
package com.spring.aop.impl;
import java.util.Arrays;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
/**
* 可以使用@Order注解指定切面的优先级,值越小优先级越高
*/
@Order(1)
@Aspect
@Component
public class ValidaAspect {
/**
* 定义一个方法,用于声明切入点表达式。一般的,该方法中不需要添入其他的代码。
* 使用@Pointcut来声明切入点表达式
* 后面的其他通知直接使用方法名来引用当前的切入点表达式
*/
@Pointcut("execution(public int com.spring.aop.impl.ArithmeticCalculcator.*(..))")
public void declareJoinPointExpression() {}
@Before("declareJoinPointExpression()")
public void validationAspect(JoinPoint joinPoint) {
System.out.println("validate:"+Arrays.asList(joinPoint.getArgs()));
}
}
正常情况下, 基于注解的声明要优先于基于 XML 的声明. 2.3基于 XML 的声明切面
2.3.1声明切面
1)导入 aop Schema
2)在 Bean 配置文件中, 所有的 Spring AOP 配置都必须定义在 元素内部. 对于每个切面而言, 都要创建一个 元素来为具体的切面实现引用后端 Bean 实例.
3)切面 Bean 必须有一个标示符, 供 元素引用
2.3.2声明切入点
1)切入点使用 元素声明
2)切入点必须定义在 元素下, 或者直接定义在 元素下.
定义在 元素下: 只对当前切面有效
定义在 元素下: 对所有切面都有效
2.3.3声明通知
通知元素需要使用 来引用切入点, 或用 直接嵌入切入点表达式. method 属性指定切面类中通知方法的名称
Main
package com.spring.aop.xml;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
//1.创建spring IOC 容器
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext-xml.xml");
//2.从IOC容器中获取bean的实例
ArithmeticCalculcator a = (ArithmeticCalculcator)ac.getBean("arithmeticCalculcatorImpl");
//3.使用bean
int result = a.add(3, 1);
System.out.println(result);
System.out.println(a.div(9, 3));
}
}
/*
validate:[3, 1]
around:The method add begins with [3, 1]
before:The method add begins with[3, 1]
around:The method add ends with4
around: The method add ends
after:The method add ends
afterReturn:The method add ends with4
4
validate:[9, 3]
around:The method div begins with [9, 3]
before:The method div begins with[9, 3]
around:The method div ends with3
around: The method div ends
after:The method div ends
afterReturn:The method div ends with3
3
*/
applicationContext-xml.xml
ArithmeticCalculcator
package com.spring.aop.xml;
public interface ArithmeticCalculcator {
int add(int i,int j);
int sub(int i,int j);
int mul(int i,int j);
int div(int i,int j);
}
ArithmeticCalculcatorImpl
package com.spring.aop.xml;
import org.springframework.stereotype.Component;
public class ArithmeticCalculcatorImpl implements ArithmeticCalculcator{
@Override
public int add(int i, int j) {
int result = i + j;
return result;
}
@Override
public int sub(int i, int j) {
int result = i - j;
return result;
}
@Override
public int mul(int i, int j) {
int result = i * j;
return result;
}
@Override
public int div(int i, int j) {
int result = i / j;
return result;
}
}
LogginAspect
package com.spring.aop.xml;
import java.util.Arrays;
import java.util.List;
import org.aopalliance.intercept.Joinpoint;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
public class LogginAspect {
//声明目标方法是一个前置通知:在目标方法开始之前通知
public void beforeMethod(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
List args = Arrays.asList(joinPoint.getArgs());
System.out.println("before:The method "+methodName+" begins with"+args);
}
//后置通知:目标方法执行后执行的通知,无论方法是否出现异常
//还不能对目标方法的返回值进行访问
public void afterMethod(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
System.out.println("after:The method "+methodName+" ends");
}
//返回通知:目标方法正常返回后执行的通知
//可以访问目标方法的返回值
public void afterReturningMethod(JoinPoint joinPoint,Object result) {
String methodName = joinPoint.getSignature().getName();
System.out.println("afterReturn:The method "+methodName+" ends with"+result);
}
//异常通知:目标方法出现异常时执行的通知
//可以访问到异常对象,可以指定出现特定异常时在执行代码
public void afterThrowingMethod(JoinPoint joinPoint,Exception ex) {
String methodName = joinPoint.getSignature().getName();
System.out.println("afterThrow:The method "+methodName+" occurs "+ex);
}
//环绕通知需要携带ProceedingJoinPoint类型的参数
//环绕通知类似于动态代理的全过程:ProceedingJoinPoint类型的参数可以决定是否执行目标方法
//环绕通知必须有返回值,返回值是目标方法的返回值
public Object aroundMethod(ProceedingJoinPoint pjp) {
Object result = null;
String methodName = pjp.getSignature().getName();
//执行目标方法
try {
//前置通知
System.out.println(" around:The method "+methodName+" begins with "+Arrays.asList(pjp.getArgs()));
result = pjp.proceed();
//返回通知
System.out.println(" around:The method "+methodName+" ends with"+result);
} catch (Throwable e) {
//异常通知
System.out.println(" around: The method "+methodName+" occurs "+e);
}
//后置通知
System.out.println(" around: The method "+methodName+" ends");
return result;
}
}
ValidaAspect
package com.spring.aop.xml;
import java.util.Arrays;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
/**
* 可以使用@Order注解指定切面的优先级,值越小优先级越高
*/
public class ValidaAspect {
public void validationAspect(JoinPoint joinPoint) {
System.out.println("validate:"+Arrays.asList(joinPoint.getArgs()));
}
}
你可能感兴趣的:(Spring)
spring-ioc-bean
周周写不完的代码
spring java 后端
本文重点在于充分应用Spring提供的IoC特性,介绍如何创建一个好用的Bean。基础篇不涉及后置处理器、BeanDefinition以及Spring加载原理相关的知识。引入ioc的起源**接口与实现类的需求变更**:最初的静态工厂模式。**反射机制**:延迟加载,避免编译时依赖。**外部化配置**:将Bean的全限定名存储在配置文件中。**缓存机制**:存储已创建的Bean对象。入门使用Spri
SpringBoot Bug 日志
优雅的造轮狮
JavaEE spring boot bug java
Spring循环依赖问题Bug如下wxMpConfiguration→subscribeHandler→wxMsgServiceImpl→wxMpConfiguration解决方案方案实施方式注意事项接口抽象定义WxMpService接口,通过接口注入最佳设计实践Setter注入对非必要依赖使用setter方法降低耦合度@Lazy注解在循环点添加延迟加载需测试性能影响配置允许循环spring.ma
Spring使用JWT进行登录验证
PXM的算法星球
Java后端 spring java 后端
前情提要:由于这学期课设需要使用SSM技术栈,导致一些好用的登录框架无法适配,所以改用手写JWT进行登录验证JWT简介JSONWebToken(JWT)是一种用于在网络应用环境中进行用户身份验证和信息交换的开放标准。它通过将数据以JSON格式进行编码,使得信息在不同的系统和应用之间得以安全传递。JWT的主要特点是结构简洁且安全性高,广泛应用于单点登录(SSO)、API授权和用户身份认证。JWT由三
Spring 事务(详解)
Bejpse
spring java 后端
4.Spring事务4.1什么是事务?将组操作封装成个执单元,要么全部成功要么全部失败。为什么要事务?如转账分为两个操作:第步操作:A账户-100元,第步操作:B账户+100元。如果没有事务,第步执成功了,第步执失败了,那么A账户平故的100元就“间蒸发”了。如果使事务就可以解决这个问题,让这组操作要么起成功,要么起失败。4.1.1事务特性事务有4特性(ACID):原性(Atomicity,或称不
Spring 集成事务管理详解:银行转账示例
阿绵
后端 spring java 后端 事务管理
1.前言在JavaEE开发中,数据库事务是保证数据一致性的重要机制。Spring提供了强大的事务管理功能,允许开发者通过声明式事务(基于注解)或编程式事务(手动管理)来控制事务。本文介绍如何在原始Spring框架(非SpringBoot)中集成事务管理,包括配置步骤和代码示例本代码示例版本要求:Java17+Spring6+2.事务管理的基本概念2.1什么是事务?事务(Transaction)是一
Spring学习笔记03——Spring Boot的文件结构
Shaoxi Zhang
Java 学习 笔记 spring boot
Springboot常见的文件结构:src/├──main/│├──java/││└──com.example.demo/││├──DemoApplication.java#主入口││├──config/#配置类││├──controller/#控制器││├──service/#业务逻辑││├──mapper/#数据库操作接口││├──entity/#数据库实体类││├──dto/#数据传输对象│
springboot接入emqx的mqtt
renkai721
JAVA spring boot mqtt emqx
需求背景物联网设备需要通过mqtt协议传输,这里记录一下,注意,这篇文章不能接入阿里云的mqtt,本人已经试过,会报错。开发教程1、EMQX安装部署--1安装必要的依赖sudoyuminstall-yyum-utilsdevice-mapper-persistent-datalvm2--2设置repo库sudoyum-config-manager--add-repohttps://repos.em
如何在Spring Boot中读取JAR包内resources目录下文件
嘵奇
提升自己 spring boot jar
精心整理了最新的面试资料和简历模板,有需要的可以自行获取点击前往百度网盘获取点击前往夸克网盘获取以下是如何在SpringBoot中读取JAR包内resources目录下文件的教程,分为多种方法及详细说明:方法1:使用ClassPathResource(Spring框架推荐)适用于Spring环境,能自动处理类路径资源。importorg.springframework.core.io.ClassP
基于SpringBoot大学生创新创业训练项目管理系统的设计与实现
四金学长
spring boot 后端 java 大学生创新创业训练项目管理系统
1.引言在当今的软件开发领域,企业级应用的开发和部署速度直接影响着业务的竞争力。SpringBoot以其轻量级、快速启动和强大的集成能力,成为构建现代企业级应用的首选框架。本文将带您深入了解SpringBoot框架的核心特性,并展示如何利用它构建一个高效、可扩展的系统。2.开发环境开发语言:Java框架:springbootJD版本:JDK1.8服务器:tomcat7数据库:mysql5.7(一定
Spring Boot 异步编程深入剖析
珠峰日记
spring boot java 后端
SpringBoot异步编程深入剖析1.异步方法的使用原理深度解析SpringBoot的异步方法基于Spring的AOP(面向切面编程)实现。当在方法上添加@Async注解时,Spring会为该方法所在的类创建一个代理对象。当调用该异步方法时,实际上是调用代理对象的方法,代理对象会将该方法的执行委托给线程池中的一个线程去执行,而调用线程会继续执行后续代码,从而实现异步执行。更复杂的使用场景除了返回
SpringBoot+Quartz+Redis+Mysql定时从Redis存入Mysql
baxxdwyp
springboot quartz redis mysql
先说明一下场景以博客为例,对每个用户的粉丝,和该用户下面的博客的赞数之和,放入redis这里以1小时更新一次代码实现以https://blog.csdn.net/baxxdwyp/article/details/102622981https://blog.csdn.net/baxxdwyp/article/details/102620035为基础,一个quartz单任务,一个redisset点赞我
springboot+mqtt(emqx)
summenger
spring boot java 后端
1.pom依赖org.springframework.bootspring-boot-starter-integrationorg.springframework.integrationspring-integration-streamorg.springframework.integrationspring-integration-mqtt2.application.yaml配置hostUrl:
新闻推荐系统:Spring Boot框架详解
2402_85758936
spring boot 后端 java
2相关技术2.1MYSQL数据库MySQL是一个真正的多用户、多线程SQL数据库服务器。是基于SQL的客户/服务器模式的关系数据库管理系统,它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等,非常适用于Web站点或者其他应用软件的数据库后端的开发工作。此外,用户可利用许多语言编写访问MySQL数据库的程序。作为开放源代码运动的产物之一,MyS
新闻稿件管理系统:SpringBoot框架全面解析
杨哥带你写代码
spring boot java 后端
5系统详细实现5.1管理员模块的实现5.1.1用户信息管理新闻稿件管理系统的系统管理员可以管理用户,可以对用户信息修改删除以及查询操作。具体界面的展示如图5.1所示。图5.1用户信息管理界面5.1.2记者信息管理系统管理员可以查看对记者信息进行添加,修改,删除以及查询操作。具体界面如图5.2所示。图5.2记者信息管理界面5.1.3审批员信息管理系统管理员可以对审批员信息进行添加,修改,删除以及查询
基于Spring Boot+vue的厨艺交流平台系统设计与实现
程序媛小果
毕设 java精品毕设 前端 spring boot vue.js 后端
大家好,今天要和大家聊的是一款基于SpringBoot的“厨艺交流平台”系统的设计与实现。项目源码以及部署相关事宜请联系我,文末附上联系方式。项目简介基于SpringBoot的“厨艺交流平台”系统设计与实现的主要使用者分为管理员、普通用户和游客。没有授权的用户无法使用本系统功能,包括个人中心、食材分类管理、用户管理、菜品分类管理、菜谱信息管理、食材信息管理、商品分类管理、商品信息管理、美食日志管理
2025年计算机毕业设计springboot 校园生活服务平台
zhihao501
课程设计 spring boot 后端
本系统(程序+源码)带文档lw万字以上文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容选题背景关于校园生活服务平台的研究,现有研究主要以校园信息化管理、服务系统集成以及学生需求满足为主。然而,专门针对校园生活服务平台综合功能设计与实现的研究较少。当前,随着信息技术的快速发展,校园生活服务平台的构建与优化成为提升校园生活质量、增强学生学习体验的重要途径。本课题目前存在的争
百万架构师第二十二课:源码分析:Spring 源码分析:Spring经典面试答疑|JavaGuide
大雄野比
spring 面试 java
Spring面试解答上半节:面试中需要注意的细节动脑子,面试是一种交流面试的时候,要用心去感受当时面试场景了解自己,自己的长处、自己的短处(巧妙地扬长避短)了解1.公司的业务场景2.你是去面试什么岗位的?Java高级工程师实际工作经验是1年(如实填写)1、请描述SpringIOC的工作原理答:定位加载注册BeanFactoryBeanDefintion...1-3年1+ApplicationCon
Spring Boot DevTools热部署:开发效率提升100%
Sendingab
spring boot 后端 java spring java-ee
SpringBootDevTools热部署:开发效率提升100%引言在开发SpringBoot应用时,每次修改代码后都需要重启应用,这无疑会浪费大量时间。SpringBootDevTools的出现彻底解决了这一问题,它通过热部署(HotSwapping)和实时重载(LiveReload)两大核心功能,让开发者告别重复启动的繁琐操作。本文将手把手教你配置DevTools,并深入解析其底层原理,助你开
Spring Boot整合Thymeleaf模板引擎实战——从静态页面到动态表单处理全流程解析
Sendingab
零基础7天精通Spring Boot Spring boot 从入门到精通 spring boot 后端 java tomcat spring spring cloud xml
https://example.com/thymeleaf-spring-demo前言在前后端不分离的传统Web项目中,Thymeleaf凭借自然的HTML语法与强大的表达式功能成为SpringBoot官方推荐的模板引擎。本文将带你从零实现用户注册功能,涵盖表单验证、页面碎片化、国际化等核心场景,并分享性能调优实战经验。一、快速整合Thymeleaf1.1添加基础依赖 xmlorg.springf
Nacos配置管理Feign远程调用Gateway服务网关
程序员要奋斗
# 微服务 gateway java spring
1.统一配置管理1.统一配置管理流程1.引入Nacos的配置管理客户端依赖 com.alibaba.cloud spring-cloud-starter-alibaba-nacos-config 2.在userservice中的resource目录添加一个bootstrap.yml文件,这个文件是引导文件,优先级高于application.yml spring: appl
【JAVA面试题】Spring、Spring MVC、Spring Boot、Spring Cloud的区别与联系
今天你慧了码码码码码码码码码码
JAVA面试题 java spring mvc
在Java生态中,Spring框架及其衍生技术(如SpringMVC、SpringBoot、SpringCloud)是开发企业级应用的核心工具。它们在功能、定位和使用场景上各有侧重,但又紧密联系。本文将详细解析它们的区别与联系,帮助你在面试中更好地回答相关问题。1.Spring框架定义:Spring是一个轻量级的控制反转(IoC)和面向切面编程(AOP)的容器框架。它提供了一种全面的编程和配置模型
SpringBoot 同时可以处理多少个请求?
missterzy
JAVA框架 spring boot java
SpringBoot作为Java开发中必备的框架,它为开发者提供了高效且易用的开发工具。因此,和它相关的面试题也非常重要。今天我们就来看一道经典的面试题:SpringBoot同时可以处理多少个请求?1.什么是SpringBoot?SpringBoot是Spring框架的一个子项目,它的设计目的是简化Spring应用的创建、配置和部署。通过SpringBoot,开发者可以轻松地创建独立运行的、生产级
Java实战:Spring Boot application.yml配置文件详解
web_13233421436
面试 学习路线 阿里巴巴 java spring boot 网络
本文将详细介绍SpringBootapplication.yml配置文件的使用和配置项。我们将探讨application.yml文件的基本概念,以及如何使用它来配置SpringBoot应用程序的各个方面。此外,我们将通过具体的示例来展示如何配置不同的SpringBoot组件,如数据源、数据库、缓存、邮件服务等。本文适合希望深入了解SpringBoot配置文件的开发者阅读。一、引言在SpringBo
软件架构设计与模式之:模块化设计与组件化架构
AI天才研究院
AI大模型企业级应用开发实战 大数据 人工智能 语言模型 Java Python 架构设计
作者:禅与计算机程序设计艺术1.背景介绍模块化、组件化、微服务架构已经成为云计算的主流架构模式,软件架构设计如何满足需求并持续优化性能是一个非常重要的课题。本文将阐述模块化、组件化、微服务架构的概念及优缺点,并从面向对象的角度阐述模块化设计与组件化架构的过程。同时介绍一些基于Java语言的开源框架(如Spring)所实现的模块化、组件化、微服务架构,并深入到源码分析其实现机制和原理。本文的主要读者
spring boot项目Linux环境jar包启动shell脚本
Crime_man
spring boot linux jar
springbootjar启动shell脚本示例使用场景shell脚本文件示例可能遇见的问题1.无权限使用`chomd`命令为文件添加权限2.Shell脚本的行尾格式不兼容通过Vim修改文件格式使用场景在linux环境,启动小型springboot项目时,我们总需要一些操作步骤才能将程序启动:查找已启动的线程id杀掉线程id使用命令启动项目我们可以讲上述命令集成的shell脚本文件中,运行shel
springcloud框架搭建
zzyh123456
spring cloud spring 后端
SpringCloud框架的搭建是一个涉及多个步骤和组件的过程,旨在构建微服务架构的应用程序。以下是一个简化的SpringCloud框架搭建流程,涵盖了主要的步骤和注意事项:1.环境准备JDK安装:确保已安装JavaDevelopmentKit(JDK),通常建议使用JDK8或更高版本。Maven或Gradle:安装Maven或Gradle作为项目管理工具,用于依赖管理和构建项目。IDE:推荐使用
k8s部署springcloud-alibaba项目
封印di恶魔
kubernetes spring cloud k8s
本文由个人总结,如需转载使用请标明原著及原文地址本文需要一些知识储备,有一定的自学能力,有一定的自行解决问题的能力,不然直接看的话压力会比较大,建议有一定知识储备后作为提升来学本文的前置条件是会docker,还要有两台以上的虚拟机,还不了解的可以先看我前一篇文章centos8安装docker运行java文件_centos8docker安装java8-CSDN博客本文是我在完整搭建完整个系统后再这里
docker springcloud k8s集成部署
zzyh123456
docker spring cloud kubernetes
Docker、SpringCloud和Kubernetes(K8s)的集成部署是一个复杂的过程,涉及到多个组件的协同工作。以下是一个简化的步骤概述,用于指导如何将这些技术集成以部署微服务架构。一、准备工作环境搭建:确保所有节点(master和slave)都已安装Docker、Kubernetes以及必要的依赖项(如Maven)。节点之间的网络配置需确保能够相互通信,并且外部服务(如DockerHu
ConditionalOnProperty注解使用介绍、应用场景以及示例代码
小猿、
spring boot spring spring spring boot
概述@ConditionalOnProperty是SpringFramework中的一个条件注解,用于根据配置文件中的属性值来决定是否创建特定的bean或者是否启用特定的配置。创建某个bean或者执行某个配置。它的工作方式类似于SpringBoot的application.properties或application.yml中的属性配置。当指定的属性在配置文件中存在且值符合条件时,相关的配置才会生
SpringBoot接入DeepSeek,保姆级教程
xuxinyang100
spring boot 后端 java
1、创建APIkey创建链接:https://platform.deepseek.com/api_keys点击创建APIkey即可免费生成一个key值,别忘记保存。2、java端接入完整目录springboot配置文件application.ymlai: config: deepseek: apiKey:填写官网申请的Key baseUrl:https://api.deepseek.co
[黑洞与暗粒子]没有光的世界
comsci
无论是相对论还是其它现代物理学,都显然有个缺陷,那就是必须有光才能够计算
但是,我相信,在我们的世界和宇宙平面中,肯定存在没有光的世界....
那么,在没有光的世界,光子和其它粒子的规律无法被应用和考察,那么以光速为核心的
&nbs
jQuery Lazy Load 图片延迟加载
aijuans
jquery
基于 jQuery 的图片延迟加载插件,在用户滚动页面到图片之后才进行加载。
对于有较多的图片的网页,使用图片延迟加载,能有效的提高页面加载速度。
版本:
jQuery v1.4.4+
jQuery Lazy Load v1.7.2
注意事项:
需要真正实现图片延迟加载,必须将真实图片地址写在 data-original 属性中。若 src
使用Jodd的优点
Kai_Ge
jodd
1. 简化和统一 controller ,抛弃 extends SimpleFormController ,统一使用 implements Controller 的方式。
2. 简化 JSP 页面的 bind, 不需要一个字段一个字段的绑定。
3. 对 bean 没有任何要求,可以使用任意的 bean 做为 formBean。
使用方法简介
jpa Query转hibernate Query
120153216
Hibernate
public List<Map> getMapList(String hql,
Map map) {
org.hibernate.Query jpaQuery = entityManager.createQuery(hql);
if (null != map) {
for (String parameter : map.keySet()) {
jp
Django_Python3添加MySQL/MariaDB支持
2002wmj
mariaDB
现状
首先,Django@Python2.x 中默认的引擎为 django.db.backends.mysql 。但是在Python3中如果这样写的话,会发现 django.db.backends.mysql 依赖 MySQLdb[5] ,而 MySQLdb 又不兼容 Python3 于是要找一种新的方式来继续使用MySQL。 MySQL官方的方案
首先据MySQL文档[3]说,自从MySQL
在SQLSERVER中查找消耗IO最多的SQL
357029540
SQL Server
返回做IO数目最多的50条语句以及它们的执行计划。
select top 50
(total_logical_reads/execution_count) as avg_logical_reads,
(total_logical_writes/execution_count) as avg_logical_writes,
(tot
spring UnChecked 异常 官方定义!
7454103
spring
如果你接触过spring的 事物管理!那么你必须明白 spring的 非捕获异常! 即 unchecked 异常! 因为 spring 默认这类异常事物自动回滚!!
public static boolean isCheckedException(Throwable ex)
{
return !(ex instanceof RuntimeExcep
mongoDB 入门指南、示例
adminjun
java mongodb 操作
一、准备工作
1、 下载mongoDB
下载地址:http://www.mongodb.org/downloads
选择合适你的版本
相关文档:http://www.mongodb.org/display/DOCS/Tutorial
2、 安装mongoDB
A、 不解压模式:
将下载下来的mongoDB-xxx.zip打开,找到bin目录,运行mongod.exe就可以启动服务,默
CUDA 5 Release Candidate Now Available
aijuans
CUDA
The CUDA 5 Release Candidate is now available at http://developer.nvidia.com/<wbr></wbr>cuda/cuda-pre-production. Now applicable to a broader set of algorithms, CUDA 5 has advanced fe
Essential Studio for WinRT网格控件测评
Axiba
JavaScript html5
Essential Studio for WinRT界面控件包含了商业平板应用程序开发中所需的所有控件,如市场上运行速度最快的grid 和chart、地图、RDL报表查看器、丰富的文本查看器及图表等等。同时,该控件还包含了一组独特的库,用于从WinRT应用程序中生成Excel、Word以及PDF格式的文件。此文将对其另外一个强大的控件——网格控件进行专门的测评详述。
网格控件功能
1、
java 获取windows系统安装的证书或证书链
bewithme
windows
有时需要获取windows系统安装的证书或证书链,比如说你要通过证书来创建java的密钥库 。
有关证书链的解释可以查看此处 。
public static void main(String[] args) {
SunMSCAPI providerMSCAPI = new SunMSCAPI();
S
NoSQL数据库之Redis数据库管理(set类型和zset类型)
bijian1013
redis 数据库 NoSQL
4.sets类型
Set是集合,它是string类型的无序集合。set是通过hash table实现的,添加、删除和查找的复杂度都是O(1)。对集合我们可以取并集、交集、差集。通过这些操作我们可以实现sns中的好友推荐和blog的tag功能。
sadd:向名称为key的set中添加元
异常捕获何时用Exception,何时用Throwable
bingyingao
用Exception的情况
try {
//可能发生空指针、数组溢出等异常
} catch (Exception e) {
【Kafka四】Kakfa伪分布式安装
bit1129
kafka
在http://bit1129.iteye.com/blog/2174791一文中,实现了单Kafka服务器的安装,在Kafka中,每个Kafka服务器称为一个broker。本文简单介绍下,在单机环境下Kafka的伪分布式安装和测试验证 1. 安装步骤
Kafka伪分布式安装的思路跟Zookeeper的伪分布式安装思路完全一样,不过比Zookeeper稍微简单些(不
Project Euler
bookjovi
haskell
Project Euler是个数学问题求解网站,网站设计的很有意思,有很多problem,在未提交正确答案前不能查看problem的overview,也不能查看关于problem的discussion thread,只能看到现在problem已经被多少人解决了,人数越多往往代表问题越容易。
看看problem 1吧:
Add all the natural num
Java-Collections Framework学习与总结-ArrayDeque
BrokenDreams
Collections
表、栈和队列是三种基本的数据结构,前面总结的ArrayList和LinkedList可以作为任意一种数据结构来使用,当然由于实现方式的不同,操作的效率也会不同。
这篇要看一下java.util.ArrayDeque。从命名上看
读《研磨设计模式》-代码笔记-装饰模式-Decorator
bylijinnan
java 设计模式
声明: 本文只为方便我个人查阅和理解,详细的分析以及源代码请移步 原作者的博客http://chjavach.iteye.com/
import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.io.Fi
Maven学习(一)
chenyu19891124
Maven私服
学习一门技术和工具总得花费一段时间,5月底6月初自己学习了一些工具,maven+Hudson+nexus的搭建,对于maven以前只是听说,顺便再自己的电脑上搭建了一个maven环境,但是完全不了解maven这一强大的构建工具,还有ant也是一个构建工具,但ant就没有maven那么的简单方便,其实简单点说maven是一个运用命令行就能完成构建,测试,打包,发布一系列功
[原创]JWFD工作流引擎设计----节点匹配搜索算法(用于初步解决条件异步汇聚问题) 补充
comsci
算法 工作 PHP 搜索引擎 嵌入式
本文主要介绍在JWFD工作流引擎设计中遇到的一个实际问题的解决方案,请参考我的博文"带条件选择的并行汇聚路由问题"中图例A2描述的情况(http://comsci.iteye.com/blog/339756),我现在把我对图例A2的一个解决方案公布出来,请大家多指点
节点匹配搜索算法(用于解决标准对称流程图条件汇聚点运行控制参数的算法)
需要解决的问题:已知分支
Linux中用shell获取昨天、明天或多天前的日期
daizj
linux shell 上几年 昨天 获取上几个月
在Linux中可以通过date命令获取昨天、明天、上个月、下个月、上一年和下一年
# 获取昨天
date -d 'yesterday' # 或 date -d 'last day'
# 获取明天
date -d 'tomorrow' # 或 date -d 'next day'
# 获取上个月
date -d 'last month'
#
我所理解的云计算
dongwei_6688
云计算
在刚开始接触到一个概念时,人们往往都会去探寻这个概念的含义,以达到对其有一个感性的认知,在Wikipedia上关于“云计算”是这么定义的,它说:
Cloud computing is a phrase used to describe a variety of computing co
YII CMenu配置
dcj3sjt126com
yii
Adding id and class names to CMenu
We use the id and htmlOptions to accomplish this. Watch.
//in your view
$this->widget('zii.widgets.CMenu', array(
'id'=>'myMenu',
'items'=>$this-&g
设计模式之静态代理与动态代理
come_for_dream
设计模式
静态代理与动态代理
代理模式是java开发中用到的相对比较多的设计模式,其中的思想就是主业务和相关业务分离。所谓的代理设计就是指由一个代理主题来操作真实主题,真实主题执行具体的业务操作,而代理主题负责其他相关业务的处理。比如我们在进行删除操作的时候需要检验一下用户是否登陆,我们可以删除看成主业务,而把检验用户是否登陆看成其相关业务
【转】理解Javascript 系列
gcc2ge
JavaScript
理解Javascript_13_执行模型详解
摘要: 在《理解Javascript_12_执行模型浅析》一文中,我们初步的了解了执行上下文与作用域的概念,那么这一篇将深入分析执行上下文的构建过程,了解执行上下文、函数对象、作用域三者之间的关系。函数执行环境简单的代码:当调用say方法时,第一步是创建其执行环境,在创建执行环境的过程中,会按照定义的先后顺序完成一系列操作:1.首先会创建一个
Subsets II
hcx2013
set
Given a collection of integers that might contain duplicates, nums, return all possible subsets.
Note:
Elements in a subset must be in non-descending order.
The solution set must not conta
Spring4.1新特性——Spring缓存框架增强
jinnianshilongnian
spring4
目录
Spring4.1新特性——综述
Spring4.1新特性——Spring核心部分及其他
Spring4.1新特性——Spring缓存框架增强
Spring4.1新特性——异步调用和事件机制的异常处理
Spring4.1新特性——数据库集成测试脚本初始化
Spring4.1新特性——Spring MVC增强
Spring4.1新特性——页面自动化测试框架Spring MVC T
shell嵌套expect执行命令
liyonghui160com
一直都想把expect的操作写到bash脚本里,这样就不用我再写两个脚本来执行了,搞了一下午终于有点小成就,给大家看看吧.
系统:centos 5.x
1.先安装expect
yum -y install expect
2.脚本内容:
cat auto_svn.sh
#!/bin/bash
Linux实用命令整理
pda158
linux
0. 基本命令 linux 基本命令整理
1. 压缩 解压 tar -zcvf a.tar.gz a #把a压缩成a.tar.gz tar -zxvf a.tar.gz #把a.tar.gz解压成a
2. vim小结 2.1 vim替换 :m,ns/word_1/word_2/gc
独立开发人员通向成功的29个小贴士
shoothao
独立开发
概述:本文收集了关于独立开发人员通向成功需要注意的一些东西,对于具体的每个贴士的注解有兴趣的朋友可以查看下面标注的原文地址。
明白你从事独立开发的原因和目的。
保持坚持制定计划的好习惯。
万事开头难,第一份订单是关键。
培养多元化业务技能。
提供卓越的服务和品质。
谨小慎微。
营销是必备技能。
学会组织,有条理的工作才是最有效率的。
“独立
JAVA中堆栈和内存分配原理
uule
java
1、栈、堆
1.寄存器:最快的存储区, 由编译器根据需求进行分配,我们在程序中无法控制.2. 栈:存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(new 出来的对象)或者常量池中(字符串常量对象存放在常量池中。)3. 堆:存放所有new出来的对象。4. 静态域:存放静态成员(static定义的)5. 常量池:存放字符串常量和基本类型常量(public static f