[转] 基于引文的Spring MVC简单介绍

[转] 基于注解的Spring MVC简单介绍

SpringMVC是一个基于DispatcherServlet的MVC框架,每一个请求最先访问的都是DispatcherServlet,DispatcherServlet负责转发每一个Request请求给相应的Handler,Handler处理以后再返回相应的视图(View)和模型(Model),返回的视图和模型都可以不指定,即可以只返回Model或只返回View或都不返回。
DispatcherServlet是继承自HttpServlet的,既然SpringMVC是基于DispatcherServlet的,那么我们先来配置一下DispatcherServlet,好让它能够管理我们希望它管理的内容。HttpServlet是在web.xml文件中声明的。
<servlet>
<servlet-name>blog</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>blog</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
上面声明了一个名为blog的DispatcherServlet,该Servlet将处理所有以“.do”结尾的请求。在初始化DispatcherServlet的时候,SpringMVC默认会到/WEB-INF目录下寻找一个叫[servlet-name]-servlet.xml的配置文件,来初始化里面的bean对象,该文件中对应的bean对象会覆盖spring配置文件中声明的同名的bean对象。如上面的就会在/WEB-INF目录下寻找一个叫blog-servlet.xml的文件;当然也可以在Servlet中声明配置文件的位置。
<servlet>
<servlet-name>blog</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/blog-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>blog</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
DispatcherServlet会利用一些特殊的bean来处理Request请求和生成相应的视图返回。
关于视图的返回,Controller只负责传回来一个值,然后到底返回的是什么视图,是由视图解析器控制的,在jsp中常用的视图解析器是InternalResourceViewResovler,它会要求一个前缀和一个后缀
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/" />
<property name="suffix" value=".jsp" />
</bean>
在上述视图解析器中,如果Controller返回的是blog/index,那么通过视图解析器解析之后的视图就是/WEB-INF/blog/index.jsp。
要使用注解的SpringMVC需要在SpringMVC的配置文件中进行声明,具体方式为先引入mvc命名空间,然后利用<mvc:annotation-driven />进行声明。
<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"
<SPAN style="BACKGROUND-COLOR: #00ff00"><SPAN style="COLOR: #ff0000">xmlns:mvc="http://www.springframework.org/schema/mvc"</SPAN></SPAN>
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
<SPAN style="COLOR: #ff0000; BACKGROUND-COLOR: #00ff00"> http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"</SPAN>>

<mvc:annotation-driven />

</beans>
主要是说说Controller.
一个类使用了@Controller进行标记的都是Controller
@Controller
public class BlogController {

}
有了Controller之后,那么到底是怎样请求一个Controller具体的方法的呢,那是通过@RequestMapping来标记的,@RequestMapping可以标记在类上面,也可以标记在方法上,当方法上和类上都标记了@RequestMapping的时候,那么对应的方法对应的Url就是类上的加方法上的,如下面的index方法,其对应的URL应为类上的/blog加上index方法上的/index,所以应为/blog/index,所以当请求/blog/index.do的时候就会访问BlogController的index方法。
@Controller
@RequestMapping("/blog")
public class BlogController {


@RequestMapping("/index")
public String index(Map<String, Object> map) {
return "blog/index";
}
}
在上面的代码中,如果index方法上没有RequestMapping注解,而只有BlogController类上有,且该类只有一个方法的时候,直接请求类上的URL就会调用里面的方法,即直接请求/blog.do的时候就会调用index方法。
在RequestMapping中还可以指定一个属性method,其主要对应的值有RequestMethod.GET和RequestMethod.POST,利用该属性可以严格的控制某一方法只能被标记的请求路径对应的请求方法才能访问,如指定method的值为GET,则表示只有通过GET方式才能访问该方法,默认是都可以访问。
在SpringMVC中常用的注解还有@PathVariable,@RequestParam,@PathVariable标记在方法的参数上,利用它标记的参数可以利用请求路径传值,看下面一个例子
@RequestMapping(value="/comment/{blogId}", method=RequestMethod.POST)
public void comment(Comment comment,@PathVariable int blogId, HttpSession session, HttpServletResponse response) throws IOException {

}
在该例子中,blogId是被@PathVariable标记为请求路径变量的,如果请求的是/blog/comment/1.do的时候就表示blogId的值为1. 同样@RequestParam也是用来给参数传值的,但是它是从头request的参数里面取值,相当于request.getParameter("参数名")方法。
在Controller的方法中,如果需要WEB元素HttpServletRequest,HttpServletResponse和HttpSession,只需要在给方法一个对应的参数,那么在访问的时候SpringMVC就会自动给其传值,但是需要注意的是在传入Session的时候如果是第一次访问系统的时候就调用session会报错,因为这个时候session还没有生成。
接下来讨论一下方法的返回值,主要有一下情况:
返回一个ModelAndView,其中Model是一个Map,里面存放的是一对对的键值对,其可以直接在页面上使用,View是一个字符串,表示的是某一个View的名称
返回一个View,也就是一个字符串,这个时候如果需要给页面传值,可以给方法一个Map参数,该Map就相当于一个Model,往该Model里面存入键值对就可以在页面上进行访问了
返回一个Model也就是一个Map,这个时候将解析默认的生成的view name。
什么也不返回,这个时候可以利用HttpServletResponse进行返回,也可以直接使用printStream进行返回
下面是一个简单的实例
@RequestMapping("/{owner}/index")
public String userIndex(Map<String, Object> map,@PathVariable String owner, HttpServletRequest request) throws ParserException {
List<DefCategory> categories = categoryService.find(owner);
int offset = Util.getOffset(request);
Pager<Blog> pager = blogService.find(owner, 0, offset, maxResults);
int totalRecords = pager.getTotalRecords();
List<Blog> blogs = pager.getData();
Util.shortBlog(blogs);

List<Message> messages = messageService.find(owner, 0, 5).getData();
Util.shortMessage(messages, 20);
map.put("messages", messages);
map.put("totalRecords", totalRecords);
List<BlogStore> stores = storeService.find(owner, 0, 5).getData();
map.put("maxResults", maxResults);
map.put("blogs", blogs);
map.put("totalRecords", totalRecords);
map.put("owner", userService.find(owner));
map.put("defCategories", categories);
map.put("stores", stores);
return "blog/userIndex";
}

 

 

