1. 程式人生 > >SSM框架中註解含義及應用場景小結

SSM框架中註解含義及應用場景小結

先說一下什麼是元件掃描:

指定一個包路徑,Spring會自動掃描該包及其子包所有元件類,當發現元件類定義前有特定的註解標記時,就將該元件納入到Spring容器。等價於原有XML配置中的<bean>定義功能。

元件掃描可以替代大量XML配置的<bean>定義。

使用元件掃描,首先需要在XML配置中指定掃描類路徑

<context:component-scan

      base-package = "org.example"/>

上面配置官網:www.fhadmin.org,容器例項化時會自動掃描org.example包及其子包下所有元件類。

指定掃描類路徑後,並不是該路徑下所有元件類都掃描到Spring容器的,只有在元件類定義前面有以下註解標記時,才會掃描到Spring容器。

@Component:通用註解;@Name:通用註解;@Repository:持久化層元件註解

@Service:業務層元件註解;@Controller:控制層元件註解

當一個元件在掃描過程中被檢測到時,會生成一個預設id值,預設id為小寫開頭的類名。也可以在註解標記中自定義id。下面兩個元件id名字分別是oracleUserDao和loginService

@Repository

public class OracleUserDao implements UserDao{

  //.....

}

@Service("loginService")

public class UserService{

  //....

}

官網:www.fhadmin.org通常受Spring管理的元件,預設的作用域是“singleton”。如果需要其他作用域可以使用@Scope註解,只要在註解中提供作用域的名稱即可。

@Scope("prototype")

@Repository

public class OracleUserDao implements EmpDao{

  //...

}

@PostConstruct和@PreDestroy註解標記分別用於指定初始化和銷燬回撥方法,使用示例:

public class ExampleBean{

  @PostConstruct

  public void init(){

    //初始化回撥方法

  }

  @PreDestroy

  public void destroy(){

  //銷燬回撥方法

  }

}

具有依賴關係的Bean物件,利用下面任何一種註解都可以實現關係注入:

@Resource

@Autowired/@Qualifier

@Inject/@Named

@Resource註解標記可以用在欄位定義或setter方法定義前面,預設首先按名稱匹配注入,然後型別匹配注入:

public class UserService{

  //@Resource

  private UserDao userDao;

  @Resource

  public void setUserDao(UserDao dao){

    this.userDao = dao;

  }

}

當遇到多個匹配Bean時注入會發生錯誤,官網:www.fhadmin.org 可以顯示指定名稱,例如@Resource(name = "empDao1")

@Autowired註解標記也可以用在欄位定義或setter方法定義前面,預設按型別匹配注入:

public class UserService{

  //@Autowired

  private UserDao userDao;

  @Autowired

  public void setUserDao(UserDao dao){

    this.userDao = dao;

  }

}

@Autowired當遇到多個匹配Bean時注入會發生錯誤,可以使用下面方法指定名稱:

public class UserService{

  //@Autowired

  //@Qualifiter("mysqlUserDao")

  private UserDao userDao;

  @Autowired

  public void setUserDao(@Qualifiter("mysqlUserDao")  userDao dao){

    this.userDao = dao;

  }

}

@Inject註解標記是Spring3.0開始增添的對JSR-330標準的支援,使用前需要新增JSR-330的jar包,使用方法與@Autowired相似,具體如:

public class UserService{

  //@Inject

  private UserDao  userDao;

  @Inject

  public void setUserDao(UserDao dao){

    this.userDao = dao;

  }

}

@Inject當遇到多個匹配Bean時注入會發生錯誤,可以使用@Named指定名稱限定,使用方法為:

public class UserService{

  private UserDao userDao;

  @Inject

  public void setUserDao(@Named("mysqlUserDao")  UserDao dao){

    this.userDao = dao;

  }

}

@Value註解可以注入Spring表示式值,使用方法:

首先在XML配置中指定要注入的properties檔案

<util:properties id = "jdbcProps"  location = "classpath:db.properties"/>

然後在setter方法前使用@Value註解

public class JDBCDataSource{

  @Value("#{jdbcProps.url}")

  private String url;

  @Value("#{jdbcProps.driver}")

  public void setUrl(String driver){

    try{Class.forName(driver)}catch(.....)...

  }

}

RequestMapping註解應用

@RequestMapping可以用在類定義和方法定義上

