Spring搭建Web应用(MVC)起步(Tomcat环境)
首先,建立WEB应用的目录,必须的。
在tomcat的webapp目录下,创建目录“spring”,目录结构如下:
spring
----WEB-INF
----classes
----lib
然后,肯定是搞web.xml了,创建一个web.xml在WEB-INF目录下。
随便去网上哪里找个web.xml模板,改改就行,如下:
[web.xml start]
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<servlet>
<servlet-name>Dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Dispatcher</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
[web.xml end]
以上面的web.xml为例,首先,我们要配一个 <welcome-file>index.jsp</welcome-file>
这样,当你直接输入你的http://www.website.com/的时候,tomcat就会默认返回
index.jsp给你,你才有机会往下面走,如进到xxx.do的页面。这个应用的根目录是“spring”,
<welcome-file>的配置没有加路径,那么默认就是在spring目录下,所以我们这个index.jsp就是
放在spring目录下。
在web.xml中,第二个要配的就是<servlet>,其中<servlet-name>随便配,只要跟后面
<servlet-mapping>中的<servlet-name>能对应得上就行。
<servlet-class>是你要处理http请求的实际类,既然我们是spring的web应用起步,
就简单的用它的DispatcherServlet,实际上,只要是httpServlet的子类且覆写了它的service方法,
都可以配到<servlet-class>中, 哥试着写了一个HttpServlet的子类,在service方法中,直接调用
esponse.getWriter().print("<html>...</html>");返回结果页面给客户端IE。
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/config.xml</param-value>
</init-param>
上面这一段,你可以配置你想要使用的配置文件,有多个就配多个<param-name>和<param-value>对。
你可以在里面配置spring的beans配置文件,也可以添加struts的,ibatis的,其他第三方框架的配置文件
<servlet-class>里面配置的类,总有办法能获取配置文件的信息,也许是Tomcat容器帮你载入配置信息,
也很有可能是容器仅提供配置文件的路径,由servlet自身在init方法中去载入这些配置文件的内容。
估计spring的DispatcherServlet是通过反射,将<param-name>跟<param-value>注入到类的属性中,
然后再用自己的一套读配置文件的接口读入配置信息。
<load-on-startup>这一项,哥完全是直接抄过来的,貌似在这个起步应用里没用。
<servlet-mapping>里面的东西就不用说了,无非就是告诉容器,只有包含.do 的http请求,才会交给
DispatcherServlet来处理。
web.xml分析完了,但是现在发现我们才弄明白了MVC中的C(Controller),那么,M跟V何解?
我们去看看/WEB-INF/config.xml就知道了:
[config.xml start]
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans">
<!-- 上面这行,后面还跟了堆命名空间啥的不管它,为节省篇幅,这里去掉 -->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewReso
lver">
<property name="viewClass">
<value>org.springframework.web.servlet.view.JstlView</value>
</property>
</bean>
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/login.do">loginAction</prop>
</props>
</property>
</bean>
<bean id="loginAction" class="com.huawei.guoqing.springmvc.LoginAction">
<property name="commandClass">
<value>com.huawei.guoqing.springmvc.LoginBean</value>
</property>
<property name="success_view">
<value>loginok.jsp</value>
</property>
<property name="fail_view">
<value>loginfail.jsp</value>
</property>
</bean>
</beans>
[config.xml end]
先看看 <bean id="viewResolver"></bean> 这一项:
id="viewResolver",这个"viewResolver"是个特殊的字符串,查看
DispatcherServlet.java的源代码,在
private void initViewResolvers(ApplicationContext context)
这个方法里面,有这样两行:
ViewResolver vr = context.getBean(VIEW_RESOLVER_BEAN_NAME, ViewResolver.class);
this.viewResolvers = Collections.singletonList(vr);
注意到 VIEW_RESOLVER_BEAN_NAME 是一个常量:"viewResolver",可见,spring把你在
<property name="viewClass"></property>中配的类实例化,注入到DispatcherServlet中,供其使用。
下面这个bean的配置比较蛊惑:
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
id="urlMapping"这个是根据学习资料配的,但是实际上哥无论把id改成什么,比如 id="abcMapping",
这个WEB应用一样正常工作,可见,这玩意不是通过名字来注入的。然后,哥配了两个bean,分别为
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<bean id="abcMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
发现,哪个配在前面,实际上 DispatcherServlet 调用的就是哪一个,然后,因为
BeanFactory中有这样的获取bean的方法:getBean(Class<T> arg0);推测,这个bean的配置关键是在
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping",只要你class配置
为SimpleUrlHandlerMapping(按spring的习惯,应该是SimpleUrlHandlerMapping的父类或接口,接口的
可能性更大)。容器就会根据类型去取道bean,注入给Servlet使用。
<bean id="urlMapping">这个bean的配置里面,最重要的就是
<prop key="/login.do">loginAction</prop>
key="/login.do",这个login.do,就是对应我们写在 index.jsp中的这一行:
<form id="form1" action="login.do" method="post">
DispatcherServlet 发现你页面提交过来的url是login.do,就会交给loginAction去处理。
这个loginAction嘛,看看我们的config.xml里面的最后一个bean定义:
<bean id="loginAction" class="com.huawei.guoqing.springmvc.LoginAction">
具体的处理类完全由我们自己实现,这就同Spring没有太紧密的耦合,这里比 <bean id="viewResolver">
跟 <bean id="urlMapping" class="xxxx"> 舒服多了。但是,我们的
LoginAction 还是必须为 org.springframework.web.servlet.mvc.SimpleFormController 的子类
注意到我们的loginAction里面,有这么一项:
<property name="commandClass">
<value>com.huawei.guoqing.springmvc.LoginBean</value>
</property>
嗯,这一项也是完全由我们自己实现的
看看LoginAction.java的代码,我们必须覆写 父类 SimpleFormController 中的 onSubmit 方法
protected ModelAndView onSubmit(Object cmd,BindException be)
{
}
Spring会把你的 commandClass 实例化 ,在调用onSubmit注入到cmd这个参数里面去。
这里Spring封装得很好的一个就是,只要你的 commandClass 的属性(这里commandClass就是 LoginBean),
跟jsp页面的表单输入项的一样,Spring就帮你自动把值注入,很是方便:
index.jsp中代码片断:
用户名 <input type="text" name="username"/>
密码 <input type="text" name="password"/>
LoginBean.java代码片断:
private String username;
private String password;
Spring会把页面上的 <input type="text" name="username"/>的内容,注入到
LoginBean的 username 属性 (应该要有相应的setter方法)。
最后,看这一项:
<property name="success_view">
<value>loginok.jsp</value>
</property>
看看 LoginAction.java 的 onSubmit(Object cmd,BindException be)方法,就知道是干嘛的了:
HashMap resultMap = new HashMap();
return new ModelAndView(this.success_view, resultMap);
Spring会帮你把页面返回到 loginok.jsp;至于这里ModelAndView这个类是怎么生成jsp的,还没有去研究。
因为我们没配置前缀后缀参数,所以返回的是webapps\spring 这个根目录下面的 loginok.jsp
(想了解更详细的配置,如前缀,后缀,请自行查阅相关资料)
总结:这样,我们就把用spring如何搭建WEB应用基本讲明白了,你想替换它的view就替换,想替换model就替换,
就是想替换Servlet也没问题。可以用第三方的MVC框架而不必拘泥于Spring的,但是不建议自己写MVC,因为,
你要从request里面提取页面的各项输入,甚至还有附件的byte流。然后再注入你自己的model,生成你自己的view类,
实在不是一件轻松的事。我们知道它的原理就好。
最后补充一些东西:
因为搭建应用过程中遇到问题,页面报错,查看了Tomcat日志,才发现是少了jar包,
弄了好几次才搞好(每次提示少这个jar包,添加进去后启动tomcat,又报少另一个),
所以把哥自己应用下的目录结构列一下,(文件名后面跟[d]的,表示是一个目录)
[dirTree start]
spring[d]
----index.jsp
----loginok.jsp
----loginfail.jsp
****WEB-INF[d]
----web.xml
----config.xml
****classes[d]
----{这里是你自己的.class文件}
****lib[d]
----commons-logging.jar
----commons-logging-api-1.1.jar
----jstl.jar
----log4j-1.2.8.jar
----org.springframework.asm-3.0.2.RELEASE.jar
----org.springframework.beans-3.0.2.RELEASE.jar
----org.springframework.context-3.0.2.RELEASE.jar
----org.springframework.context.support-3.0.2.RELEASE.jar
----org.springframework.core-3.0.2.RELEASE.jar
----org.springframework.expression-3.0.2.RELEASE.jar
----org.springframework.web-3.0.2.RELEASE.jar
----org.springframework.web.servlet-3.0.2.RELEASE.jar
----servlet-api.jar
[dirTree end]
然后,肯定是搞web.xml了,创建一个web.xml在WEB-INF目录下。
随便去网上哪里找个web.xml模板,改改就行,如下:
[web.xml start]
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
</web-app>
[web.xml end]
以上面的web.xml为例,首先,我们要配一个 <welcome-file>index.jsp</welcome-file>
这样,当你直接输入你的http://www.website.com/的时候,tomcat就会默认返回
index.jsp给你,你才有机会往下面走,如进到xxx.do的页面。这个应用的根目录是“spring”,
<welcome-file>的配置没有加路径,那么默认就是在spring目录下,所以我们这个index.jsp就是
放在spring目录下。
在web.xml中,第二个要配的就是<servlet>,其中<servlet-name>随便配,只要跟后面
<servlet-mapping>中的<servlet-name>能对应得上就行。
<servlet-class>是你要处理http请求的实际类,既然我们是spring的web应用起步,
就简单的用它的DispatcherServlet,实际上,只要是httpServlet的子类且覆写了它的service方法,
都可以配到<servlet-class>中, 哥试着写了一个HttpServlet的子类,在service方法中,直接调用
esponse.getWriter().print("<html>...</html>");返回结果页面给客户端IE。
<init-param>
</init-param>
上面这一段,你可以配置你想要使用的配置文件,有多个就配多个<param-name>和<param-value>对。
你可以在里面配置spring的beans配置文件,也可以添加struts的,ibatis的,其他第三方框架的配置文件
<servlet-class>里面配置的类,总有办法能获取配置文件的信息,也许是Tomcat容器帮你载入配置信息,
也很有可能是容器仅提供配置文件的路径,由servlet自身在init方法中去载入这些配置文件的内容。
估计spring的DispatcherServlet是通过反射,将<param-name>跟<param-value>注入到类的属性中,
然后再用自己的一套读配置文件的接口读入配置信息。
<load-on-startup>这一项,哥完全是直接抄过来的,貌似在这个起步应用里没用。
<servlet-mapping>里面的东西就不用说了,无非就是告诉容器,只有包含.do 的http请求,才会交给
DispatcherServlet来处理。
web.xml分析完了,但是现在发现我们才弄明白了MVC中的C(Controller),那么,M跟V何解?
我们去看看/WEB-INF/config.xml就知道了:
[config.xml start]
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans">
<!-- 上面这行,后面还跟了堆命名空间啥的不管它,为节省篇幅,这里去掉 -->
</beans>
[config.xml end]
先看看 <bean id="viewResolver"></bean> 这一项:
id="viewResolver",这个"viewResolver"是个特殊的字符串,查看
DispatcherServlet.java的源代码,在
private void initViewResolvers(ApplicationContext context)
这个方法里面,有这样两行:
注意到 VIEW_RESOLVER_BEAN_NAME 是一个常量:"viewResolver",可见,spring把你在
<property name="viewClass"></property>中配的类实例化,注入到DispatcherServlet中,供其使用。
下面这个bean的配置比较蛊惑:
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
id="urlMapping"这个是根据学习资料配的,但是实际上哥无论把id改成什么,比如 id="abcMapping",
这个WEB应用一样正常工作,可见,这玩意不是通过名字来注入的。然后,哥配了两个bean,分别为
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<bean id="abcMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
发现,哪个配在前面,实际上 DispatcherServlet 调用的就是哪一个,然后,因为
BeanFactory中有这样的获取bean的方法:getBean(Class<T> arg0);推测,这个bean的配置关键是在
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping",只要你class配置
为SimpleUrlHandlerMapping(按spring的习惯,应该是SimpleUrlHandlerMapping的父类或接口,接口的
可能性更大)。容器就会根据类型去取道bean,注入给Servlet使用。
<bean id="urlMapping">这个bean的配置里面,最重要的就是
<prop key="/login.do">loginAction</prop>
key="/login.do",这个login.do,就是对应我们写在 index.jsp中的这一行:
<form id="form1" action="login.do" method="post">
DispatcherServlet 发现你页面提交过来的url是login.do,就会交给loginAction去处理。
这个loginAction嘛,看看我们的config.xml里面的最后一个bean定义:
<bean id="loginAction" class="com.huawei.guoqing.springmvc.LoginAction">
具体的处理类完全由我们自己实现,这就同Spring没有太紧密的耦合,这里比 <bean id="viewResolver">
跟 <bean id="urlMapping" class="xxxx"> 舒服多了。但是,我们的
LoginAction 还是必须为 org.springframework.web.servlet.mvc.SimpleFormController 的子类
注意到我们的loginAction里面,有这么一项:
嗯,这一项也是完全由我们自己实现的
看看LoginAction.java的代码,我们必须覆写 父类 SimpleFormController 中的 onSubmit 方法
Spring会把你的 commandClass 实例化 ,在调用onSubmit注入到cmd这个参数里面去。
这里Spring封装得很好的一个就是,只要你的 commandClass 的属性(这里commandClass就是 LoginBean),
跟jsp页面的表单输入项的一样,Spring就帮你自动把值注入,很是方便:
index.jsp中代码片断:
LoginBean.java代码片断:
Spring会把页面上的 <input type="text" name="username"/>的内容,注入到
LoginBean的 username 属性 (应该要有相应的setter方法)。
最后,看这一项:
看看 LoginAction.java 的 onSubmit(Object cmd,BindException be)方法,就知道是干嘛的了:
Spring会帮你把页面返回到 loginok.jsp;至于这里ModelAndView这个类是怎么生成jsp的,还没有去研究。
因为我们没配置前缀后缀参数,所以返回的是webapps\spring 这个根目录下面的 loginok.jsp
(想了解更详细的配置,如前缀,后缀,请自行查阅相关资料)
总结:这样,我们就把用spring如何搭建WEB应用基本讲明白了,你想替换它的view就替换,想替换model就替换,
就是想替换Servlet也没问题。可以用第三方的MVC框架而不必拘泥于Spring的,但是不建议自己写MVC,因为,
你要从request里面提取页面的各项输入,甚至还有附件的byte流。然后再注入你自己的model,生成你自己的view类,
实在不是一件轻松的事。我们知道它的原理就好。
最后补充一些东西:
因为搭建应用过程中遇到问题,页面报错,查看了Tomcat日志,才发现是少了jar包,
弄了好几次才搞好(每次提示少这个jar包,添加进去后启动tomcat,又报少另一个),
所以把哥自己应用下的目录结构列一下,(文件名后面跟[d]的,表示是一个目录)
[dirTree start]
[dirTree end]