SSM中的常用注解

1.Mybatis中的注解

@param

使用param注解标识mapper接口中的方法参数

此时,会将这些参数放在map集合中,以@Param注解的value属性值为键,以参数为值;以param1,param2…为键,以参数为值;只需要通过${}和#{}访问map集合的键就可以获取相对应的值

注意${}需要手动加单引号

public interface TestMapper{
    void TestByParam(@Param("username") String username,@Param("password") String password);
}
<!--User TestByParam(@Param("username") String username, @Param("password") String password)-->
    <select id="TestByParam" resultType="User">
        select * from t_user where username = #{username} and password = #{password}
    </select>fr

2.Spring中的注解

(1)基于注解管理bean

以上四个注解功能一致,@Controller、@Service、@Repository都是由@Component扩展出来的
但是对于开发人员来说,可以通过不同的注解标记不同的组件

@Component

标记一个普通组件

@Component
public class User{}
@Controller (Servlet)

标记一个控制层组件

@Controller
public class UserController
@Service (Service)

标记一个业务层组件

@Service
public class UserServiceImpl{}
@Repository (Dao)

标记一个持久层组件

@Repository
public class UserDaoImpl{}

注意:通过标记和扫描被IOC容器管理的bean都有默认的id,类名的小驼峰,即类名的首字母小写的结果
若需要自定义bean的id,此时可以通过@Controller、@Service、@Repository、@Component的value属性设置

@Autowired

基于注解的自动装配

@Autowired注解可以标记在成员变量、set方法、有参构造上,建议标记在成员变量上,此时不需要设置set方法和有参构造

@Autowired
private UserService userService;

原理:

(1) @Autowired注解默认使用byType的方式完成自动装配,即根据类型在IOC容器中匹配某个bean为当前的属性赋值

(2) 若通过byType的方式,在IOC容器中没有匹配到任何一个bean,此时报错:NoSuchBeanDefinitionException

(3) 导致NoSuchBeanDefinitionException是因为在@Autowired中,有属性required,默认值为true,表示当前的属性必须完成自动装配,若装配失败则报错NoSuchBeanDefinitionException
此时可以将required设置为false,则表示能装配则装配,若无法装配,则使用默认值,一般不用

(4) 若在IOC容器中匹配到了多个bean,此时会自动切换为byName,即将需要赋值的成员变量的名字作为bean的id在IOC容器中匹配

(5) 若通过byName没有匹配到任何一个bean,即IOC容器中有多个类型匹配的bean,但是任何一个bean的id和要赋值的成员变量的名字都不一致
此时报错:NoUniqueBeanDefinitionException,可以在成员变量上添加@Qualifier注解,通过通过该注解的value属性设置某个bean的id,将bean为当前属性赋值

@Qualifier
@Autowired
@Qualifier("userServiceImpl")
private UserService userService;

即IOC容器中有多个类型匹配的bean,但是任何一个bean的id和要赋值的成员变量的名字都不一致,通过该注解的value属性设置某个bean的id,将bean为当前属性赋值

(2)AOP中的注解

@Aspect

将组件标记为一个切面

@Component
@Aspect
public class LoggerAspect {}
@Order

切面的优先级

通过value属性设置一个正整数,值越小优先级越高

@Component
@Aspect
@Order(2)
public class LoggerAspect{

    @Before("pointCut()")
    public void beforeAdviceMethod(JoinPoint joinPoint){
        //获取连接点所对应方法的方法名
		String methodName = joinPoint.getsignature().getName();
		//获取连接点所对应方法的参数
		Object[] args = joinPoint.getArgs();
        System.out.println("beforeAdvice-->前置通知,方法:" + methodName + ",参数:" + 			Arrays.toString(args));
    }
}

@Component
@Aspect
@Order(1)
public class ValidateAspect{
    //验证计算机,要求在日志之前
    @Before"com.swz.LoggerAspect.pointCut()"
    public void beforeAdviceMethod(JoinPoint joinPoint){
        System.Out.Println("ValidateAspect-->前置通知")
    }
    
}
@Pointcut

设置一个公共的切入点表达式