@RequestMapping標明這個類或者方法與哪一個客戶請求對應

@RequestMapping可以定義在Controller類前和處理方法前,主要用於指定Controller的方法處理哪些請求

@Controller

@RequestMapping("/demo01")

public class Controller{

  @RequestMapping("/hello")

  public String execute()throws Exception{

    return "hello";

  }

}

開啟@RequestMapping註解對映,官網:www.fhadmin.org需要在Spring的XML配置檔案中定義RequestMappingHandlerMapping(類定義前)和RequestMappingHandlerAdapter(方法定義前)兩個bean元件

示例:

<bean 

class ="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>

<bean

class = "org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>

從Spring3.2版本開始可以使用下面XML配置簡化RequestMappingHandlerMapping和RequestMappingHandlerAdapter定義:

<mvc:annotation-driven/>

Controller註解應用

推薦使用@Controller註解宣告Controller元件,這樣可以使得Controller定義更加靈活,可以不用實現Controller介面,請求處理的方法也可以靈活定義

@Controller

@RequestMapping("/demo01")

public classs Controller{

 @RequestMapping("/hello")

  public String execute()throws Exception{

    return "hello";

  }

}

為了使@Controller註解生效,需要在Spring的XML配置檔案中開啟元件掃描定義,並指定Controller元件所在包

<context:component-scan  base-package = "com.controller"/>

接受請求引數值

Spring MVC Web請求提交資料到控制器有下面幾種方法:

使用 HttpServletRequest獲取

使用@RequestParam註解

使用自動機制封裝成Bean物件

使用@RequestParam註解:

Spring會自動將表單引數注入到方法引數(名稱一致)

使用@RequestParam註解,對映不一致的名稱

優點引數型別會自動轉換,但可能出現型別轉換異常

@RequestMapping("/login-action.form")

public String checkLogin(String name,@RequestParam("pwd")String password,HttpServletRequest req){

  System.out.println(name);

  System.out.println(password);

  User user = userService.login(name,password);

    //處理過程

  return "success";

使用@ModelAttribute註解是當Controller元件處理後,需要向JSP傳值用此方法。

(引出:向JSP頁面傳值也可以直接使用HttpServletRequest和Session;ModeAndView物件;ModelMap引數物件等)

示例:

在Controller方法的引數部分或Bean屬性方法上使用。

@RequestMapping("login-action.from")

public String checkLogin(@ModelAttribute("user")User user){

  //處理過程

  return "success";

}

@ModelAttribute("name")

public String getName(){

  return name;

}

(@ModelAttribute資料會利用HttpServletRequest的Attribute傳遞到JSP頁面中)

@ExceptionHandler註解

@ExceptionHandler註解提供了Spring MVC處理異常的方法

(引出:Spring MVC處理異常的方法有三種:使用Spring MVC提供的簡單異常處理器(SimpleMappingExceptionResolver);實現HandlerExceptionResolver介面自定義異常處理器;使用 @ExceptionHandler註解實現異常處理)

@ExceptionHandler註解使用方法:

public class BaseController{

  @ExceptionHandler

  public String execute(HttpServletRequest req,Exception e){

    req.setAttribute("e",e);

    //可根據異常型別不同返回不同檢視名

    return "error";

  }

}

(適合區域性處理有“處理過程”的異常)

然後其他的Controller繼承BaseController類即可

@ResponseBody註解(在Spring MVC中,此註解與JSON響應相關)

在控制器方法上使用 @ResponseBody 註解, 就可以自動的將控制器的返回值(JavaBean)轉換為JSON傳送到客戶端.

@ResponseBody註解主要用於Controller元件的處理方法前,使用方法為:

引入jackson開發包,後面示例用的是jackson-annotations-2.4.1.jar,jackson-core-2.4.1.jar,jackson-databind-2.4.1.jar

在Spring配置檔案中定義<mvc:annotation-driven/>,開啟對@ResponseBody應用的支援

在Controller處理方法前定義@ResponseBody註解

示例:

使用@ResponseBody,返回單個值:

@RequestMapping("/test1")

@ResponseBody

public boolean f1(){
  //業務處理程式碼

  return true;

}

使用@ResponseBody返回多個值:

@RequestMapping("/test2")

@ResponseBody

public Map<String,Object>f2(){

  Map<String,Object> m = new HashMap<String,Object>)();

  m.put("id",1);

  m.put("name","Tom");

  return m;

}

