1、確保導入了jackson-core-asl-1.9.13.jar和jackson-mapper-asl-1.9.13.jar包
2、在spring的配置文件中加入<mvc:annotation-driven />這句,它提供了讀取jason的支持
3、
使用springMVC的@ResponseBody注解
@responsebody表示該方法的返回結果直接寫入HTTP response body中
一般在異步獲取數據時使用,在使用@RequestMapping后,返回值通常解析為跳轉路徑,加上@responsebody后返回結果不會被解析為跳轉路徑,而是直接寫入HTTP response body中。比如異步獲取json數據,加上@responsebody后,會直接返回json數據。
4、在以上配置都正確的情況下,我的項目還是不能返回json串。報錯:The resource identified by this request is only capable of generating responses with characteristics not acceptable according to the request "accept" headers ()。
今天終于在一個外文網站找到答案,是由于spring版本的問題引起的。我之前一直用的是3.0.0的版本。就是因為這個版本的問題。于是果斷去官網下載3.2版本的,一切正常運行,成功返回json數據。
posted @
2014-11-16 22:41 kelly 閱讀(14147) |
評論 (1) |
編輯 收藏
struts和spring整合首先要在Web容器啟動的時候自動裝配ApplicationContext的配置信息,可想而知應該在web.xml做相應的配置:
[html]
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:applicationContext.xml
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
配置了org.springframework.web.context.ContextLoaderListener后我們就不惜要編寫代碼顯示地實例化ApplicationContext對象了。至于為什么要使用監聽是因為web.xml 的加載順序是:context-param -> listener -> filter -> servlet 。如果你是在不想使用監聽,或許你可以嘗試下繼承struts2的org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter重寫這個它的init方法在StrutsPrepareAndExecuteFilter過濾器init中實例化ApplicationContext對象加載配置信息,雖然這種方法也可行,但是當攔截每個action都會加載一次配置信息,重新實例化了一個新的web容器,不僅浪費了資源也讓spring更加依賴了struts。
1、使用xml方式:
struts2配置
<package name="user" extends="struts-default">
<action name="login" class="userAction">
<result name="success">/success.jsp</result>
<result name="input" type="redirect">/index.jsp</result>
</action>
</package>
spring配置
<bean id="userDao" class="org.han.dao.impl.UserDaoImpl" />
<bean id="biz" class="org.han.service.impl.LoginBizImpl">
<property name="userdao" ref="userDao"/>
</bean>
<bean id="userAction" class="org.han.action.LoginAction" scope="prototype" >
<property name="biz" ref="biz" />
</bean>
注意紅色部分,struts2的action class與對應的action bean必須相同,這樣才能由spring管理action;
2、struts2使用零配置方式:
當你導入了零配置插件包的時候千萬要注意約定大于配置,還是上面的spring配置,只是不需要struts2配置了。
第一種方式:只需要將Action的className對應到spring配置中的bean id就行了
@Action(value = "/login", results = { @Result(name = "success", location = "/success.jsp"),@Result(name="input",location="/index.jsp")},className="userAction")
public String login() throws Exception {
// TODO Auto-generated method stub
User u=biz.login(this.getUser());
if(u!=null){
return SUCCESS;
}
return INPUT;
}
第二種方式:
Action注解不需要className了,將spring配置稍作修改
<bean id="org.han.action.LoginAction" class="org.han.action.LoginAction" scope="prototype" >
<property name="biz" ref="biz" />
</bean>
這樣可以是因為當你使用零配置的時候,action的class默認是當前類的全類名,所以和spring整合的時候剛好使用全類名在spring配置中查找以全類名為id的bean。
3、struts2、spring都使用注解方式:
www.2cto.com
<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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:component-scan base-package="org.han.dao.impl,org.han.service.impl,org.han.action"/>
</beans>
<context:component-scan base-package=""/>用此種方式,不需要在配置文件中再配置bean,也不需要再導入上面對應的處理bean。也就是說可以不需要在配置文件中使用<context:annotation-config/>了,因為此種方式會自動導入
[java]
@Namespace("/")
@Component(value="userLogin")
@Scope(value="prototype")
public class LoginAction extends ActionSupport {
public LoginAction() {
super();
// TODO Auto-generated constructor stub
System.out.println("action:"+this.hashCode());
}
@Autowired
private ILoginBiz biz;
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
@Autowired
public void setBiz(ILoginBiz biz) {
this.biz = biz;
}
@Override
@Action(value = "hello", results = { @Result(name = "success", location = "/success.jsp"),@Result(name="input",location="/index.jsp")})
public String execute() throws Exception {
// TODO Auto-generated method stub
System.out.println("biz:"+this.biz.hashCode());
User u=biz.login(this.getUser());
if(u!=null){
return SUCCESS;
}
return INPUT;
}
}
@Component 有一個可選的入參,用于指定 Bean 的名稱。一般情況下,Bean 都是 singleton 的,需要注入 Bean 的地方僅需要通過 byType 策略就可以自動注入了,所以大可不必指定 Bean 的名稱。除了提供 @Component 注釋外,還定義了幾個擁有特殊語義的注釋,它們分別是:@Repository、@Service 和 @Controller。在目前的 Spring 版本中,這 3 個注釋和 @Component 是等效的,但是從注釋類的命名上,很容易看出這 3 個注釋分別和持久層、業務層和控制層(Web 層)相對應。雖然目前這 3 個注釋和 @Component 相比沒有什么新意,但 Spring 將在以后的版本中為它們添加特殊的功能。所以,如果 Web 應用程序采用了經典的三層分層結構的話,最好在持久層、業務層和控制層分別采用 @Repository、@Service 和 @Controller 對分層中的類進行注釋,而用 @Component 對那些比較中立的類進行注釋。
@Scope用于定義Bean的作用范圍。
@Autowired 注釋,它可以對類成員變量、方法及構造函數進行標注,完成自動裝配的工作。當 Spring 容器啟動時,AutowiredAnnotationBeanPostProcessor 將掃描 Spring 容器中所有 Bean,當發現 Bean 中擁有 @Autowired 注釋時就找到和其匹配(默認按類型匹配)的 Bean,并注入到對應的地方中去。所以對成員變量使用 @Autowired 后,您大可將它們的 setter 方法刪除。
@Qualifier(“name”) 中的 name是 Bean 的名稱,所以 @Autowired 和 @Qualifier 結合使用時,自動注入的策略就從 byType 轉變成 byName 了。@Autowired 可以對成員變量、方法以及構造函數進行注釋,而 @Qualifier 的標注對象是成員變量、方法入參、構造函數入參。
@PostConstruct 和 @PreDestroy:JSR-250 為初始化之后/銷毀之前方法的指定定義了兩個注釋類,這兩個注釋只能應用于方法上。標注了 @PostConstruct 注釋的方法將在類實例化后調用,而標注了 @PreDestroy 的方法將在類銷毀之前調用。
通過 <bean> 元素的 init-method/destroy-method 屬性進行配置,都只能為 Bean 指定一個初始化 / 銷毀的方法。但是使用 @PostConstruct 和 @PreDestroy 注釋卻可以指定多個初始化 / 銷毀方法,那些被標注 @PostConstruct 或@PreDestroy 注釋的方法都會在初始化 / 銷毀時被執行。
更多的關于注解使用:請看官方文檔
4、總結:
1、注釋配置不一定在先天上優于 XML 配置。如果 Bean 的依賴關系是固定的,(如 Service 使用了哪幾個 DAO 類),這種配置信息不會在部署時發生調整,那么注釋配置優于 XML 配置;反之如果這種依賴關系會在部署時發生調整,XML 配置顯然又優于注釋配置,因為注釋是對 Java 源代碼的調整,您需要重新改寫源代碼并重新編譯才可以實施調整。
2、如果 Bean 不是自己編寫的類(如 JdbcTemplate、SessionFactoryBean 等),注釋配置將無法實施,此時 XML 配置是唯一可用的方式。
3、注釋配置往往是類級別的,而 XML 配置則可以表現得更加靈活。比如相比于 @Transaction 事務注釋,使用 aop/tx 命名空間的事務配置更加靈活和簡單。
所以在實現應用中,我們往往需要同時使用注釋配置和 XML 配置,對于類級別且不會發生變動的配置可以優先考慮注釋配置;而對于那些第三方類以及容易發生調整的配置則應優先考慮使用 XML 配置。Spring 會在具體實施 Bean 創建和 Bean 注入之前將這兩種配置方式的元信息融合在一起。
posted @
2014-01-17 21:51 kelly 閱讀(290) |
評論 (0) |
編輯 收藏
來自:http://hanyexiaoxiao.iteye.com/blog/410123
1. 使用Spring注解來注入屬性
1.1. 使用注解以前我們是怎樣注入屬性的
類的實現:
public class UserManagerImpl implements UserManager {
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
...
}
配置文件:
<bean id="userManagerImpl" class="com.kedacom.spring.annotation.service.UserManagerImpl">
<property name="userDao" ref="userDao" />
</bean>
<bean id="userDao" class="com.kedacom.spring.annotation.persistence.UserDaoImpl">
<property name="sessionFactory" ref="mySessionFactory" />
</bean>
1.2. 引入@Autowired注解(不推薦使用,建議使用@Resource)
類的實現(對成員變量進行標注)
public class UserManagerImpl implements UserManager {
@Autowired
private UserDao userDao;
...
}
或者(對方法進行標注)
public class UserManagerImpl implements UserManager {
private UserDao userDao;
@Autowired
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
...
}
配置文件
<bean id="userManagerImpl" class="com.kedacom.spring.annotation.service.UserManagerImpl" />
<bean id="userDao" class="com.kedacom.spring.annotation.persistence.UserDaoImpl">
<property name="sessionFactory" ref="mySessionFactory" />
</bean>
@Autowired可以對成員變量、方法和構造函數進行標注,來完成自動裝配的工作。以上兩種不同實現方式中,@Autowired的標注位置不同,它們都會在Spring在初始化userManagerImpl這個bean時,自動裝配userDao這個屬性,區別是:第一種實現中,Spring會直接將UserDao類型的唯一一個bean賦值給userDao這個成員變量;第二種實現中,Spring會調用setUserDao方法來將UserDao類型的唯一一個bean裝配到userDao這個屬性。
1.3. 讓@Autowired工作起來
要使@Autowired能夠工作,還需要在配置文件中加入以下代碼
<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />
1.4. @Qualifier
@Autowired是根據類型進行自動裝配的。在上面的例子中,如果當Spring上下文中存在不止一個UserDao類型的bean時,就會拋出BeanCreationException異常;如果Spring上下文中不存在UserDao類型的bean,也會拋出BeanCreationException異常。我們可以使用@Qualifier配合@Autowired來解決這些問題。
1. 可能存在多個UserDao實例
@Autowired
public void setUserDao(@Qualifier("userDao") UserDao userDao) {
this.userDao = userDao;
}
這樣,Spring會找到id為userDao的bean進行裝配。
2. 可能不存在UserDao實例
@Autowired(required = false)
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
1.5. @Resource(JSR-250標準注解,推薦使用它來代替Spring專有的@Autowired注解)
Spring 不但支持自己定義的@Autowired注解,還支持幾個由JSR-250規范定義的注解,它們分別是@Resource、@PostConstruct以及@PreDestroy。
@Resource的作用相當于@Autowired,只不過@Autowired按byType自動注入,而@Resource默認按byName自動注入罷了。@Resource有兩個屬性是比較重要的,分別是name和type,Spring將@Resource注解的name屬性解析為bean的名字,而type屬性則解析為bean的類型。所以如果使用name屬性,則使用byName的自動注入策略,而使用type屬性時則使用byType自動注入策略。如果既不指定name也不指定type屬性,這時將通過反射機制使用byName自動注入策略。
@Resource裝配順序
- 如果同時指定了name和type,則從Spring上下文中找到唯一匹配的bean進行裝配,找不到則拋出異常
- 如果指定了name,則從上下文中查找名稱(id)匹配的bean進行裝配,找不到則拋出異常
- 如果指定了type,則從上下文中找到類型匹配的唯一bean進行裝配,找不到或者找到多個,都會拋出異常
- 如果既沒有指定name,又沒有指定type,則自動按照byName方式進行裝配(見2);如果沒有匹配,則回退為一個原始類型(UserDao)進行匹配,如果匹配則自動裝配;
1.6. @PostConstruct(JSR-250)
在方法上加上注解@PostConstruct,這個方法就會在Bean初始化之后被Spring容器執行(注:Bean初始化包括,實例化Bean,并裝配Bean的屬性(依賴注入))。
它的一個典型的應用場景是,當你需要往Bean里注入一個其父類中定義的屬性,而你又無法復寫父類的屬性或屬性的setter方法時,如:
public class UserDaoImpl extends HibernateDaoSupport implements UserDao {
private SessionFactory mySessionFacotry;
@Resource
public void setMySessionFacotry(SessionFactory sessionFacotry) {
this.mySessionFacotry = sessionFacotry;
}
@PostConstruct
public void injectSessionFactory() {
super.setSessionFactory(mySessionFacotry);
}
...
}
這里通過@PostConstruct,為UserDaoImpl的父類里定義的一個sessionFactory私有屬性,注入了我們自己定義的sessionFactory(父類的setSessionFactory方法為final,不可復寫),之后我們就可以通過調用super.getSessionFactory()來訪問該屬性了。
1.7. @PreDestroy(JSR-250)
在方法上加上注解@PreDestroy,這個方法就會在Bean初始化之后被Spring容器執行。由于我們當前還沒有需要用到它的場景,這里不不去演示。其用法同@PostConstruct。
1.8. 使用<context:annotation-config />簡化配置
Spring2.1添加了一個新的context的Schema命名空間,該命名空間對注釋驅動、屬性文件引入、加載期織入等功能提供了便捷的配置。我們知道注釋本身是不會做任何事情的,它僅提供元數據信息。要使元數據信息真正起作用,必須讓負責處理這些元數據的處理器工作起來。
AutowiredAnnotationBeanPostProcessor和CommonAnnotationBeanPostProcessor就是處理這些注釋元數據的處理器。但是直接在Spring配置文件中定義這些Bean顯得比較笨拙。Spring為我們提供了一種方便的注冊這些BeanPostProcessor的方式,這就是<context:annotation-config />:
<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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<context:annotation-config />
</beans>
<context:annotationconfig />將隱式地向Spring容器注冊AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor、 PersistenceAnnotationBeanPostProcessor以及RequiredAnnotationBeanPostProcessor這4個BeanPostProcessor。
2. 使用Spring注解完成Bean的定義
以上我們介紹了通過@Autowired或@Resource來實現在Bean中自動注入的功能,下面我們將介紹如何注解Bean,從而從XML配置文件中完全移除Bean定義的配置。
2.1. @Component(不推薦使用)、@Repository、@Service、@Controller
只需要在對應的類上加上一個@Component注解,就將該類定義為一個Bean了:
@Component
public class UserDaoImpl extends HibernateDaoSupport implements UserDao {
...
}
使用@Component注解定義的Bean,默認的名稱(id)是小寫開頭的非限定類名。如這里定義的Bean名稱就是userDaoImpl。你也可以指定Bean的名稱:
@Component("userDao")
@Component是所有受Spring管理組件的通用形式,Spring還提供了更加細化的注解形式:@Repository、@Service、@Controller,它們分別對應存儲層Bean,業務層Bean,和展示層Bean。目前版本(2.5)中,這些注解與@Component的語義是一樣的,完全通用,在Spring以后的版本中可能會給它們追加更多的語義。所以,我們推薦使用@Repository、@Service、@Controller來替代@Component。
2.2. 使用<context:component-scan />讓Bean定義注解工作起來
<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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<context:component-scan base-package="com.kedacom.ksoa" />
</beans>
這里,所有通過<bean>元素定義Bean的配置內容已經被移除,僅需要添加一行<context:component-scan />配置就解決所有問題了——Spring XML配置文件得到了極致的簡化(當然配置元數據還是需要的,只不過以注釋形式存在罷了)。<context:component-scan />的base-package屬性指定了需要掃描的類包,類包及其遞歸子包中所有的類都會被處理。
<context:component-scan />還允許定義過濾器將基包下的某些類納入或排除。Spring支持以下4種類型的過濾方式:
- 過濾器類型 表達式范例 說明
- 注解 org.example.SomeAnnotation 將所有使用SomeAnnotation注解的類過濾出來
- 類名指定 org.example.SomeClass 過濾指定的類
- 正則表達式 com\.kedacom\.spring\.annotation\.web\..* 通過正則表達式過濾一些類
- AspectJ表達式 org.example..*Service+ 通過AspectJ表達式過濾一些類
以正則表達式為例,我列舉一個應用實例:
<context:component-scan base-package="com.casheen.spring.annotation">
<context:exclude-filter type="regex" expression="com\.casheen\.spring\.annotation\.web\..*" />
</context:component-scan>
值得注意的是<context:component-scan />配置項不但啟用了對類包進行掃描以實施注釋驅動Bean定義的功能,同時還啟用了注釋驅動自動注入的功能(即還隱式地在內部注冊了AutowiredAnnotationBeanPostProcessor和CommonAnnotationBeanPostProcessor),因此當使用<context:component-scan />后,就可以將<context:annotation-config />移除了。
2.3. 使用@Scope來定義Bean的作用范圍
在使用XML定義Bean時,我們可能還需要通過bean的scope屬性來定義一個Bean的作用范圍,我們同樣可以通過@Scope注解來完成這項工作:
@Scope("session")
@Component()
public class UserSessionBean implements Serializable {
...
}
3. 參考
http://kingtai168.iteye.com/blog/244002
http://www.iteye.com/topic/244153
http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-annotation-config
http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-classpath-scanning
posted @
2014-01-17 12:00 kelly 閱讀(255) |
評論 (0) |
編輯 收藏
摘要: Struts2.3+Spring3.2的整合
這兩天都是一直在鼓搗Struts2.3如何整合Spring3.2以及dao層到底選用什么以及如何整合。下面就把自己這兩天的一些小成果分享出來也以便自己以后在實際項目中快速搭建。
首先是Struts2.3整合Spring3.2
1、新建一個web工程(這個就不說了)
2、添...
閱讀全文
posted @
2014-01-16 10:32 kelly 閱讀(1963) |
評論 (0) |
編輯 收藏
警告信息如下:
警告: No configuration found for the specified action: '/myNameSpace/login.action' in namespace: ''. Form action defaulting to 'action' attribute's literal value.
struts.xml配置信息(部分)
<package name="packageName" extends="struts-default" namespace="/myNameSpace">
<action name="login" class="com.jato.srvclink.test.login.LoginAction" method="login">
jsp頁面配置信息(部分)
<s:form action="/myNameSpace/login.action">
思考:沒有在''的namespace中發現指定的action '/myNameSpace/login.action'
答疑:因為配置的struts2標簽并未指定namespace屬性。所以struts2會默認從根命名空間"/"搜索action串' /myNameSpace/login.action',如果搜索不到將進入默認命名空間''搜索action請求串,在默認命名空間中是肯定找不到我們 定義的action的,所以,struts2拋出一個警告信息。
但是為什么我們沒有填寫namespace,我們的請求也可以正常訪問呢?
我們來看一下解析后的html
查看源碼得到的html(部分)
<form id="login" onsubmit="return true;" action="/srvclink/myNameSpace/login.action" method="post">
我們看到form提交的action串是準確的url請求,action串確實是/srvclin(應用根)/myNameSpace(命名空間)/login.action。
命名空間中找不到action定義,并不意味著這個action真的不存在,只是我們的代碼有問題而已。還有一點是我們在jsp頁面的action請求中 手動的加入了.action后綴。事實上struts2會自動追加.action的,因為我們并沒有合法的使用struts2的標簽,所以struts2 這里并沒有給我們追加.action,解析后的代碼中存在的.action,完全是我們手動在jsp頁面填寫的,有疑問的網友可以不手動添加查看 html。
我們修改我們的程序代碼
jsp頁面配置信息(部分)修改后加入namespace屬性,修改action屬性值為/login.action
<s:form action="/login.action" namespace="/myNameSpace">
請求頁面后,大家很失望吧?警告依然存在。但是我們看一下警告信息。
警告信息:
警告: No configuration found for the specified action: '/login.action' in namespace: '/myNameSpace'. Form action defaulting to 'action' attribute's literal value.
沒有在'/myNameSpace'的namespace中發現指定的action '/login.action'
毫無疑問,這里的警告和第一次的警告信息截然不同。我們現在存在命名空間,'/myNameSpace'能夠被struts2檢索到,并不是開始的''。那問題的關鍵在哪里呢?
在namespace中沒有發現指定的action '/login.action' ???
我們來看一下struts.xml中的配置:
struts.xml配置信息(部分)
<package name="packageName" extends="struts-default" namespace="/myNameSpace">
<action name="login" class="com.jato.srvclink.test.login.LoginAction" method="login">
是的,我們'/myNameSpace'命名空間下,只有action名字為'login'的定義,并沒有所謂的'/login.action' 定義,所以struts2的警告并未錯。如果大家對這個抱有懷疑,可以修改action的名字'login'為‘/longin.action’
<action name="/login.action" class="com.jato.srvclink.test.login.LoginAction" method="login">
請求頁面時你會發現不在報警告信息,原因很簡單。因為在命名空間為'myNameSpace'下確實存在命名為'/login.action'的action。
我們再次修改配置文件
jsp頁面配置信息(部分)修改后action屬性值為longin
<s:form action="login" namespace="/myNameSpace">
請求頁面時,我們發現不再有警告信息了。
如果你有足夠細心,我想你應該可以徹底的明白為什么struts2會報警了吧?你也應該明白了使用struts2標簽action中添加/線后請求反而報錯的原因了。
posted @
2014-01-16 10:13 kelly 閱讀(255) |
評論 (0) |
編輯 收藏