@Component
@Aspect
public class LoggerAspect{
//可以使用在其他类,不过要写全类名	
@Pointcut("execution( * com.swz.CalculatorImpl.*(..) )")
public void pointCut(){}

//通过切入点表达式定位切入点
    @Before("pointCut()")
    public void beforeAdviceMethod(JoinPoint joinPoint){}

}
public class ValidateAspect{
    
    @Before"com.swz.LoggerAspect.pointCut()"
    public void beforeAdviceMethod(JoinPoint joinPoint){}
    
}

切入点表达式的语法,即(@Before,@After中括号内写的内容)

1.execution( 访问修饰符 返回值类型 包类方法(参数类型) )

2.execution( * com.swz.CalculatorImpl.*(…) )

  • 用*号代替“权限修饰符”和“返回值”部分表示“权限修饰符”和“返回值”不限
  • 在包名的部分,一个“*”号只能代表包的层次结构中的一层,表示这一层是任意的。
    • 例如:*.Hello匹配com.Hello,不匹配com.atguigu.Hello
  • 在包名的部分,使用“*…”表示包名任意、包的层次深度任意
  • 在类名的部分,类名部分整体用*号代替,表示类名任意
  • 在类名的部分,可以使用*号代替类名的一部分
    • 例如:*Service匹配所有名称以Service结尾的类或接口
  • 在方法名部分,可以使用*号表示方法名任意
  • 在方法名部分,可以使用*号代替方法名的一部分
    • 例如:*Operation匹配所有方法名以Operation结尾的方法
  • 在方法参数列表部分,使用(…)表示参数列表任意
  • 在方法参数列表部分,使用(int,…)表示参数列表以一个int类型的参数开头
  • 在方法参数列表部分,基本数据类型和对应的包装类型是不一样的
    • 切入点表达式中使用 int 和实际方法中 Integer 是不匹配的
  • 在方法返回值部分,如果想要明确指定一个返回值类型,那么必须同时写明权限修饰符

通知

在切面中将横切关注点封装一个方法,使用指定的注解将其标记为不同的通知方法

前置通知: 使用@Before标记,在目标对象核心功能之前执行

返回通知: 使用@AfterReturning标记,在目标对象方法的返回值之后执行

异常通知: 使用@AfterThrowing标记,在目标对象方法的catch语句块中执行

后置通知: 使用@After标记,在目标对象方法的finally语句块中执行

环绕通知: 使用Around标记,在目标对象的四个位置执行

@Before

前置通知

@Component
@Aspect
public class LoggerAspect{
    //通过切入点表达式定位切入点
    @Before("execution(public int com.swz.aop.annotation.CalculatorImpl.*(int, int))")
    public void beforeAdviceMethod(JoinPoint joinPoint){
        //获取连接点所对应方法的方法名
		String methodName = joinPoint.getsignature().getName();
		//获取连接点所对应方法的参数
		Object[] args = joinPoint.getArgs();
        System.out.println("beforeAdvice-->前置通知,方法:" + methodName + ",参数:" + 			Arrays.toString(args));
    }
}
@AfterReturning

返回通知

@Component
@Aspect
public class LoggerAspect{
    //通过切入点表达式定位切入点
    @AfterReturning("execution(public int com.swz.aop.annotation.CalculatorImpl.*(int, int))" returning = "result")
    public void AfterReturningAdviceMethod(JoinPoint joinPoint , Object result){
        //获取连接点所对应方法的方法名
		String methodName = joinPoint.getsignature().getName();
        System.out.println("AfterReturningAdvice-->返回通知,方法:" + methodName + ",结果:"  		+result);
    }
}
@AfterThrowing

异常通知

@Component
@Aspect
public class LoggerAspect{
    //通过切入点表达式定位切入点
    @AfterThrowing("execution(public int com.swz.aop.annotation.CalculatorImpl.*(int, int))" throwing = "result")
    public void AfterThrowingAdviceMethod(JoinPoint joinPoint , Throwable ex){
        //获取连接点所对应方法的方法名
		String methodName = joinPoint.getsignature().getName();
        System.out.println("AfterThrowingAdvice-->返回通知,方法:" + methodName + ",异常信  		  息:"+ex);
    }
}
@After