使用@ResponseBody返回List結果:

@RequestMapping("/test3")

@ResponseBody

public List<String>f3(){
  List<String> list = new ArrayList<String>();

  list.add("java");

  list.add("php");

  list.add("ui");

  return list;

}

使用@ResponseBody返回物件結果:

@RequestMapping("/test4")

@ResponseBody

public Object f4(){

  Object obj = new Object();

  return obj;

}

使用@ResponseBody返回物件集合結果:

@RequestMapping("/test5")

@ResponseBody

public Object f5(){

  Emp e1 = new Emp();

  e1.setId(1);

  e1.setName("張三");

  Emp e2 = new Emp();

  e2.setId(2);

  e2.setName("李四");

  List<Emp> list = new ArrayList<Emp>();

  list.add(e1);

  ;ist.add(e2);

  return list;

}

註解實現AOP

開發步驟:

建立方面元件:

建立一個類,充當方面元件,實現通用業務邏輯。

宣告方面元件官網:www.fhadmin.org:

在applicationContext.xml中開啟AOP註解掃描:

<aop:aspectj-autoproxy proxy-target-class = "true"/>;

使用@Component註解標識這個類,將其宣告為元件。

使用@Aspect註解標識這個類,將其宣告為方面元件。

使用方面元件:

在元件的方法上,使用註解將方面元件作用到目標元件的方法上,並設定通知型別以確認方面元件呼叫的時機。

使用前置通知,在方面元件方法上增加註解:

@Before("within(controller..*)")

public void log(){

}

後置通知、最終通知使用方法與前置通知一致,只需要將註解改為@AfterReturning、@After即可。

環繞通知,在方面元件方法上增加註解:

@Around("within(controller..*)")

public Object log(ProceedingJoinPoint p) throws Throwable{

  //此處程式碼在目標元件前執行

  Object obj = p.proceed();//執行目標元件方法

  //此處程式碼在目標元件後執行

  return obj;

}

使用異常通知,在方面元件方法上增加註解:

@AfterThrowing(pointcut = "within(controller..*)",throwing = "e")

public void log(Exception e){

}

@Transactional註解

此註解實現宣告式事務,步驟如下:

在applicationContext.xml中宣告事務元件官網:www.fhadmin.org,開始事務註解掃描,示例為:

<!-- 宣告事務管理元件 -->

<bean id = "txManager"

  class = "org.springframework.jdbc.datasource.DataSourceTransactionManager">

      <property name = "dataSource"  ref = "ds"/>

</bean>

<!-- 開啟事務註解掃描 -->

<tx:annotation-driven transaction-manager = "txManager"  proxy-target-class = "true"/>

transaction-manager指定的事務管理器txManager,需要根據資料庫訪問技術不同選擇不同的實現。例如JDBC、Mybatis技術選用DataSourceTransactionManager,而Hibernate技術則選用HibernateTransactionManager.

使用 @Transactional註解宣告事務,使用方法為:

 @Transactional

public class DefaultFooService implements FooService{

  // @Transactional

  public void insertFoo(Foo foo){...}

  public void updateFoo(Foo foo){...}

 @Transactional註解標記可以用在類定義和方法定義前,方法的事務設定將優先於類級別註解的事務設定。

 @Transactional註解標記有以下屬性,在使用時可以根據需要做特殊設定:

- propagation:設定事務傳播

- isolation:設定事務隔離級別

- readOnly:設定為只讀,還是可讀寫

- rollbackFor:設定遇到哪些異常必須回滾

- noRollbackFor:設定遇到哪些異常不回滾

@Transactional註解屬性預設設定如下:

事務傳播設定是:PROPAGATION_REQUIRED

事務隔離級別是:ISOLATION_DEFAULT

事務是讀/寫

事務超時預設是依賴於事務系統的,或者事務超時沒有被支援

任何RuntimeException將觸發事務回滾,但是任何Checked Exception將不觸發事務回滾

@PathVariable應用

@PathVariable作用是將URI請求模板中的變數解析出來,對映到處理方法的引數上,示例為:

@RequestMapping(value = "/emp/{id}",method = requestMethod.GET)

public String execute(@PathVariable("id") int id){

  //查詢操作處理

  return " ";

}

上述URI請求模板匹配/emp/1、emp/2等格式請求