不废话了,Spring 有多重要。首先是跑个 Hello World。
Spring 最基本功能是 IOC,如果不懂或者好奇原理的可以参考《极简版 Java 依赖注射》。
Hello World
怎么获取 Spring?官方推荐 Maven 依赖管理(据说 Ant 也可以),也可以下载 Java 源码构建。但本人比较追求好快多省,不喜欢加一坨坨多余的东西,就想直接下 jar 包。于是找到 http://repo.spring.io/release/org/springframework/。
不知道下载哪些必要的包?没关系,先把 Hello World 代码贴进去,有报错的咱就去下载。
Hello World 程序一个三个文件,分别如下。
// hello/MessageService.java
package hello;
public interface MessageService {
String getMessage();
}
// hello/MessagePrinter.java
package hello;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class MessagePrinter {
final private MessageService service;
@Autowired
public MessagePrinter(MessageService service) {
this.service = service;
}
public void printMessage() {
System.out.println(this.service.getMessage());
}
}
// hello/Application.java
package hello;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.*;
@Configuration
@ComponentScan
public class Application {
@Bean
MessageService mockMessageService() {
return new MessageService() {
public String getMessage() {
return "Hello World!";
}
};
}
public static void main(String[] args) {
ApplicationContext context =
new AnnotationConfigApplicationContext(Application.class);
MessagePrinter printer = context.getBean(MessagePrinter.class);
printer.printMessage();
}
}
缺的 jar 包大概如下(如果有新版本就下新版本),
基本上官方下载都齐了,另外依赖 Apache 日志接口,下载 http://commons.apache.org/proper/commons-logging/download_logging.cgi。
这些就是运行 Spring Hello World 最基本的包了。Alt+Shift+X 运行下 Java 程序,成功运行结果如下。
虽然成功运行了,但 IDE 提示“Resource leak: 'context' is never closed”,怎么办?有人说用 Java 1.7 的 try 自动回收资源可以,但我试过不成功,于是改这个 ((ConfigurableApplicationContext) context).close(); 就 ok 了。
Spring MVC
MVC 需要 spring-web-4.2.4.RELEASE.jar、spring-webmvc-4.2.4.RELEASE.jar 包,还需要 AOP 的框架 aspectjweaver-1.6.10.jar 和 aopalliance-1.0.jar。
Spring MVC 仍旧与传统 Servlet MVC 那样配置 web.xml。当然新版 4.0 是可以作为 XML 零配置的,在 Java 里面使用注解就可以完成 XML 配置了(Servlet 3.0 开始都支持了)。
第一步,配置 web.xml 如下。
<?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">
<display-name>MyServlet</display-name>
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>springMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springMVC</servlet-name>
<url-pattern>/greeting</url-pattern>
</servlet-mapping>
</web-app>
DispatcherServlet 继承自 HttpServlet 的,由它来分各种请求。每一个请求最先访问的都是 DispatcherServlet,DispatcherServlet 负责转发每一个 Request 请求给相应的Handler,Handler 处理以后再返回相应的视图(View)和模型(Model)。
该例子中我们指定了 /greeting 分发,对应执行哪个控制器呢?初始化 DispatcherServlet时会在 WEB-INF 目录中寻找一个名为 [servlet-名称]-servlet.xml 的文件,在那里执行对应的控制器。并且可以在那里定义相关的 Beans,重写在全局中定义的任何 Beans。
这个例子中是 springMVC-servlet.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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
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
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<bean name="/greeting" class="hello.web.GreetingController" />
<!-- ViewResolver -->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
GreetingController 源码如下:
package hello.web;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
public class GreetingController {
@RequestMapping("/greeting")
public String greeting(@RequestParam(value="name", required=false, defaultValue="World") String name, Model model) {
model.addAttribute("name", name);
return "greeting";
}
}
控制器 greeting 返回的字符串就是对应的模板文件,这一般是 jsp WEB-INF/spring-servlet.xml 配置文件中有 ViewResolver 视图控制器,所有不用我们指定模板所在目录和后缀名。
@RequestMapping 注解是 url 路径映射,可以多个。
整合 Spring
至今为止没有让 Spring IOC 和 Spring MVC 发生任何联系(貌似 MVC 可以脱离 Spring 本身独立使用,——这听上去有点不可思议)。事实上,MVC 基本可以不需要 Spring 其他繁杂的包,仅仅依赖下面这些包就可以工作了。
怎么让 Web 服务都受到 Spring IOC 容器管制呢?
在使用 Spring 容器的 web 应用中,业务对象间的依赖关系都可以用 context.xml 文件来配置,并且由 Spring 容器来负责依赖对象的创建。如果要在 servlet 中使用 Spring 容器管理业务对象,通常需要使用 WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext()) 来获得 WebApplicationContext,然后调用 WebApplicationContext.getBean("beanName") 来获得对象的引用,这实际上是使用了依赖查找来获得对象,并且在 servlet 代码中硬编码了应用对象的 bean 名字。为了能在 servlet 中感知 Spring 中 bean,可采用如下步骤来实现:
http://www.open-open.com/lib/view/open1417248512252.html
官方文档:http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html
Spring MVC 用法笔记
为什么 Pojo 的 boolean 获取不到值?
如果你的字段名是 isOnline 以 is 开头的,要把 is 去掉,例如
<div class="row">
是否上线:<label>
上线 <input type="radio" name="online" value="1" ${info.online ? 'checked' : ''} />
</label>
<label>
下线 <input type="radio" name="online" value="0" ${info.online ? 'checked' : ''} />
</label>
</div>
value 用 1 或者 true 皆可。