后置通知

@Component
@Aspect
public class LoggerAspect{
    //通过切入点表达式定位切入点
    @After("execution(public int com.swz.aop.annotation.CalculatorImpl.*(int, int))")
    public void AfterAdviceMethod(JoinPoint joinPoint){
        //获取连接点所对应方法的方法名
		String methodName = joinPoint.getsignature().getName();
        System.out.println("AfterAdvice-->后置通知,方法:" + methodName + "执行完毕");
    }
}

JoinPoint

//JoinPoint获取获取链接点的相关信息
//获取连接点所对应方法的方法名
String methodName = joinPoint.getsignature().getName();
//获取连接点所对应方法的参数
Object[] args = joinPoint.getArgs();
@Around

环绕通知

@Component
@Aspect
public class LoggerAspect{
    @Around("execution(public int com.swz.aop.annotation.CalculatorImpl.*(int, int))")
    public void aroundAdviceMethod(ProceedingJoinPoint joinPoint){
        Object result = null;
        try{
            System.out.println("beforeAdvice-->前置通知,方法:" + methodName + ",参数:" + 			 Arrays.toString(args));
            joinPoint.procces();
            System.out.println("AfterReturningAdvice-->返回通知,方法:" + methodName + ",结    			果:"+result);
        }catch{
            
        }finally{
            
        }
    }
}

(3) Spring整合Junit4,junit5

测试方法在Spring的环境下运行,可以在当前测试类中自动装配IOC容器所管理的对象

@RunWith

设置Junit方法是在什么Junit环境下执行

@ContextConfiguration

设置Spring的配置文件

//指定测试方法在Spring的IOC环境中执行
@RunWith(SpringJUnit4ClassRunner.class)//junit4
//设置IOC容器所对应的配置文件
@ContextConfiguration("classpath:spring-jdbc.xml")
public void Test(){
    
    @Autowired
    private JdbcTemplate jdbcTemplate;
    	
}

@Extendwith
//指定测试方法在Spring的IOC环境中执行
@Extendwith(SpringExtension .class)//junit5
//设置IOC容器所对应的配置文件
@ContextConfiguration("classpath:spring-jdbc.xml")
public void Test(){
    
    @Autowired
    private JdbcTemplate jdbcTemplate;
    	
}
@SpringJUnitConfig

复合注解

@SpringJUnitConfig(locations = {"classpath:spring-context.xml"})
public void Test(){
    
    @Autowired
    private JdbcTemplate jdbcTemplate;
    	
}

(4)基于注解的声明式事务

@Transactional

用法

1、基于注解的声明式事务的实现步骤
a>在配置文件中配置事务管理器
b>开启事务的注解驱动
c>在需要被事务管理的方法上或类上添加注解@Transactional

2、@Transactional标记的位置
标记在方法上,则该方法会被事务管理
标记在类上,则类中所有的方法会被事务管理

元注解

@Target({ElementType.TYPE, ElementType.METHOD})//当前注解能标记的位置,表示可以用在类和方法上
@Retention(RetentionPolicy.RUNTIME)//当前注解能保存到哪一个阶段,RUNTIME表示到字节码
@Inherited//表示注解可以被继承
@Documented
public @interface Transactional {}

xml配置

	<!--设置数据源事务管理器-->
    <bean id="transactionManager" 			 class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!--配置数据源-->
        <property name="dataSource" ref="dataSource"></property>
    </bean>

	<!--
	开启事务的注解驱动
	将使用@Transactional注解标记的方法或类中所有的方法被事务管理器管理
	-->
    <tx:annotation-driven transaction-manager="transactionManager"/>

注解|事务属性

1.只读

可以通过@Transactional注解的readOnly属性设置事务的只读,默认值为false
若当前事务中全部都是查询操作,就可以设置事务的只读属性,此时会通知数据库,从数据库层面优化当前事务中的操作
注意:若当前事务设置了readOnly=“true”,但是事务中有任何一个增删改操作,则直接报错:Connection is read-only. Queries leading to data modification are not allowed

