网站功能模块图/百度贴吧人工客服
目录
一、简介
( 1 ) 是什么
( 2 ) 分类
( 3 ) 作用
二、自定义注解
( 1 ) 如何自定义注解
( 2 ) 场景演示
场景一(获取类与方法上的注解值)
场景二( 获取类属性上的注解属性值 )
场景三( 获取参数修饰注解对应的属性值 )
三、Aop自定义注解的应用
带给我们的收获
一、简介
( 1 ) 是什么
在Spring MVC中,自定义注解是一种通过Java语言提供的元注解机制,用于在控制器方法、参数、类等地方添加注解,从而实现特定的功能或行为。
在Spring MVC中,自定义注解是一种用于标记和定义特定功能的注解。通过自定义注解,可以在控制器方法、参数、类等地方添加注解,从而实现特定的功能或行为。
Java注解是附加在代码中的一些元信息,用于一些工具在编译、运行时进行解析和使用,起到说明、配置的功能。 注解相关类都包含在java.lang.annotation包中
通过自定义注解,可以提高代码的可读性和可维护性,同时也可以减少重复的代码编写。在Spring MVC中,可以使用Java的元注解来定义自定义注解,例如
@Target
、@Retention
、@Documented
等。
通过自定义注解,可以提高代码的可读性和可维护性,同时也可以减少重复的代码编写。在Spring MVC中,自定义注解可以应用于控制器方法的映射、参数校验、数据绑定、AOP切面等方面,从而实现特定的功能。
( 2 ) 分类
Java注解可以分为三类:
1. 元注解(Meta-Annotation):元注解是用来注解其他注解的注解,用于对注解进行说明和定义。常用的元注解有四种:
- - @Retention:用于指定注解的保留策略,即注解在什么地方有效。
- 有三个取值:RetentionPolicy.SOURCE(注解仅在源代码中有效)、RetentionPolicy.CLASS(注解在源代码和class文件中有效,默认值)、RetentionPolicy.RUNTIME(注解在运行时有效)。
- - @Target:用于指定注解的作用目标,即注解可以应用在哪些元素上。
- 常用的取值有:ElementType.TYPE(类、接口、枚举)、ElementType.FIELD(字段)、ElementType.METHOD(方法)、ElementType.PARAMETER(方法参数)、ElementType.CONSTRUCTOR(构造函数)、ElementType.LOCAL_VARIABLE(局部变量)、ElementType.ANNOTATION_TYPE(注解)、ElementType.PACKAGE(包)等。
- - @Documented:用于指定注解是否包含在JavaDoc中。
- - @Inherited:用于指定注解是否可以被继承。
2. 基本注解(Built-in Annotation):基本注解是Java内置的一些注解,用于标记和修饰代码。常用的基本注解有三个:
- - @Override:用于标记方法覆盖父类的方法。
- - @Deprecated:用于标记已过时的方法、类或字段。
- - @SuppressWarnings:用于抑制编译器警告。
3. 自定义注解(Custom Annotation):自定义注解是开发者根据业务需求自行定义的注解,用于标记和修饰代码。自定义注解可以通过元注解的方式进行配置,以达到特定的目的。自定义注解的作用可以是:
- - 标记和识别特定的代码逻辑或功能。
- - 提供额外的元数据,用于生成文档、配置文件等。
- - 在运行时通过反射获取注解信息,实现一些特定的逻辑。
- - 与其他框架或工具进行集成,实现特定的功能。
总结:元注解用于对其他注解进行说明和定义,基本注解是Java内置的用于标记和修饰代码的注解,而自定义注解是根据业务需求自行定义的注解,用于标记和修饰代码,并提供额外的元数据和功能。
( 3 ) 作用
在Spring MVC中,自定义注解可以用于实现以下功能:
- 1. 请求映射:可以使用自定义注解来标记Controller中的方法,用于指定请求的URL路径和请求方法。例如,可以定义一个自定义注解`@GetMapping`,用于标记处理GET请求的方法,简化了在`@RequestMapping`中指定请求方法的操作。
- 2. 参数绑定:可以使用自定义注解来标记Controller中方法的参数,用于指定参数的来源和绑定规则。例如,可以定义一个自定义注解`@PathVariable`,用于标记方法参数,表示该参数从URL路径中获取。
- 3. 参数校验:可以使用自定义注解来标记方法的参数,用于指定参数的校验规则。例如,可以定义一个自定义注解`@Valid`,用于标记方法参数,表示该参数需要进行校验。
- 4. AOP切面:可以使用自定义注解来标记需要进行AOP切面处理的方法或类。例如,可以定义一个自定义注解`@Log`,用于标记需要记录日志的方法,然后通过AOP切面对标记了`@Log`注解的方法进行日志记录。
- 5. 权限控制:可以使用自定义注解来标记需要进行权限控制的方法或类。例如,可以定义一个自定义注解`@RequiresPermission`,用于标记需要进行权限验证的方法,然后通过AOP切面对标记了`@RequiresPermission`注解的方法进行权限验证。
通过自定义注解,可以使代码更加简洁、易读,并且可以实现一些特定的功能,提高开发效率和代码的可维护性。在Spring MVC中,自定义注解的应用非常广泛,可以根据具体的业务需求进行自定义注解的定义和使用。
二、自定义注解
( 1 ) 如何自定义注解
要自定义注解,需要使用Java提供的元注解来对注解进行配置,然后使用@interface关键字定义注解的名称和属性。以下是自定义注解的步骤:
1 . 使用元注解配置注解的行为和作用范围。常用的元注解有:
- @Retention:用于指定注解的生命周期。常用的取值有RetentionPolicy.SOURCE(注解在编译期丢弃)、RetentionPolicy.CLASS(注解在编译期保留,但在运行时丢弃,默认值)、RetentionPolicy.RUNTIME(注解在运行时保留)。
- @Target:用于指定注解的作用目标。常用的取值有ElementType.TYPE(类、接口、枚举)、ElementType.FIELD(字段)、ElementType.METHOD(方法)、ElementType.PARAMETER(方法参数)、ElementType.CONSTRUCTOR(构造函数)、ElementType.LOCAL_VARIABLE(局部变量)、ElementType.ANNOTATION_TYPE(注解)、ElementType.PACKAGE(包)等。
- @Documented:用于指定注解是否包含在JavaDoc中。
- @Inherited:用于指定注解是否可以被继承。
@Deprecated:用于标记已过时的注解。当一个注解被标记为@Deprecated时,表示该注解已不推荐使用,可以使用其他替代的注解。
@Native:用于指定注解是否为本地注解。本地注解是指由JDK或第三方库提供的注解,而不是自定义的注解。
@SuppressWarnings:用于抑制编译器警告。可以使用@SuppressWarnings注解来忽略特定的警告信息,例如未使用的变量、未检查的类型转换等。
2 . 使用@interface关键字定义注解的名称和属性。注解的名称可以是任意合法的Java标识符,通常以大写字母开头。注解的属性使用方法类似于接口的方法,可以指定默认值。
3 . 在需要使用注解的地方使用注解。可以在类、方法、字段等地方使用自定义注解,并根据注解的属性进行配置。
4 . 在运行时通过反射获取注解信息。可以使用Java的反射机制,在运行时获取类、方法、字段等上的注解信息,并根据注解的属性进行特定的逻辑处理。
以下是一个示例,演示了如何自定义一个简单的注解:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyAnnotation {String value() default "";int count() default 0;
}
在上面的示例中,定义了一个名为
MyAnnotation
的注解,使用了@Retention(RetentionPolicy.RUNTIME)
元注解指定了注解在运行时保留,使用了@Target(ElementType.METHOD)
元注解指定了注解可以应用在方法上。注解中定义了两个属性,一个是value
,一个是count
,并指定了默认值。
然后可以在需要使用注解的地方使用@MyAnnotation
来标记方法,
并根据需要配置注解的属性值:
@MyAnnotation(value = "Hello", count = 10)
public void myMethod() {// do something
}
在运行时,可以使用反射来获取注解的信息:
Method method = MyClass.class.getMethod("myMethod");
MyAnnotation annotation = method.getAnnotation(MyAnnotation.class);
String value = annotation.value(); // 获取注解的属性值
int count = annotation.count();
通过以上步骤,就可以自定义注解并在代码中使用了。根据具体的业务需求,可以定义不同的注解,并使用注解来实现特定的功能。
( 2 ) 场景演示
创建完项目之后,找到 pom.xml 配置文件 ,进行项目引用导入。
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.example</groupId><artifactId>CloudJunzySSM</artifactId><version>1.0-SNAPSHOT</version><packaging>war</packaging><name>CloudJunzySSM Maven Webapp</name><!-- FIXME change it to the project's website --><url>http://www.example.com</url><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target><maven.compiler.plugin.version>3.7.0</maven.compiler.plugin.version><!--添加jar包依赖--><!--1.spring 5.0.2.RELEASE相关--><spring.version>5.0.2.RELEASE</spring.version><!--2.mybatis相关--><mybatis.version>3.4.5</mybatis.version><!--mysql--><mysql.version>5.1.44</mysql.version><!--pagehelper分页jar依赖--><pagehelper.version>5.1.2</pagehelper.version><!--mybatis与spring集成jar依赖--><mybatis.spring.version>1.3.1</mybatis.spring.version><!--3.dbcp2连接池相关 druid--><commons.dbcp2.version>2.1.1</commons.dbcp2.version><commons.pool2.version>2.4.3</commons.pool2.version><!--4.log日志相关--><log4j2.version>2.9.1</log4j2.version><log4j2.disruptor.version>3.2.0</log4j2.disruptor.version><slf4j.version>1.7.13</slf4j.version><!--5.其他--><junit.version>4.12</junit.version><servlet.version>4.0.0</servlet.version><lombok.version>1.18.2</lombok.version><mybatis.ehcache.version>1.1.0</mybatis.ehcache.version><ehcache.version>2.10.0</ehcache.version><redis.version>2.9.0</redis.version><redis.spring.version>1.7.1.RELEASE</redis.spring.version><jackson.version>2.9.3</jackson.version><jstl.version>1.2</jstl.version><standard.version>1.1.2</standard.version><tomcat-jsp-api.version>8.0.47</tomcat-jsp-api.version><commons-fileupload.version>1.3.3</commons-fileupload.version><hibernate-validator.version>5.0.2.Final</hibernate-validator.version><shiro.version>1.3.2</shiro.version></properties><dependencies><!--1.spring相关--><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-beans</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-orm</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-tx</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-web</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>${spring.version}</version></dependency><!--2.mybatis相关--><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>${mybatis.version}</version></dependency><!--mysql--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>${mysql.version}</version></dependency><!--pagehelper分页插件jar包依赖--><dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper</artifactId><version>${pagehelper.version}</version></dependency><!--mybatis与spring集成jar包依赖--><dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>${mybatis.spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context-support</artifactId><version>${spring.version}</version></dependency><!--mybatis与ehcache整合--><dependency><groupId>org.mybatis.caches</groupId><artifactId>mybatis-ehcache</artifactId><version>${mybatis.ehcache.version}</version></dependency><!--ehcache依赖--><dependency><groupId>net.sf.ehcache</groupId><artifactId>ehcache</artifactId><version>${ehcache.version}</version></dependency><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>${redis.version}</version></dependency><dependency><groupId>org.springframework.data</groupId><artifactId>spring-data-redis</artifactId><version>${redis.spring.version}</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>${jackson.version}</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-core</artifactId><version>${jackson.version}</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-annotations</artifactId><version>${jackson.version}</version></dependency><!--3.dbcp2连接池相关--><dependency><groupId>org.apache.commons</groupId><artifactId>commons-dbcp2</artifactId><version>${commons.dbcp2.version}</version><exclusions><exclusion><artifactId>commons-pool2</artifactId><groupId>org.apache.commons</groupId></exclusion></exclusions></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId><version>${commons.pool2.version}</version></dependency><!--springmvc依赖--><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>${spring.version}</version></dependency><!--4.log日志相关依赖--><!-- log4j2日志相关依赖 --><!-- log配置:Log4j2 + Slf4j --><!-- slf4j核心包--><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>${slf4j.version}</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>jcl-over-slf4j</artifactId><version>${slf4j.version}</version><scope>runtime</scope></dependency><!--核心log4j2jar包--><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-api</artifactId><version>${log4j2.version}</version></dependency><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-core</artifactId><version>${log4j2.version}</version></dependency><!--用于与slf4j保持桥接--><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-slf4j-impl</artifactId><version>${log4j2.version}</version></dependency><!--web工程需要包含log4j-web,非web工程不需要--><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-web</artifactId><version>${log4j2.version}</version><scope>runtime</scope></dependency><!--需要使用log4j2的AsyncLogger需要包含disruptor--><dependency><groupId>com.lmax</groupId><artifactId>disruptor</artifactId><version>${log4j2.disruptor.version}</version></dependency><!--5.其他--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>${junit.version}</version>
<!-- <scope>test</scope>--></dependency><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>${servlet.version}</version><scope>provided</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>${lombok.version}</version><scope>provided</scope></dependency><dependency><groupId>jstl</groupId><artifactId>jstl</artifactId><version>${jstl.version}</version></dependency><dependency><groupId>taglibs</groupId><artifactId>standard</artifactId><version>${standard.version}</version></dependency><dependency><groupId>org.apache.tomcat</groupId><artifactId>tomcat-jsp-api</artifactId><version>${tomcat-jsp-api.version}</version></dependency><dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>${commons-fileupload.version}</version></dependency><dependency><groupId>org.hibernate</groupId><artifactId>hibernate-validator</artifactId><version>${hibernate-validator.version}</version></dependency><!--shiro依赖--><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-core</artifactId><version>${shiro.version}</version></dependency><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-web</artifactId><version>${shiro.version}</version></dependency><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring</artifactId><version>${shiro.version}</version></dependency></dependencies><build><finalName>CloudJunzySSM</finalName><resources><!--解决mybatis-generator-maven-plugin运行时没有将XxxMapper.xml文件放入target文件夹的问题--><resource><directory>src/main/java</directory><includes><include>**/*.xml</include></includes></resource><!--解决mybatis-generator-maven-plugin运行时没有将jdbc.properites文件放入target文件夹的问题--><resource><directory>src/main/resources</directory><includes><include>*.properties</include><include>*.xml</include></includes></resource></resources><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>${maven.compiler.plugin.version}</version><configuration><source>${maven.compiler.source}</source><target>${maven.compiler.target}</target><encoding>${project.build.sourceEncoding}</encoding></configuration></plugin><plugin><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-maven-plugin</artifactId><version>1.3.2</version><dependencies><!--使用Mybatis-generator插件不能使用太高版本的mysql驱动 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>${mysql.version}</version></dependency></dependencies><configuration><overwrite>true</overwrite></configuration></plugin><plugin><artifactId>maven-clean-plugin</artifactId><version>3.1.0</version></plugin><!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging --><plugin><artifactId>maven-resources-plugin</artifactId><version>3.0.2</version></plugin><plugin><artifactId>maven-compiler-plugin</artifactId><version>3.8.0</version></plugin><plugin><artifactId>maven-surefire-plugin</artifactId><version>2.22.1</version></plugin><plugin><artifactId>maven-war-plugin</artifactId><version>3.2.2</version></plugin><plugin><artifactId>maven-install-plugin</artifactId><version>2.5.2</version></plugin><plugin><artifactId>maven-deploy-plugin</artifactId><version>2.8.2</version></plugin></plugins></build>
</project>
创建配置文件 spring-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><!-- spring框架和mybatis进行整合的配置文件加载到spring的上下文中-->
<import resource="classpath:spring-mybatis.xml"></import></beans>
创建配置文件 spring-mybatis.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"><!--1. 注解式开发 --><!-- 注解驱动 --><context:annotation-config/><!-- 用注解方式注入bean,并指定查找范围:com.CloudJun及子子孙孙包--><context:component-scan base-package="com.CloudJun"/><context:property-placeholder location="classpath:jdbc.properties"/><bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource"destroy-method="close"><property name="driverClassName" value="${jdbc.driver}"/><property name="url" value="${jdbc.url}"/><property name="username" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/><!--初始连接数--><property name="initialSize" value="10"/><!--最大活动连接数--><property name="maxTotal" value="100"/><!--最大空闲连接数--><property name="maxIdle" value="50"/><!--最小空闲连接数--><property name="minIdle" value="10"/><!--设置为-1时,如果没有可用连接,连接池会一直无限期等待,直到获取到连接为止。--><!--如果设置为N(毫秒),则连接池会等待N毫秒,等待不到,则抛出异常--><property name="maxWaitMillis" value="-1"/></bean><!--4. spring和MyBatis整合 --><!--1) 创建sqlSessionFactory--><bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><!-- 指定数据源 --><property name="dataSource" ref="dataSource"/><!-- 自动扫描XxxMapping.xml文件,**是任意路径 --><property name="mapperLocations" value="classpath*:com/CloudJun/**/mapper/*.xml"/><!-- 指定别名 --><property name="typeAliasesPackage" value="com/CloudJun/**/model"/><!--配置pagehelper插件--><property name="plugins"><array><bean class="com.github.pagehelper.PageInterceptor"><property name="properties"><value>helperDialect=mysql</value></property></bean></array></property></bean><!--2) 自动扫描com/CloudJun/**/mapper下的所有XxxMapper接口(其实就是DAO接口),并实现这些接口,--><!-- 即可直接在程序中使用dao接口,不用再获取sqlsession对象--><bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"><!--basePackage 属性是映射器接口文件的包路径。--><!--你可以使用分号或逗号 作为分隔符设置多于一个的包路径--><property name="basePackage" value="com/CloudJun/**/mapper"/><property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/></bean><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource" /></bean><tx:annotation-driven transaction-manager="transactionManager" /><aop:aspectj-autoproxy/>
</beans>
创建配置文件 spring-mvc.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-4.3.xsdhttp://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/spring-mvc.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-4.3.xsd"><!--1) 扫描com.CloudJun及子子孙孙包下的控制器(扫描范围过大,耗时)--><context:component-scan base-package="com.CloudJun"/><!--2) 此标签默认注册DefaultAnnotationHandlerMapping和AnnotationMethodHandlerAdapter --><mvc:annotation-driven /><!--3) 创建ViewResolver视图解析器 --><bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"><!-- viewClass需要在pom中引入两个包:standard.jar and jstl.jar --><property name="viewClass"value="org.springframework.web.servlet.view.JstlView"></property><property name="prefix" value="/WEB-INF/jsp/"/><property name="suffix" value=".jsp"/></bean><!--4) 单独处理图片、样式、js等资源 --><!-- <mvc:resources location="/css/" mapping="/css/**"/><mvc:resources location="/js/" mapping="/js/**"/><mvc:resources location="WEB-INF/images/" mapping="/images/**"/>--><!-- 处理static包里的所有静态资源 --><mvc:resources location="/static/" mapping="/static/**"/><!-- 处理文件上传下载的资源 --><bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"><!-- 必须和用户JSP 的pageEncoding属性一致,以便正确解析表单的内容 --><property name="defaultEncoding" value="UTF-8"></property><!-- 文件最大大小(字节) 1024*1024*50=50M--><property name="maxUploadSize" value="52428800"></property><!--resolveLazily属性启用是为了推迟文件解析,以便捕获文件大小异常--><property name="resolveLazily" value="true"/></bean><!--<!– <!–配置自定义拦截器–>–>-->
<!-- <mvc:interceptors>-->
<!-- <bean class="com.CloudJun.Interceptor.OneInterceptor"></bean>-->
<!-- </mvc:interceptors>--><!-- <!–2) 配置自定义多拦截器(拦截器链)–>-->
<!-- <mvc:interceptors>-->
<!-- <!– 拦截所以有用请求地址 –>-->
<!-- <mvc:interceptor>-->
<!-- <mvc:mapping path="/**"/>-->
<!-- <bean class="com.CloudJun.Interceptor.OneInterceptor"/>-->
<!-- </mvc:interceptor>-->
<!-- <!– 只拦截中间有用名为clz的请求地址 –>-->
<!-- <mvc:interceptor>-->
<!-- <mvc:mapping path="/hot/**"/>-->
<!-- <bean class="com.CloudJun.Interceptor.TwoInterceptor"/>-->
<!-- </mvc:interceptor>-->
<!-- </mvc:interceptors>--><!--<!– 用户权限的请求拦截–>-->
<!-- <mvc:interceptors>-->
<!-- <bean class="com.CloudJun.Interceptor.LoginInterceptor"></bean>-->
<!-- </mvc:interceptors>--><bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"><property name="messageConverters"><list><ref bean="mappingJackson2HttpMessageConverter"/></list></property></bean><bean id="mappingJackson2HttpMessageConverter"class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"><!--处理中文乱码以及避免IE执行AJAX时,返回JSON出现下载文件--><property name="supportedMediaTypes"><list><value>text/html;charset=UTF-8</value><value>text/json;charset=UTF-8</value><value>application/json;charset=UTF-8</value></list></property></bean><!-- springmvc提供的简单异常处理器 --><bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"><!-- 定义默认的异常处理页面 --><property name="defaultErrorView" value="error"/><!-- 定义异常处理页面用来获取异常信息的变量名,也可不定义,默认名为exception --><property name="exceptionAttribute" value="ex"/><!-- 定义需要特殊处理的异常,这是重要点 --><property name="exceptionMappings"><props><prop key="java.lang.RuntimeException">error</prop></props><!-- 还可以定义其他的自定义异常 --></property></bean><!--处理controller层发送请求到biz层,会经过切面拦截处理--><aop:aspectj-autoproxy/>
</beans>
也可以不进行以上配置及导入,一下是基于我博客中代码进行知识点扩展
SpringMVC之JSON数据返回及异常处理机制
重写创建的项目才需要导入以上引用及配置
场景一(获取类与方法上的注解值)
创建 TranscationModel 直接C到包里接口
package com.CloudJun.annotation;public enum TranscationModel {Read, Write, ReadWrite
}
创建 MyAnnotation1 直接C到包里接口
package com.CloudJun.annotation;import java.lang.annotation.*;/*** @author CloudJun* MyAnnotation1注解可以用在类、接口、属性、方法上* 注解运行期也保留* 不可继承*/
@Target({ElementType.TYPE, ElementType.FIELD,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
//@Inherited //继承使用需要该注解,否则读取不到已继承的注解及属性
@Documented
public @interface MyAnnotation1 {String name();
}
创建 MyAnnotation2 直接C到包里接口
package com.CloudJun.annotation;import java.lang.annotation.*;/*** @author CloudJun* MyAnnotation2注解可以用在方法上* 注解运行期也保留* 不可继承*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyAnnotation2 {TranscationModel model() default TranscationModel.ReadWrite;
}
创建 MyAnnotation3 直接C到包里接口
package com.CloudJun.annotation;import java.lang.annotation.*;/*** @author CloudJun* MyAnnotation3注解可以用在方法上* 注解运行期也保留* 可继承*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface MyAnnotation3 {TranscationModel[] models() default TranscationModel.ReadWrite;
}
创建测试类进行自定义注解测试 Demo1
package com.CloudJun.annotation.Demo1;import com.CloudJun.annotation.MyAnnotation1;
import com.CloudJun.annotation.MyAnnotation2;
import com.CloudJun.annotation.MyAnnotation3;
import com.CloudJun.annotation.TranscationModel;/*** @author CloudJun* 获取类与方法上的注解值*/
@MyAnnotation1(name = "Cloud")
public class Demo1 {@MyAnnotation1(name = "Jun")private Integer age;@MyAnnotation2(model = TranscationModel.Read)public void list() {System.out.println("list");}@MyAnnotation3(models = {TranscationModel.Read, TranscationModel.Write})public void edit() {System.out.println("edit");}
}
创建测试类进行自定义注解测试 Demo1Test
package com.CloudJun.annotation.Demo1;import com.CloudJun.annotation.MyAnnotation1;
import com.CloudJun.annotation.MyAnnotation2;
import com.CloudJun.annotation.MyAnnotation3;
import com.CloudJun.annotation.TranscationModel;
import org.junit.Test;/*** @author CloudJun*/
public class Demo1Test {@Testpublic void list() throws Exception {
// 获取类上的注解MyAnnotation1 annotation1 = Demo2.class.getAnnotation(MyAnnotation1.class);System.out.println(annotation1.name());//Cloud// 获取方法上的注解MyAnnotation2 myAnnotation2 = Demo1.class.getMethod("list").getAnnotation(MyAnnotation2.class);System.out.println(myAnnotation2.model());//Read// 获取属性上的注解MyAnnotation1 myAnnotation1 = Demo1.class.getDeclaredField("age").getAnnotation(MyAnnotation1.class);System.out.println(myAnnotation1.name());// Jun}@Testpublic void edit() throws Exception {MyAnnotation3 myAnnotation3 = Demo1.class.getMethod("edit").getAnnotation(MyAnnotation3.class);for (TranscationModel model : myAnnotation3.models()) {System.out.println(model);//Read,Write}}
}
执行其中的方法( list )进行测试,输出结果如下 :
执行其中的方法( edit)进行测试,输出结果如下 :
场景二( 获取类属性上的注解属性值 )
场景自定义注解 TestAnnotation
package com.CloudJun.annotation.Demo2;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** @author CloudJun*/
//@Retention(RetentionPolicy.SOURCE)
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface TestAnnotation {String value() default "默认value值";String what() default "这里是默认的what属性对应的值";
}
创建测试类进行自定义注解的测试 Demo2
package com.CloudJun.annotation.Demo2;/*** @author CloudJun* 获取类属性上的注解属性值*/
public class Demo2 {@TestAnnotation(value = "这里是value对应的值--msg1", what = "这里是what对应的值--msg1")private static String msg1;@TestAnnotation("这就是value对应的值==pa")private static String msg2;@TestAnnotation(value = "这就是value对应的值==as")private static String msg3;@TestAnnotation(what = "这就是what对应的值")private static String msg4;
}
创建测试类进行自定义注解的测试 Demo2Test
package com.CloudJun.annotation.Demo2;import org.junit.Test;/*** @author CloudJun* 1.value--默认值* 2.default--默认值的赋予*/
public class Demo2Test {@Testpublic void test1() throws Exception {TestAnnotation msg1 = Demo2.class.getDeclaredField("msg1").getAnnotation(TestAnnotation.class);System.out.println(msg1.value());System.out.println(msg1.what());}@Testpublic void test2() throws Exception{TestAnnotation msg2 = Demo2.class.getDeclaredField("msg2").getAnnotation(TestAnnotation.class);System.out.println(msg2.value());System.out.println(msg2.what());}@Testpublic void test3() throws Exception{TestAnnotation msg3 = Demo2.class.getDeclaredField("msg3").getAnnotation(TestAnnotation.class);System.out.println(msg3.value());System.out.println(msg3.what());}@Testpublic void test4() throws Exception{TestAnnotation msg4 = Demo2.class.getDeclaredField("msg4").getAnnotation(TestAnnotation.class);System.out.println(msg4.value());System.out.println(msg4.what());}
}
执行其中 test1 的方法进行测试,输出结果为 :
执行其中 test2 的方法进行测试,输出结果为 :
执行其中 test3 的方法进行测试,输出结果为 :
执行其中 test4 的方法进行测试,输出结果为 :
场景三( 获取参数修饰注解对应的属性值 )
创建自定义注解 IsNotNull
package com.CloudJun.annotation.Demo3;import java.lang.annotation.*;/*** @author CloudJun* 非空注解:* 使用在方法的参数上,false表示此参数可以为空,true不能为空*/
@Documented
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface IsNotNull {boolean value() default false;
}
创建测试类 Demo3
package com.CloudJun.annotation.Demo3;/*** @author CloudJun* 获取参数修饰注解对应的属性值*/
public class Demo3 {public void hello1(@IsNotNull(true) String name) {System.out.println("hello:" + name);}public void hello2(@IsNotNull String name) {System.out.println("hello:" + name);}
}
创建测试类 Demo3Test进行方法测试
package com.CloudJun.annotation.Demo3;import org.junit.Test;import java.lang.reflect.Method;
import java.lang.reflect.Parameter;/*** @author CloudJun*/
public class Demo3Test {@Testpublic void hello1() throws Exception {Demo3 demo3 = new Demo3();for (Parameter parameter : demo3.getClass().getMethod("hello1", String.class).getParameters()) {IsNotNull annotation = parameter.getAnnotation(IsNotNull.class);if(annotation != null){//如果值没有设置,将会是默认值为:falseSystem.out.println(annotation.value());//true}}}@Testpublic void hello2() throws Exception {Demo3 demo3 = new Demo3();for (Parameter parameter : demo3.getClass().getMethod("hello2", String.class).getParameters()) {IsNotNull annotation = parameter.getAnnotation(IsNotNull.class);if(annotation != null){//如果值有设置,将会是默认值为:trueSystem.out.println(annotation.value());//false}}}@Testpublic void hello3() throws Exception {
// 模拟浏览器传递到后台的参数 解读@requestParamString name = "独孤九剑";Demo3 demo3 = new Demo3();Method method = demo3.getClass().getMethod("hello1", String.class);for (Parameter parameter : method.getParameters()) {IsNotNull annotation = parameter.getAnnotation(IsNotNull.class);if(annotation != null){System.out.println(annotation.value());//trueif (annotation.value() && !"".equals(name)){method.invoke(demo3,name);}}}}
}
执行其中的方法( hello1 )进行测试,输出结果为 :
执行其中的方法( hello2 )进行测试,输出结果为 :
执行其中的方法( hello3 )进行测试,输出结果为 :
三、Aop自定义注解的应用
AOP(面向切面编程)是一种编程范式,它通过在程序运行时动态地将额外的逻辑织入到方法或类中,从而实现对方法或类的增强。自定义注解可以与AOP结合使用,用于标记需要进行增强的方法或类。
以下是一个示例,演示了如何使用自定义注解与AOP结合,实现日志记录的功能:
1 .定义自定义注解@MyLog
,用于标记需要记录日志的方法:
package com.CloudJun.annotation.aop;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;/*** @author CloudJun*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyLog {String desc();
}
2 . 定义切面类MyLogAspect
,在该类中定义增强逻辑,例如记录日志:
package com.CloudJun.aspect;import com.CloudJun.annotation.aop.MyLog;
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.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;/*** @author CloudJun*/
@Component
@Aspect
public class MyLogAspect {private static final Logger logger = LoggerFactory.getLogger(MyLogAspect.class);/*** 只要用到了com.CloudJun.annotation.aop.MyLog这个注解的,就是目标类* 是目标类就会执行以下before方法里的代码*/@Pointcut("@annotation(com.CloudJun.annotation.aop.MyLog)")private void MyValid() {}@Before("MyValid()")public void before(JoinPoint joinPoint) {MethodSignature signature = (MethodSignature) joinPoint.getSignature();logger.debug("[" + signature.getName() + " : start.....]");System.out.println("[" + signature.getName() + " : start.....]");MyLog myLog = signature.getMethod().getAnnotation(MyLog.class);logger.debug("【目标对象方法被调用时候产生的日志,记录到日志表中】:"+myLog.desc());System.out.println("【目标对象方法被调用时候产生的日志,记录到日志表中】:" + myLog.desc());}// @Around("MyValid()")
// public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
// long startTime = System.currentTimeMillis();
// System.out.println(pjp.getTarget());//获取目标方法
// System.out.println(pjp.getThis());//
// Object[] args = pjp.getArgs();//获取参数
// System.out.println(Arrays.toString(args));//输出参数
// Object ob = pjp.proceed();//获取方法返回值
// System.out.println(ob);//输出返回值
// logger.info("耗时 : " + (System.currentTimeMillis() - startTime));
// return ob;
// }}
在上面的切面类中,使用
@Aspect
注解标记该类为切面类。@Pointcut("@annotation(com.CloudJun.annotation.aop.MyLog)")
注解用于定义切点,表示匹配所有标记有@Log
注解的方法。@Before
注解表示在目标方法执行前执行增强逻辑。
3 . 创建一个控制器 LogController
package com.CloudJun.web;import com.CloudJun.annotation.aop.MyLog;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;import javax.servlet.http.HttpServletRequest;/*** @author CloudJun*/
@Controller
public class LogController {@RequestMapping("/myLog")@MyLog(desc = "这是结合spring aop知识,讲解自定义注解应用的一个案例")public void testLogAspect(HttpServletRequest request){request.getRemoteAddr();//这里是获取请求IP,可以输出或者保存在某个地方及属性request.getRemotePort();//这里是获取请求端口,可以输出或者保存在某个地方及属性System.out.println("这里随便来点啥");}
}
自定义注解与AOP结合使用,可以实现各种不同的功能,如权限控制、性能监控、事务管理等。根据具体的业务需求,可以定义不同的注解,并在切面类中实现相应的增强逻辑。
测试
开启服务器,在浏览器中进行访问地址,进行测试( 以下访问地址是根据自己配置而修改的 )
访问该地址进行测试 : localhost:8081/ssm/
myLog ( 结果如下 )
将切面类中( MyLogAspect ) 的 before 方法进行注释,将其中的 doAround 方法注释打开
同样访问该地址进行测试 : localhost:8081/ssm/myLog ( 结果如下 )
小总结
通过自定义注解与AOP结合使用,可以实现各种不同的功能,根据具体的业务需求进行定制化开发。这种方式可以将横切逻辑与业务逻辑分离,提高代码的可维护性和可扩展性,同时也减少了代码的重复编写。
带给我们的收获
学习SpringMVC中的自定义注解和AOP自定义注解的应用可以带来以下几个方面的收获:
1. 提高代码重用性:通过自定义注解,我们可以将一些常用的功能逻辑抽象为注解,然后在需要的地方进行标记和使用。这样可以减少代码的重复编写,提高代码的可维护性和可读性。
2. 简化开发流程:通过自定义注解,我们可以简化一些繁琐的配置和操作。比如,在SpringMVC中,我们可以使用自定义注解来标记控制器的映射路径,从而省去手动配置URL映射的步骤,简化了开发流程。
3. 实现横切关注点:AOP(面向切面编程)可以通过自定义注解来实现横切关注点的功能,例如日志记录、事务管理、权限控制等。通过在代码中标记自定义注解,可以将这些关注点与业务逻辑分离,提高代码的可维护性和可扩展性。
4. 代码解耦和模块化:通过自定义注解和AOP,我们可以将一些功能逻辑和横切关注点从业务代码中解耦出来,实现模块化的开发。这样可以降低代码的耦合度,提高代码的可测试性和可维护性。
总的来说,学习SpringMVC中的自定义注解和AOP自定义注解的应用,可以提高代码的重用性、简化开发流程,实现横切关注点,解耦业务代码,从而带来更加高效、可维护和可扩展的代码开发和管理。
相关文章:

学会SpringMVC之自定义注解各种场景应用,提高开发效率及代码质量
目录 一、简介 ( 1 ) 是什么 ( 2 ) 分类 ( 3 ) 作用 二、自定义注解 ( 1 ) 如何自定义注解 ( 2 ) 场景演示 场景一(获取类与方法上的注解值) 场景二( 获取类属性上的注解属性值 ) 场景三( 获取参数修…...

步态识别常见模块解读及代码实现:基于OpenGait框架
步态识别常见模块解读及代码实现:基于OpenGait框架 最近在看步态识别相关论文,但是因为记忆力下降的原因,老是忘记一些内容。因此记录下来方便以后查阅,仅供自己学习参考,没有背景知识和论文介绍。 目录 步态识别常见…...

前端八股文之“闭包”
一、定义 一句话概括闭包:能够访问函数内部变量的函数与这个变量的组合构成了闭包结构。如下代码 function fuc1(){let num 999return function fuc2(){console.log(num)}}fuc1()(); 如代码所示,fuc2和父级变量num构成了一个闭包环境。 二、原理 子…...

数据可视化:掌握数据领域的万金油技能
⭐️⭐️⭐️⭐️⭐️欢迎来到我的博客⭐️⭐️⭐️⭐️⭐️ 🐴作者:秋无之地 🐴简介:CSDN爬虫、后端、大数据领域创作者。目前从事python爬虫、后端和大数据等相关工作,主要擅长领域有:爬虫、后端、大数据开发、数据分析等。 🐴欢迎小伙伴们点赞👍🏻、收藏⭐️、…...

Apache Kafka 基于 S3 的数据导出、导入、备份、还原、迁移方案
在系统升级或迁移时,用户常常需要将一个 Kafka 集群中的数据导出(备份),然后在新集群或另一个集群中再将数据导入(还原)。通常,Kafka集群间的数据复制和同步多采用 Kafka MirrorMaker࿰…...

事务管理AOP
事务管理 事务回顾 概念:事务是一组操作的集合,它是一个不可分割的工作单位,这些操作要么同时成功,要么同时失败 操作: 开启事务:一组操作开始前,开启事务-start transaction/be…...

Java从Tif中抽取最大的那张图进行裁剪成x*y份
之前我有一篇帖子《kfb格式文件转jpg格式》讲述到 kfb > tif > jpg,但是针对于超大tif中的大图是无法顺利提取的,就算是能顺利提取,试想一下,2G的tif文件,如果能提取处理最大的那张图,并且在不压缩的…...

人工智能AI界的龙头企业,炸裂的“英伟达”时代能走多远
原创 | 文 BFT机器人 1、AI芯片的竞争格局已趋白热化 尽管各类具有不同功能和定位的AI芯片在一定程度上可实现互补,但同时也在机遇与挑战并存中持续调整定位。在AI训练端,英伟达的GPU凭着高算力的门槛,一直都是训练端的首选。 只有少数芯片能…...

【实战】H5 页面同时适配 PC 移动端 —— 旋转横屏
文章目录 一、场景二、方案三、书单推荐01 《深入实践Kotlin元编程》02 《Spring Boot学习指南》03 《Kotlin编程实战》 一、场景 一个做数据监控的单页面,页面主要内容是一个整体必须是宽屏才能正常展示,这时就不能用传统的适配方案了,需要…...

使用凌鲨进行聚合搜索
作为研发人员,我们经常需要在多个来源之间查找信息,以便进行研发工作。除了常用的搜索引擎如百度和必应之外,我们还需要查阅各种代码文档和依赖包等资源。这些资源通常分散在各个网站和文档库中,需要花费一定的时间和精力才能找到…...

程序设计之——手把手教你如何从Excel文件中读取学生信息
在当今信息化时代,计算机技术已经深入到各个领域,而程序设计则成为推动信息化建设的关键技术之一。在众多领域中,学生信息管理系统无疑是其中一个重要的应用。本文将从学生信息管理系统的开发入手,探讨开如何高效且保证质量的完成…...

Docker容器化技术(从零学会Docker)
文章目录 前言一、初识Docker1.初识Docker-Docker概述2.初识Docker-安装Docker3.初识Docker-Docker架构4.初识Docker-配置镜像加速器 二、Docker命令1.Docker命令-服务相关命令2.Docker命令-镜像相关命令3.Docker命令-容器相关命令 三、Docker容器的数据卷1.Docker容器数据卷-数…...

【新版】系统架构设计师 - 案例分析 - 总览
个人总结,仅供参考,欢迎加好友一起讨论 架构 - 案例分析 - 总览 新旧大纲对应 旧版新版系统规划软件架构设计设计模式系统设计系统建模分布式系统设计嵌入式系统设计系统的可靠性分析与设计系统的安全性和保密性设计系统计划信息系统架构的设计理论和实…...

【Git】02-Git常见应用
文章目录 1. 删除不需要分支2. 修改最新Commit的Message3. 修改之前Commit的Message4. 连续多个Commit整理为一个5. 不连续的Commit整理为一个6. 比较暂存区和HEAD中文件差异7. 比较工作区和暂存区中文件差异8. 将暂存区恢复为HEAD相同9. 工作区文件恢复和暂存区相同10. 取消暂…...

YOLO物体检测-系列教程2:YOLOV2整体解读
🎈🎈🎈YOLO 系列教程 总目录 YOLOV1整体解读 YOLOV2整体解读 YOLOV2提出论文:YOLO9000: Better, Faster, Stronger 1、YOLOV1 优点:快速,简单!问题1:每个Cell只预测一个类别&…...

u盘传输数据的时候拔出会怎么样?小心这些危害
U盘是我们日常生活和工作中常使用的一种便携式存储设备。然而,在使用U盘传输数据时,有时我们会不小心将它拔出,而这个看似微不足道的行为实际上可能会带来严重的后果。本文将向您介绍U盘在传输数据时突然拔出可能导致的各种危害,其…...

【踩坑纪实】URL 特殊字符 400 异常
URL 特殊字符 400 异常 笔者之前在写后端或者前端时,在处理表单时,经常有对特殊字符的检验处理,但自己也不清楚为什么要这么做,浅浅地以为可能是特殊字符不好看或者存取可能会造成异常?不过一直没遇到过问题ÿ…...

Contents:帮助公司为营销目的创建内容
【产品介绍】 名称 Contents上线时间 2017年5月 具体描述 Contents是一家提供基于人工智能的内容生成平台的企业,可以帮助用户在各种网站和工具中使用最先进的机器学习模型,实现视频编辑、图像生成、3D建模等内容创作。【团队介绍…...

1397: 图的遍历——广度优先搜索
题目描述 广度优先搜索遍历类似于树的按层次遍历的过程。其过程为:假设从图中的某顶点v出发,在访问了v之后依次访问v的各个未曾被访问过的邻接点,然后分别从这些邻接点出发依次访问它们的邻接点,并使“先被访问的顶点的邻接点”先…...

Java 华为真题-选修课
需求: 现有两门选修课,每门选修课都有一部分学生选修,每个学生都有选修课的成绩,需要你找出同时选修了两门选修课的学生,先按照班级进行划分,班级编号小的先输出,每个班级按照两门选修课成绩和的…...

Invalid access token: Invalid header string: ‘utf-8‘ codec can‘t decode byte
报错:在运行一个txt文档时报Invalid access token: Invalid header string: ‘utf-8’ codec can’t decode byte 原因:文档编码方式的原因,电脑默认的是UFT-8格式的编码 解决方法:用notepad改一下文档编码就好...

Java 中将多个 PDF 文件合并为一个 PDF
一.前言 我们将从以下两个方面向您展示如何将多个PDF文件合并为一个PDF: 1. 将文件中的多个 PDF 合并为单个 PDF 2. 将流中的多个 PDF 合并为单个 PDF 1. 了解 Spire.PDF 库 要在 Java 中合并 PDF 文件,我们将使用Spire.PDF 库。Spire.PDF for Java 是…...

python经典百题之水仙花数
题目:打印出所有的“水仙花数”,所谓“水仙花数”是指一个三位数,其各位数字立方和等于该数 本身。例如:153是一个“水仙花数”,因为1531的三次方+5的三次方+3的三次方。 方法一:暴…...

jvm的调优工具
1. jps 查看进程信息 2. jstack 查看进程的线程 59560为进程id 产生了死锁就可以jstack查看了 详细用途可以看用途 3. jmap 如何使用dump文件看下 查看 4.jstat 空间占用和次数 5. jconsole可视化工具 各种使用情况,以及死锁检测 6. visualvm可视化工具…...

C语言--字符串旋转笔试题
C语言–字符串旋转笔试题 文章目录 C语言--字符串旋转笔试题一、字符串左旋1.1 思路11.2 思路1代码1.3 思路21.4 思路2代码 二、字符串旋转结果判断2.1 思路12.2 思路2 一、字符串左旋 实现一个函数,可以左旋字符串中的k个字符。 例如: ABCD左旋一个字…...

IntelliJ IDEA使用_常规设置
文章目录 版本说明主题设置取消检查更新依赖自动导入禁止import xxx.*、允许import内部类显示行号、方法分割线、空格代码提示(匹配所有字母)自定义注释颜色添加头部注释自定义字体设置字符编码关联本地GitJDK编译版本Maven配置Tomcat配置代码注释设置头…...

ResponseBodyAdvice 获取参数
废话不多说,简练,一针见血,解决问题,才是最好的。 首先肯定是重写了这个beforeBodyWrite方法 重点来了,获取请求参数: request.getBody()返回一个inputStream流,这里你可以 使用很多方法把这个…...

人力资源服务升级正当时,法大大助力佩信集团加速数字化
人力资源服务业是现代服务业的一个重要门类,在促进就业创业、提供人才服务方面发挥重要作用。同时面对产业转型升级、平台经济快速发展、企业用工成本提高等新形势,发展人力资源服务业对于促进社会化就业、更好发挥我国人力资源优势、服务经济社会发展具…...

UG\NX二次开发 二维向量相加
文章作者:里海 来源网站:王牌飞行员_里海_里海NX二次开发3000例,里海BlockUI专栏,C\C++-CSDN博客 简介: UG\NX二次开发 二维向量相加 效果: 代码: #include "me.hpp"void doIt() {const double vec1[2] = { 1.0,2.0 };const double vec2[2] = { 2.0,2.…...

RabbitMQ深入 —— 持久化和发布确认
前言 前面的文章荔枝梳理了如何去配置RabbitMQ环境并且也介绍了两种比较简单的运行模式,在这篇文章中荔枝将会继续梳理有关RabbitMQ的持久化机制以及发布确认模式的相关知识,希望能够帮助到大家~~~ 文章目录 前言 一、持久化 1.1 队列持久化 1.2 消息…...