转自:http://www.linuxidc.com/Linux/2012-02/54896p3.htm

1 楼 snlilei 2012-02-27  
1、web项目启动时出现ClassCastException。具体信息如下:     
        org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in ServletContext resource  [/META-INF/applicationContext.xml]:   Invocation of init method failed;   nested exception is org.springframework.beans.BeanInstantiationException:   Could not instantiate bean class [org.hibernate.cfg.AnnotationConfiguration]:    Constructor threw exception; nested exception is java.lang.ClassCastException:     org.hibernate.annotations.common.reflection.java.JavaReflectionManager cannot be cast to org.hibernate.annotations.common.reflection.MetadataProviderInjector

原因:
hibernate3.jar,里面已经包含?annotations相关包,与hibernate3.jar和hibernate-annotations.jar或hibernate-commons-annotations.jar有冲突。

解决办法:
将lib目录下的:   hibernate-annotations.jar 和 hibernate-commons-annotations.jar 删除后重新部署。


2、部署web工程到tomcat是出错:An internal error occurred during: "Redeploy". java.lang.NullPointerException

原因:JDK版本不一致

解决办法:

    右键项目名→Properties→Java Build Path→Libraries→选中JRE System Library[Sun JDK 1.6.0_13]→Edit→选中“Workspace default JRE(Sun JDK 1.6.0_13)”→Finish
    重新部署

3、tomcat部署成功,启动tomcat后找不到页面,报404错误
原因:
欢迎页面放置路径错误,应该放在发布包的下的根目录里,WEB-INF目录外面,与WEB-INF目录同级。

解决方案:
把欢迎页面放到正确的的路径下。
web.xml文件配置:
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
则把index.jsp文件的放置路径为:/webapp/dss/index.jsp

4、启动后老是打印错误日志:
java.lang.Exception: DEBUG -- CLOSE BY CLIENT STACK TRACE
at com.mchange.v2.c3p0.impl.NewPooledConnection.close(NewPooledConnection.java:491)
at com.mchange.v2.c3p0.impl.NewPooledConnection.close(NewPooledConnection.java:191)
at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1PooledConnectionResourcePoolManager.destroyResource(C3P0PooledConnectionPool.java:470)
at com.mchange.v2.resourcepool.BasicResourcePool$1DestroyResourceTask.run(BasicResourcePool.java:964)
at com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:547)

原因:
这个是c3p0的调试信息,不会影响C3PO的使用

解决方法:
这个是c3p0调测数据库连接的测试信息,不是错误。最简单的方法时提高日志输出级别,就看不到了。
        这个信息是datasource中的automaticTestTable配置引起的,使用<property name=”preferredTestQuery” value=”select * from dual” /> ,这个属性就可以既能检测连接,还不用建立垃圾表,当然这个是在oracle中,dual是自带的虚拟表吗,sqlserver和mysql的from及以后就可以省掉了。

5、解析jsp页面时字符编码出错:
org.apache.jasper.JasperException: Page-encoding specified in XML prolog (UTF-8) is different from that specified in jsp-property-group (utf-8)

原因:
jsp页面中配置的字符编码与web.xml文件的配置不一致

解决方法:
修改JSP页面中的配置:<?xml version="1.0" encoding="UTF-8"?>,
与web.xml文件中的配置
  <jsp-property-group>
   <url-pattern>*.jsp</url-pattern>
  <page-encoding>UTF-8</page-encoding>
  </jsp-property-group>
  两者保持一致。

6、myeclipse 开发web项目切换到JSP编辑器时出现错误信息:myeclispe unhandled event loop exception NO more handles,
点击OK时弹出对话框:
An SWT error has occurred.   
You are recommended to exit the workbench.  
Subsequent errors may happen and may terminate the workbench without warning.   
See the .log file for more details.     Do you want to exit the workbench?
点击OK时自动退出。

原因:
默认的JSP编辑器无法识别JSP中的部分元素

解决方案:
window->preferences->general->editors->file associations 选中JSP,换一个编辑器即可。不行的话就先将默认的jsp designer 移除,再选择。

7、tomcat启动时加载log4j配置文件失败:
log4j:WARN No appenders could be found for logger (org.springframework.web.context.ContextLoader).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.

原因:
这个提示是读入web应用程序的log4j.properties文件之前报出来的。是在加载org.springframework.web.context.ContextLoader这个listener的时候没找到log4j的配置文件造成的。

解决方案:
把log4j的配置放到org.springframework.web.context.ContextLoader之前,让spring先加载

10、spring容器找不到映射URL
No mapping found for HTTP request with URI [/dss/login.do] in DispatcherServlet with name 'dss'

2 楼 wutheringsea 2012-02-28  
谢谢楼上提供搭建项目时常见的错误和处理办法[转] 基于引文的Spring MVC简单介绍