2.超时
可以通过@Transactional注解的timeout属性设置事务的超时,默认值为-1,即一直等
当设置了事务的超时属性,若事务执行时超过指定时间未执行完毕,则会强制回滚并抛出异常:TransactionTimedOutException

3.回滚策略
可以通过@Transactional注解的rollbackFor、rollbackForClassName、noRollbackFor、noRollbackForClassName属性设置事务的回滚策略
可以通过事务的回滚策略设置导致或不导致事务回滚的异常
声明式事务默认情况下任何的运行时异常都会导致事务的回滚
4.事务属性之隔离级别

可以通过@Transactional注解的isolation属性设置事务的隔离级别
isolation=Isolation.DEFAULT:使用数据库默认的隔离级别
isolation=Isolation.READ_UNCOMMITTED:读未提交
isolation=Isolation.READ_COMMITTED:读已提交
isolation=Isolation.REPEATABLE_READ:可重复读
isolation=Isolation.SERIALIZABLE:序列化

5.事务属性之传播行为
可以通过@Transactional注解的propagation属性设置事务的传播行为
当事务方法A调用事务方法B,对于事务方法B使用A的事务或者B本身的事务,即事务方法被调用时,使用事务的方式就是事务的传播行为
propagation=Propagation.REQUIRED:默认值,使用调用者的事务
propagation=Propagation.REQUIRES_NEW:使用被调用者的事务

@Transactional(
    readOnly="true"//只读
    timeout= 3//超时
    rollbackFor =		//导致事务回滚的异常,内容是Class类型
    rollbackForClassName		//导致事务回滚的异常,内容是字符串类型
    noRollbackFor				//不导致事务回滚的异常,内容是Class类型
    noRollbackForClassName		//不导致事务回滚的异常,内容是字符串类型
    isolation = Isolation.DEFAULT
    propagation=Propagation.REQUIRED
)

2.SpringMVC中的注解

@RequestMapping

1.功能

把浏览器发送的请求和@RequestMapping注解所设置的请求信息进行匹配,若匹配成功,则@RequestMapping所标记的方法就是处理当前请求的方法

2.标记的位置

标记在类上,为标记在方法上的@RequestMapping设置一个前缀的路径

标记在方法上,为需要处理的请求设置一个具体的路径

@Controller
@RequestMapping("/test")
public class TestRequestMapping{
    
    @RequestMapping("/success")//此时的真实路径为/test/success
    public String success(){
        return "success";
    }
}

3.属性

1>value属性

@RequestMapping注解的value属性是通过请求的请求路径匹配请求映射

value属性是字符串数组类型,因此可以设置多个请求的请求路径,由注解所标记的方法可以处理value中所设置的每一个路径所对应的请求

@Controller
@RequestMapping("/test")
public class TestRequestMapping{
    
    @RequestMapping({"/success","/abc"})//此时的真实路径为/test/success|/test/abc
    public String success(){
        return "success";
    }
}
<a th:href="@{/test/success}">测试@RequestMapping注解的value属性</a>
<a th:href="@{/test/abc}">测试@RequestMapping注解的value属性</a>

2>method属性

@RequestMapping注解的method属性是通过请求的请求路径匹配请求映射

method属性是RequestMethod数组类型,因此可以设置多种请求方式,当前注解@RequestMapping注解所标记的方法处理的请求的请求方式只要满足其中一种即可

若@RequestMapping注解的Value属性可以匹配,但是method属性无法匹配此时报错405: Request method ‘GET’ not supported

@Controller
@RequestMapping("/test")
public class TestRequestMapping{
    
    @RequestMapping(
        value = {"/success","/abc"}//此时的真实路径为/test/success|/test/abc
        method = {RequestMethod.GET,RequestMethod.POST}
    )
    public String success(){
        return "success";
    }
}

3>params属性

@RequestMapping注解的params属性是通过请求的请求参数匹配请求映射

若@RequestMapping注解的value属性可以匹配,但是params属性无法匹配,页面报错400

params属性中可以使用四种表达式

param :匹配的请求必须携带请求参数param

!param :匹配的请求一定不能携带请求参数param

param=value:匹配的请求必须携带请求参数param,且值必须为value

