SSM常用注解总结
@Param
Dao接口中方法定义,多个参数
User findByCondition(@Param("id") Integer id,@Param("username") String username);
lombok注解
@Data //get,set,toString,Hashcode,equals等方法
@NoArgsConstructor //空参构造
@AllArgsConstructor //带参构造
public class Account {
private Integer id;
private String name;
private Double money;
}
@Component@Controller,@Service ,@Repository
上述4个注解都是加到类上的。
他们都可以起到类似bean标签的作用。可以把加了该注解类的对象放入Spring容器中。
实际再使用时选择任意一个都可以。但是后3个注解是语义化注解。
如果是Service类要求使用@Service。
如果是Dao类要求使用@Repository
如果是Controllerl类要求使用@Controller
如果是其他类可以使用@Component
@Repository("userDao")
public class UserDaoImpl implements UserDao {
public void show() {
System.out.println("查询数据库,展示查询到的数据");
}
}
@Data
@NoArgsConstructor
@AllArgsConstructor
@Component("phone")
public class Phone {
private double price;
private String name;
private String password;
private String path;
}
@Service("userService")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserServiceImpl implements UserService {
private UserDao userDao;
private int num;
private String str;
public void show() {
userDao.show();
}
}
@Value
简单类型注入,主要用于String,Integer等可以直接赋值的属性注入。不依赖setter方法,支持SpEL表达式。
@Service("userService")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserServiceImpl implements UserService {
private UserDao userDao;
@Value("199")
private int num;
@Value("若风")
private String str;
@Value("#{19+3}")
private Integer age;
public void show() {
userDao.show();
}
}
@AutoWired
引用数据类型注入,一般用于下面两种,注入Dao接口和service接口
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
@Controller
public class UserController {
@Autowired
private UserService userService;
required属性代表这个属性是否是必须的,默认值为true。
如果是true的话Spring容器中如果找不到相同类型的对象完成属性注入就会出现异常。
@Autowired(required = false)
private UserService userService;
如果改为false,就是找不到也无所谓,不报错,但是不会赋值,就是null
@Qualifier
如果相同类型的bean在容器中有多个时,单独使用@AutoWired就不能满足要求,这时候可以再加上@Qualifier来指定bean的名字从容器中获取bean注入。
@Autowired
@Qualifier("userDao2")
private UserDao userDao;
注意:该直接不能单独使用。单独使用没有作用
@Configuration
标注在类上,表示当前类是一个配置类。我们可以用注解类来完全替换掉xml配置文件。
@Configuration
public class ApplicationConfig {
}
@ComponentScan
可以用来代替context:component-scan标签来配置组件扫描。basePackages属性来指定要扫描的包。
注意要加在配置类上。
@Configuration
@ComponentScan(basePackages = "com.sangeng")//指定要扫描的包
public class ApplicationConfig {
}
@Bean
和@component@Service@Repository一样 都是代替标签放到spring容器中的,但是@Bean主要是用来导入第三方类的 比如DruidDataSource类
使用:定义一个方法,在方法中创建对应的对象并且作为返回值返回。然后在方法上加上@Bean注解,注解的value属性来设置bean的名称。
@Configuration
@ComponentScan(basePackages = "com.sangeng")
public class ApplicationConfig {
@Bean("dataSource")
public DruidDataSource getDataSource(){
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setDriverClassName("com.mysql.jdbc.Driver");
druidDataSource.setUsername("root");
druidDataSource.setUrl("jdbc:mysql://localhost:3306/mybatis_db");
druidDataSource.setPassword("root");
return druidDataSource;
}
}
注意事项:如果同一种类型的对象在容器中只有一个,我们可以不设置bean的名称
@Configuration
@ComponentScan(basePackages = "com.sangeng")
public class ApplicationConfig {
@Bean
public DruidDataSource getDataSource(){
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setDriverClassName("com.mysql.jdbc.Driver");
druidDataSource.setUsername("root");
druidDataSource.setUrl("jdbc:mysql://localhost:3306/mybatis_db");
druidDataSource.setPassword("root");
return druidDataSource;
}
}
@PropertySource
可以用来代替context:property-placeholder,让Spring读取指定的properties文件。然后可以使用@Value来获取读取到的值。
使用:在配置类上加@PropertySource注解,注解的value属性来设置properties文件的路径。
然后在配置类中定义成员变量。在成员变量上使用@Value注解来获取读到的值并给对应的成员变量赋值。
@Configuration
@ComponentScan(basePackages = "com.sangeng")
@PropertySource("jdbc.properties")
public class ApplicationConfig {
@Value("${jdbc.driver}")
private String driverClassName;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
}
注意事项:使用@Value获取读到的properties文件中的值时使用的是${key},而不是#{key}。
@Aspect切面类
@Pointcut切点
@Component
@Aspect
public class MyAspect {
// 用Pointcut注解中的属性来指定对哪些方法进行增强
@Pointcut("execution(* com.sangeng.service.*.*(..))")
public void pt(){}
/*
用@Before注解来指定该方法中是增强的代码,并且是在被增强方法执行前执行的
@Before的属性写上加了@Pointcut注解的方法: 方法名()
*/
@Before("pt()")
public void methodbefore(){
System.out.println("方法被调用了");
}
}
@annotation
我们也可以在要增强的方法上加上注解。然后使用@annotation来表示对加了什么注解的方法进行增强。
写法:@annotation(注解的全类名)
例如:
定义注解如下
@Target({ElementType.METHOD})//该注解可以加在方法上
@Retention(RetentionPolicy.RUNTIME)
public @interface InvokeLog {
}
给需要增强的方法增加自定义注解
@Service
public class PhoneService {
@InvokeLog
public void deleteAll(){
System.out.println("PhoneService中deleteAll的核心代码");
}
}
切面类中使用@annotation来确定要增强的方法
@Component
@Aspect
public class MyAspect {
// 用Pointcut注解中的属性来指定对哪些方法进行增强
@Pointcut("@annotation(com.sangeng.aspect.InvokeLog)")
public void pt(){}
@Before("pt()")
public void methodbefore(){
System.out.println("方法被调用了");
}
}
通知分类
@Before:前置通知,在目标方法执行前执行
@AfterReturning: 返回后通知,在目标方法执行后执行,如果出现异常不会执行
@After:后置通知,在目标方法之后执行,无论是否出现异常都会执行
@AfterThrowing:异常通知,在目标方法抛出异常后执行
@Around:环绕通知,围绕着目标方法执行
伪代码方便理解
public Object test() {
before();//@Before 前置通知
try {
Object ret = 目标方法();//目标方法调用
afterReturing();//@AfterReturning 返回后通知
} catch (Throwable throwable) {
throwable.printStackTrace();
afterThrowing();//@AfterThrowing 异常通知通知
}finally {
after();//@After 后置通知
}
return ret;
}
环绕通知
@Around("pt()")
public void around(ProceedingJoinPoint pjp){
System.out.println("目标方法前");
try {
pjp.proceed();//目标方法执行
System.out.println("目标方法后");
} catch (Throwable throwable) {
throwable.printStackTrace();
System.out.println("目标方法出现异常");
}finally {
System.out.println("finally中进行增强");
}
}
@Order
多切面顺序问题
在实际项目中我们可能会存在配置了多个切面的情况。这种情况下我们很可能需要控制切面的顺序。
我们在默认情况下Spring有它自己的排序规则。(按照类名排序)
如果是注解方式配置的AOP可以在切面类上加**@Order注解来控制顺序。@Order中的属性越小优先级越高。**
@Component
@Aspect
@Order(2)
public class APrintLogAspect {
//省略无关代码
}
@Component
@Aspect
@Order(1)
public class CryptAspect {
//省略无关代码
}
先使用CryptAspect里面的增强,再使用APrintLogAspect里的增强
@RunWith
@ContextConfiguration
@test
测试类中
@RunWith(SpringJUnit4ClassRunner.class)//让测试运行与Spring测试环境
@ContextConfiguration(locations = "classpath:applicationContext.xml")设置Spring配置文件或者配置类
public class SpringTest {
@Autowired
private AccountService accountService;
@Autowired
private TestServiceImpl testServiceImpl;
@Test
public void testTransfer() {
accountService.transfer(2,1,20.0);
}
@Test
public void testPropagation(){
testServiceImpl.test();
}
}
@Transactional
对service类中方法进行事务控制,底层是AOP增强
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
@Transactional
@Override
public void test() {
userDao.insertUser(new User(null,"test1",11,"aa"));
System.out.println(1/0);//除0异常
userDao.insertUser(new User(null,"test2",12,"bb"));
}
传播行为参数
属性值行为REQUIRED(必须要有)外层方法有事务,内层方法就加入。外层没有,内层就新建REQUIRES_NEW(必须要有新事务)外层方法有事务,内层方法新建。外层没有,内层也新建SUPPORTS(支持有)外层方法有事务,内层方法就加入。外层没有,内层就也没有NOT_SUPPORTED(支持没有)外层方法有事务,内层方法没有。外层没有,内层也没有MANDATORY(强制要求外层有)外层方法有事务,内层方法加入。外层没有。内层就报错NEVER(绝不允许有)外层方法有事务,内层方法就报错。外层没有。内层就也没有
@Transactional(propagation = Propagation.REQUIRES_NEW)
@Override
public void test() {
userDao.insertUser(new User(null,"test1",11,"aa"));
System.out.println(1/0);//除0异常
userDao.insertUser(new User(null,"test2",12,"bb"));
}
隔离级别参数
Isolation.DEFAULT 使用数据库默认隔离级别
Isolation.READ_UNCOMMITTED 读未提交
Isolation.READ_COMMITTED 读已提交
Isolation.REPEATABLE_READ 可重复读
Isolation.SERIALIZABLE 序列化
@Transactional(propagation = Propagation.REQUIRES_NEW,isolation = Isolation.READ_COMMITTED)
@Override
public void test() {
userDao.insertUser(new User(null,"test1",11,"aa"));
System.out.println(1/0);//除0异常
userDao.insertUser(new User(null,"test2",12,"bb"));
}
只读readOnly
如果事务中的操作都是读操作,没涉及到对数据的写操作可以设置readOnly为true。这样可以提高效率。
@Transactional(readOnly = true)
public void log() {
System.out.println("打印日志");
int i = 1/0;
}
@RequestMapping
设置请求规则
该注解可以加到方法上或者是类上,我们期望让请求的资源路径为**/test/testPath的请求能够被testPath**方法处理则可以写如下代码
@Controller
@RequestMapping("/test")
public class TestController {
@RequestMapping("/testPath")
public String testPath(){
return "/success.jsp";
}
}
指定请求方式
@PostMapping
@GetMapping
@PutMapping
@DeleteMapping
@PathVariable
从请求路径获取RestFul风格的请求参数,不加默认获取QueryString格式参数(需要字段名一致)
获取多个参数,写多个@PathVariable
@GetMapping("/user/{id}")
public ResponseResult findById(@PathVariable("id") Integer id) {//从请求路径获取id
User user = userService.findById(id);
if(user == null) {
return new ResponseResult(500,"没有该用户");
}
return new ResponseResult(200,"操作成功",user);
}
@RequestParam
从请求路径获取QueryString格式参数,如果方法参数名和请求参数名不一致,我们就需要加上**@RequestParam**注解
@RequestMapping("/testRquestParam")
public String testRquestParam(@RequestParam("id") Integer uid,@RequestParam("name") String name, @RequestParam("likes")String[] likes){
System.out.println("testRquestParam");
System.out.println(uid);
System.out.println(name);
System.out.println(Arrays.toString(likes));
return "/success.jsp";
}
@RequestBody
从请求体中获取json格式的数据
@PostMapping("/user")
public ResponseResult insertUser(@RequestBody User user) {//从请求体中获取user(json格式)
userService.insertUser(user);
return new ResponseResult(200,"操作成功");
}
相关注解其他参数属性
required
代表是否必须,默认值为true也就是必须要有对应的参数。如果没有就会报错。
如果对应的参数可传可不传则可以把去设置为fasle
例如:
@RequestMapping("/testRquestParam")
public String testRquestParam(@RequestParam(value = "id",required = false) Integer uid,@RequestParam("name") String name, @RequestParam("likes")String[] likes){
System.out.println("testRquestParam");
System.out.println(uid);
System.out.println(name);
System.out.println(Arrays.toString(likes));
return "/success.jsp";
}
defaultValue
@RequestParam特有属性
如果对应的参数没有,我们可以用defaultValue属性设置默认值。
例如:
@RequestMapping("/testRquestParam")
public String testRquestParam(@RequestParam(value = "id",required = false,defaultValue = "777") Integer uid,@RequestParam("name") String name, @RequestParam("likes")String[] likes){
System.out.println("testRquestParam");
System.out.println(uid);
System.out.println(name);
System.out.println(Arrays.toString(likes));
return "/success.jsp";
}
@ResponseBody
可以加到方法或者类上
表示方法的返回值都会被自动转化为json格式放到响应体中返回给客户端
@Controller
@RequestMapping("/response")
public class ResponseController {
@GetMapping("/user/{id}")
@ResponseBody //这方法的返回值放入响应体中
public User testResponse(@PathVariable Integer id){
User user = new User(id,null,null,null);
return user;
}
}
一般和@Controller连用,变成**@RestController**
@RestController//这类中所有方法的返回值都会放到响应体中
public class UserController {
@Autowired
private UserService userService;
@DateTimeFormat
指定字符串的格式
请求路径中传递yyyy-MM-dd这种格式的字符串会被解析为日期类
@RequestMapping("/testDateConverter")
public String testDateConverter(@DateTimeFormat(pattern = "yyyy-MM-dd") Date birthday){
System.out.println("testDateConverter");
System.out.println(birthday);
return "/success.jsp";
}
@RequestHeader
在方法中定义一个参数,参数前加上**@RequestHeader**注解,知道要获取的请求头名即可获取对应请求头的值。
想要获取 device-type 这个请求头则可以按照如下方式定义方法。
@Controller
public class RequestResponseController {
@RequestMapping("/getHeader")
public String getHeader(@RequestHeader(value = "device-type") String deviceType){
System.out.println(deviceType);
return "test";
}
}
@CookieValue
在方法中定义一个参数,参数前加上**@CookieValue** 注解,知道要获取的cookie名即可获取对应cookie的值。
想要获取 JSESSIONID 的cookie值。则可以按照如下方式定义方法。
@Controller
public class RequestResponseController {
@RequestMapping("/getCookie")
public String getCookie(@CookieValue("JSESSIONID") String sessionId){
System.out.println(sessionId);
return "test";
}
}
@ControllerAdvice
@ExceptionHandler
统一异常处理,我们在实际项目中Dao层和Service层的异常都会被抛到Controller层
创建类加上**@ControllerAdvice注解进行标识,自定义异常处理方法使用@ExceptionHandler**标识可以处理的异常。
@Component
@ControllerAdvice
public class MyControllerAdvice {
@ExceptionHandler({NullPointerException.class,ArithmeticException.class})
public ModelAndView handlerException(Exception ex){
//如果出现了相关的异常,就会调用该方法
String msg = ex.getMessage();
ModelAndView modelAndView = new ModelAndView();
//把异常信息存入域中
modelAndView.addObject("msg",msg);
//跳转到error.jsp
modelAndView.setViewName("/WEB-INF/page/error.jsp");
return modelAndView;
}
}
@JsonInclude
一般在自定义返回到响应体的Result类中使用
//某个属性的值不为null才会转换成json
@JsonInclude(JsonInclude.Include.NON_NULL)
//任何接口都会返回一个ResponseResult对象,统一格式
public class ResponseResult
}