问题
I have to design a very large scale project for a bank using spring mvc. I already choose to go with the XML configuration. My concern is to limit the start up time of the server. There will be approximately 2000 controllers.
I already use component scan for scanning the @Controller
. It worked fine. But, the problem is when I remove the component scan from XML and add the controller bean using bean configuration manually in XML, it didn't create the instance of controller in IOC container. And gives me the 404 not found error. So how can I configure the controller without component scanning in XML.
Followings are my code samples. Any help?
servlet-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"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
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">
<context:annotation-config/>
<mvc:resources mapping="/resources/**" location="/resources/" />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/" />
<property name="suffix" value=".jsp" />
</bean>
<!--<context:component-scan base-package="" />-->
</beans>
root-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">
<import resource="dataContext/data-context.xml" />
<bean id="contactSetupController" class="com.stl.afs.ci.cca.controller.ContactSetupController">
<property name="contactSetupDao" ref="contactSetupDao" />
</bean>
<bean id="contactSetupDao" class="com.stl.afs.ci.cca.controller.ContactSetupDao" scope="prototype">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
</beans>
ContactSetupController.java
package com.stl.afs.ci.cca.controller;
import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
@RequestMapping("/contactsetup")
public class ContactSetupController {
private static final Logger logger = LoggerFactory.getLogger(ContactSetupController.class);
private ContactSetupDao contactSetupDao;
public void setContactSetupDao(ContactSetupDao contactSetupDao) {
this.contactSetupDao = contactSetupDao;
}
@RequestMapping(method = RequestMethod.GET)
public String index(ModelMap model) {
contactSetupDao.showDepedency();
model.addAttribute("message", "Hello world! Nice to see you in the planet");
return "ci/contactsetup/index";
}
}
ContactSetupDao.java
package com.stl.afs.ci.cca.controller;
import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/**
* Created by ARNAB on 1/8/2015.
*/
public class ContactSetupDao {
public ContactSetupDao() {
System.out.println("------DAO------");
}
private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sessionFactory) {
System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@" + sessionFactory);
this.sessionFactory = sessionFactory;
}
@Transactional(readOnly = true)
public void showDepedency(){
Query query = sessionFactory.getCurrentSession().createSQLQuery("SELECT * FROM customers");
int i = 0;
for (Object o : query.list()) {
i++;
}
System.out.println(i);
}
}
回答1:
The problem why you get 404 - Not Found
is use of tag <context:annotation-config/>
only.
<context:annotation-config/>
only activates the annotation on the beans which are already registered with your application context and does basic autowiring for you. It does not auto-detect and register beans.
So there are no as such no Controllers
available for you to handle request.
In order to configure controllers you either switch back to context:component-scan
which anyways is working for you (do consider taking M. Deinum suggestion while reverting) or manually configure the controllers to respective URL's via HandlerMappings
such as SimpleUrlHanslerMapping (not recommended due to verbosity involved)
P.S.: Do read this fabulous post discussing the differences between <context:annotation-config>
and <context:component-scan>
回答2:
How can I configure the controller without component scanning in XML?
. you can use annotation based configuration to avoid XML.
check this EnableWebMvc configuration. I configured a spring3.2 project without xml configuration. it was totally annotation based.
overwrite startup of web application Initializer :
public class Initializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException
{
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(WebAppConfig.class);
ctx.setServletContext(servletContext);
ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcher", new DispatcherServlet(ctx));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
servletContext.addListener(new ContextLoaderListener(ctx));
}
}
Configuration file for application context
@Configuration
@ComponentScan("com.paul.nkp") // set your root package, it will scan all sub-package
@EnableWebMvc
@EnableTransactionManagement
@PropertySource("classpath:com/paul/nkp/application.properties")
public class WebAppConfig extends WebMvcConfigurerAdapter {
/**
* configured for read property values using @Value attibutes
*
* @return
*/
@Bean
public static PropertySourcesPlaceholderConfigurer placeHolderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
@Bean(name = "multipartResolver")
public static MultipartResolver multipartResolver() {
return new CommonsMultipartResolver();
}
@Bean
public LocalSessionFactoryBean sessionFactory() throws PropertyVetoException, IOException {
LocalSessionFactoryBean sessionFactoryBean = new LocalSessionFactoryBean();
......
sessionFactoryBean.setHibernateProperties(getHibernateProperties());
System.out.println("Session Factory Init");
return sessionFactoryBean;
}
}
Now everything in code, no xml manipulation. There is a ComponentScan annotation in configuration file, which scan all spring annotation from you base package.
来源:https://stackoverflow.com/questions/27847237/how-to-configure-controller-in-spring-without-component-scanning-in-xml