param!=value:匹配的请求可以不携带请求参数param,若携带则一定不能为value

@Controller
@RequestMapping("/test")
public class TestRequestMapping{
    
    @RequestMapping(
        value = {"/success","/abc"}//此时的真实路径为/test/success|/test/abc
        params = {"username","password!=123456"}//必须有用户名且密码不能为123456
    )
    public String success(){
        return "success";
    }
}

4>headers属性

headers方法同params,因为头信息就是键值对

若@RequestMapping注解的value属性可以匹配,但是headers属性无法匹配,页面报错404

@Controller
@RequestMapping("/test")
public class TestRequestMapping{
    
    @RequestMapping(
        value = {"/success","/abc"}//此时的真实路径为/test/success|/test/abc
        headers = "Lock Host"
    )
    public String success(){
        return "success";
    }
}

4.SpringMVC支持ant风格的路径

可以在@RequestMapping注解的value属性中,设置路径时使用一些特殊的符号表示特殊的含义

?:任意的单个字符,注意不能匹配?和/

*:任意个数的任意字符,注意不能匹配?和/

星星:任意层数的任意目录,注意不能匹配?,使用**时,前后和中间都不可以有其他内容

@PathVariable

SpringMVC路径中的占位符常用于RESTful风格中,当请求路径中将某些数据通过路径的方式传输到服务器中,就可以在相应的@RequestMapping注解的value属性中通过占位符{xxx}表示传输的数据,在通过**@PathVariable**注解,将占位符所表示的数据赋值给控制器方法的形参

<a th:href="@{/testRest/1/admin}">测试路径中的占位符-->/testRest</a><br>
@RequestMapping("testRest/1/{username}")
public String testRest(@PathVariable("username") String username){
    System.Out.println("username = " + username);
    return "success";
}

当占位符内的形参与方法参数的形参一致时可以省略@PathVariable的value值

@RequestMapping("testRest/1/{username}")
public String testRest(@PathVariable String username){
    System.Out.println("username = " + username);
    return "success";
}

(1)获取请求参数

@RequestParam

@RequestParam是将请求参数和控制器方法的形参创建映射关系

@RequestParam注解一共有三个属性:

value:指定为形参赋值的请求参数的参数名

required:设置是否必须传输此请求参数,默认值为true

若设置为true时,则当前请求必须传输value所指定的请求参数,若没有传输该请求参数,且没有设置defaultValue属性,则页面报错400:Required String parameter ‘xxx’ is not present;若设置为false,则当前请求不是必须传输value所指定的请求参数,若没有传输,则注解所标识的形参的值为null

defaultValue:不管required属性值为true或false,当value所指定的请求参数没有传输或传输的值为""时,则使用默认值为形参赋值

<a th:href="@{/param/RequestParam(username='admin')}">
    使用RequestParam获取请求参数
</a>
@RequestMapping("/RequestParam")
    public String testRequestParam(
        @RequestParam(
            value = "username",//参数名username
            required = true,//表示必须传参数,与defaultValue一起用毫无意义
            defaultValue = "aaa"//参数默认值为aaa
        ) String username){
        System.out.println("username = " + username + " password = " + password);
        return "success";
    }
@RequestHeader

@RequestHeader是将请求头信息和控制器方法的形参创建映射关系

@RequestHeader注解一共有三个属性:value、required、defaultValue,用法同@RequestParam

<a th:href="@{/param/RequestHeader}">使用RequestHeader获取请求头信息</a>
@RequestMapping("/RequestHeader")
    public String testRequestHeader(@RequestHeader("referer") String referer){
        System.out.println(referer);
        return "success";
    }
@CookieValue

@CookieValue是将cookie数据和控制器方法的形参创建映射关系

@CookieValue注解一共有三个属性:value、required、defaultValue,用法同@RequestParam

<a th:href="@{/param/CookieValue}">使用CookieValue获取Cookie信息</a>
@RequestMapping("/CookieValue")
    public String testCookieValue(@CookieValue("JSESSIONID") String JSESSIONID){
        System.out.println(JSESSIONID);
        return "success";
    }
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值