一、应用@Autowired和@Service进行依赖注入
将依赖注入到Spring MVC控制器最简单的方法是通过注释@Autowired到字段或方法。
为了能作为依赖注入,类一定要声明成@Service,它表示类是一个服务。另外在配置文件中还要添加一个
<component-scan />元素来扫描依赖基本包。
<context: component-scan basepackage="dependencyPackage"/>
二、重定向和Flash属性
转发与重定向的不同:转发更快,因为重定向要经过客户端,而转发没有。
但是有时候用重定向更好,若要重定向到一个外部的网站,转发无法实现。
使用重定向不方便的一个地方是,不能轻松的传值给目标页面,而转发则可以简单的将属性添加到Model中,使目标视图可以文章。由于重定向经过了客户端,所以Model中的值在重定向时
丢失了。但是我们在Spring 3.1和更新的版本中,可以用Flash属性来进行重定向传值。
这里,我们在Spring MVC文件中要配置一个<annotation-driven/>元素,然后,还要在方法上添加一个新的参数类型RedirectAttribute.
三、请求参数和路径变量
请求参数与路径变量都可以用来发送值到服务器。二者都是URL的一部分。
- 请求参数
采用 key= value的形式,并用&分隔。如下带有一个productId的请求参数。
http://localhost:8080/app04b/product_retrive?productId=3
在传统的方法中,我们用下面的方法来得到一个请求参数的值。
String productId=httpServletRequest.getParmeter("productId");
在Spring MVC中,我们有更简单的方法来得到请求参数的值:通过 RequestParam注释类型来注释方法参数 。如下
public void sendProduct(@RequestParam int productId )
@RequestParam注解的参数不一定是字符串。
- 路径变量
类似请求变量,但是没有key部分,只是一个值。如在app04bk ,
/product_view/productId
其中productId用来表示产品标识符的一个整数,用来发送一个值到服务器。
@RequestMapping (value ="/product_view/{id}") public String viewProduct(@PathVariable long id ,Model model){ Product product = productService.get(id); model.addAttribute("product",product); return "ProductView"; }
为了使用路径变量,我们先在RequestMapping注解的值属性中添加一个变量。上面的例子中定义了一个名为id的路径变量。
然后在方法签名中添加同名的变量,并加上@PathVariable注解,当这个方法被调用的时候,请求URL的id 值将复制到路径变量中,这样就可以在方法中使用。路径变量的类型可以不是字符串,
Spring MVC将尽力转换成非字符串类型。
可以在请求中使用多个路径变量,如下
@RequestMapping (value="/product_view/{userId}/{orderId}")
有时候使用路径变量,浏览器会误解路径变量,略。
四、@ModelAttribute
前面说到,Spring MVC在每次调用 请求处理方法时,都会创建Model类型的一个实例 。如果我们要用这个实例,可以在方法中添加一个 Model类型的参数。还可以使用在方法中添加添加
ModelAttribute注释类型来访问Model实例。
1. 带@ModelAttribute注解的方法会将它输入的或者创建的参数对象添加到Model对象中(若方法中没有显式的添加)
如下
@RequestMapping (method=RequestMethod.POST) public String submitOrder(@ModelAttribute("newOrder") Order order, Model model) { .... }
输入或者创建的Order实例将用newOrder键值添加到Model对象中,如果没有key,则使用这个对象类型的名字。如下面的会使用key="order"将Order实例添加到Model对象中。
public String submitOrder(@ModelAttribute Oder order, Model model)
2. @ModelAttribute 的第二个用处是标注一个非请求的处理方法
被@ModelAttribute标注的方法会在每次调用 这个控制器的请求处理方法前被调用,被标注的方法可以返回
> 一个对象
如果返回一个对象,则返回的对象会自动添加到Model中。如
@ModelAttribute public Product addProduct(@RequestParam String productId){ return productSerivce.get(productId); }
> void 类型
这里,一定要添加一个Model类型的参数,并自行将实例添加到Model中。如下
@ModelAttribute public void populateModel(@RequestParam String id ,Model model){ model.addAttribute(new Account(id)); }
五、例子
- 工程目录
- Controller代码
@Controller public class ProductController { private static final Log logger = LogFactory.getLog(ProductController.class) ; //使ProductService的一个实例注入到里面,所以后面可以直接用了 @Autowired private ProductService productService ; @RequestMapping(value="/product_input") public String inputProduct(){ logger.info("inputProduct called"); return"ProductForm" ; } @RequestMapping(value ="/product_save" , method=RequestMethod.POST) public String saveProduct(ProductForm productForm , RedirectAttributes redirectAttributes){ logger.info("saveProduct called"); //no need to create and instantiate a ProductForm //create product Product product = new Product() ; product.setName(productForm.getName()); product.setDescription(productForm.getDescription()) ; try { product.setPrice(Float.parseFloat(productForm.getPrice())); } catch (NumberFormatException e) { e.printStackTrace(); } // add product using Flash Product savedProduct = productService.add(product) ; redirectAttributes.addFlashAttribute("message", "the product was added ok") ; //重定向 return "redirect:/product_view/"+savedProduct.getId() ; } @RequestMapping(value="/product_view/{id}") public String viewProduct(@PathVariable Long id , Model model){ Product product = productService.get(id) ; //添加要在视图中显示的属性 model.addAttribute("product", product) ; return "ProductView"; } }
- ProductService
提供一个各种处理产品方法的接口
public interface ProductService { Product add(Product product) ; Product get(long id) ; }
- ProductServiceImpl
//使类可以被扫描到,表示类是一个服务 @Service public class ProductServiceImpl implements ProductService { private Map<Long ,Product> products= new HashMap<Long, Product>() ; private AtomicLong generator = new AtomicLong() ; public ProductServiceImpl (){ Product product = new Product() ; product.setName("JX1 power drill"); product.setDescription("powerful and drill"); product.setPrice(129.9F); add(product) ; } @Override public Product add(Product product) { long newId = generator.incrementAndGet() ; product.setId(newId); products.put(newId, product) ; return product; } @Override public Product get(long id) { return products.get(id); } }
- web.xml文件
<?xml version="1.0" encoding="UTF-8"?> <web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/config/springmvc-config.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
- springmvc-config.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:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!--一个用于扫描控制器类,一个用于扫描服务类 --> <context:component-scan base-package="app04b.controller"/> <context:component-scan base-package="app04b.service"/> <mvc:annotation-driven/> <mvc:resources mapping="/css/**" location="/css/"/> <mvc:resources mapping="/*.html" location="/"/> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/"/> <property name="suffix" value=".jsp"/> </bean> </beans>
- ProductView.jsp
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <!DOCTYPE HTML> <html> <head> <title>View Product</title> <style type="text/css">@import url("<c:url value="/css/main.css"/>");</style> </head> <body> <div id="global"> <h4>${message}</h4> <p> <h5>Details:</h5> Product Name: ${product.name}<br/> Description: ${product.description}<br/> Price: $${product.price} </p> </div> </body> </html>