Spring MVC---基于注解的控制器
| 基于注解的控制器 |
- SpringMVC是一个基于DispatcherServlet的MVC框架,每个请求最先访问的是DispatcherServlet,DispatcherServlet负责将每一个Request转发到相应的Handler,Handler处理后再返回相应的模型(Model)和视图(View)。在使用注解的Spring MVC中,处理器Handler是基于@Controller和@RequestMapping两个注解的,这两个注解可以提供非常灵活的匹配和处理方式。
| @Controller和@RequestMapping注解 |
- @Controller注解类型
声明一个控制器类,Spring使用扫描机制来找到应用程序中所有基于注解的控制器类,控制器类的内部包含每个动作相应的处理方法,如下是一个@Controller的例子。
package com.example.controller; import org.springframework.web.servlet.mvc.support.RedirectAttributes;
...
@Controller
public class ProductController {
//request-handling methods here
}
为了保证Spring能扫描到控制器类,需要完成两个配置,首先要在Spring MVC的配置文件中声明Spring-context,如下所示:
<beans
...
xmlns:context="http://www.springframework.org/schema/context"
...
>
其次需要应用<component-scan/>元素,在该元素中指定控制器类的基本包。例如所有的控制器类都在com.example.controller及其子包下,则该元素如下:
<context:component-scan base-package="com.example.controller"/>
确保所有控制器都在基本包下,并且不要指定太广泛的基本包,否则会导致Spring MVC扫描无关的包。
- @RequestMapping注解类型
该注解类型在控制器类的内部定义每一个动作相应的处理方法,一个采用@RequestMapping注释的方法将成为一个请求处理方法,并由调度程序在接收到对应的URL请求时调用,下面是一个RequestMapping注解方法的控制器类。
package com.example.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
... @Controller
public class ProductController { @RequestMapping(value="/productInput")
public String inputProduct(){
//do something here
return "ProductForm";
}
}
使用RequestMapping注解的value属性将URL映射到方法,在如上的例子中,我们将productInput映射到inputProduct()方法,通过http://localhost:8081/SpringMVC/productInput访问inputProduct方法。RequestMapping方法除了有value属性外,还有method属性,该属性用来指示该方法仅处理哪些http方法,例如,仅当HTTP POST或PUT方法时,调用下面的processOrder方法。
@RequestMapping(value="/order_process", method={RequestMethod.POST, RequestMethod.PUT})
public String processOrder(){
//do something here
return "OrderForm";
}
如果method属性只有一个HTTP方法值,则无需{},直接为method=RequestMethod.POST,如果未指定method属性,则请求处理方法可以处理任意HTTP方法。此外RequestMapping注释类型也可以用来注释一个控制器类,如下所示:
import org.springframework.stereotype.Controller;
... @Controller
@RequestMapping(value="/customer")
public class CustomerController{
@RequestMapping(value="/delete", method={RequestMethod.POST, RequestMethod.PUT})
public String deleteCustomer(){
//do something here
return ...;
}
}
在这种情况下,所有的方法都将映射为相对于类级别的请求,如例子中的deleteCustomer方法,由于控制器类映射使用"/customer",而deleteCustomer方法映射为"/delete",则需要通过http://localhost:8081/SpringMVC/customer/delete。
| 应用基于注解的控制器 |
本节将通过一个例子说明基于注解的控制器,展示了一个包含两个请求处理方法的控制器类,项目目录结构如下:

我们首先对类进行介绍,Product是产品类,包括产品的名称、描述和价格属性,该类实现了Serializable接口,而ProductForm类与HTML表单相映射,是Product在服务端的代表,表单对象传递ServletRequest给其他组件,还有当数据校验失败时,表单对象将用于保存和展示用户在原始表单上的输入。DBOperator类负责与mysql数据库打交道,ProductService定义了服务层的接口,ProductServiceImpl实现了ProductService中定义的接口。
Product类代码如下,包含属性和属性的set和get方法:
public class Product implements Serializable{
private static final long serialVersionUID = 1L;
private String name;
private String description;
private double price;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public static long getSerialversionuid() {
return serialVersionUID;
}
}
ProductForm代码如下,和Product类唯一区别就是不用实现Serializable接口:
public class ProductForm {
private String name;
private String description;
private double price;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
}
DBOperator类包含两个方法,一个是执行sql语句,一个是从数据库中查询数据:
public class DBOperator {
private JdbcTemplate jdbcTemplate;
//通过setter的方式实现依赖注入
public void setJdbcTemplate(JdbcTemplate jdbcTemplate){
this.jdbcTemplate = jdbcTemplate;
}
public Map query(String sql,int id){
Map productInfo = this.jdbcTemplate.queryForMap(sql, id);
return productInfo;
}
public void insert(String sql,Object[] obj){
this.jdbcTemplate.update(sql, obj);
}
}
服务层的ProductService和实现类ProductServiceImpl如下,ProductServiceImpl类中通过@Autowired和@Service进行DBOperator对象的依赖,@Autowired注解会使DBOperator的一个实例被注入到ProductServiceImpl实例中,为了能是类能被spring扫描到,必须为其标注为@Service。
public interface ProductService {
public Long addProduct(Product product);
public Product queryProduct(long productID);
}
@Service
public class ProductServiceImpl implements ProductService{
//生成产品的ID,是数据库表中的主键
private AtomicLong generator = new AtomicLong();
@Autowired
private DBOperator operator;
@Override
public Long addProduct(Product product) {
// TODO Auto-generated method stub
Long id = generator.incrementAndGet();
String name = product.getName();
String description = product.getDescription();
double price = product.getPrice();
Object[] obj = new Object[]{id,name,description,price};
String sql = "insert into t_product values(?,?,?,?)";
operator.insert(sql,obj);
return id;
}
@Override
public Product queryProduct(long productID) {
// TODO Auto-generated method stub
String sql = "select * from t_product where id=?";
Map productInfo = this.operator.query(sql,(int)productID);
String name = (String) productInfo.get("name");
String description = (String) productInfo.get("description");
double price = (double) productInfo.get("price");
Product product = new Product();
product.setDescription(description);
product.setName(name);
product.setPrice(price);
return product;
}
}
当然最重头戏的还是ProductController类,该类中的方法通过RequestMapping指定Request和Handler的对应关系,而在saveProduct方法的参数中通过RedirectAttribute实现页面的重定向。
@Controller
public class ProductController {
private static final Log logger = LogFactory.getLog(ProductController.class); @Autowired
private ProductService productService; @RequestMapping(value="/productInput")
public String inputProduct(){
//logger.info("inputProduct called");
return "ProductForm";
} @RequestMapping(value="/productSave", method=RequestMethod.POST)
public String saveProduct(ProductForm productForm, RedirectAttributes redirectAttributes){
//logger.info("saveProduct called");
Product product = new Product();
product.setName(productForm.getName());
product.setDescription(productForm.getDescription());
product.setPrice(productForm.getPrice());
//add product
Long productID = productService.addProduct(product);
redirectAttributes.addAttribute("message", "The product was successfully added.");
return "redirect:/product_view/" + productID;
} @RequestMapping(value="/product_view/{id}")
public String viewProduct(@PathVariable Long id, Model model){
Product product = productService.queryProduct(id);
model.addAttribute("product", product);
return "ProductDetails";
}
}
如下是web.xml配置文件,应用servlet和servlet-mapping元素,servlet元素内的<load-on-startup>元素是可选的。如果存在,则它将在应用程序启动时装载servlet并调用它的init方法,若不存在,则在该servlet的第一个请求时加载,可以通过<init-param>中的<param-value>元素指定配置文件的路径,如果没有<init-param>元素,则默认路径为程序的WEB-INF目录下的servletName-servlet.xml。
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<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),其中包括指定控制器类所在的包、默认访问路径请求的html、配置数据源(注意用户名和密码需要改为自己数据库的用户名和密码)通过setter的方式在DBOperator对象中注入jdbcTemplate对象,最后通过viewResolver指定视图文件所在的路径以及后缀。
<?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"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.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
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
<context:component-scan base-package="com.example.controller"/>
<context:component-scan base-package="service"/>
<context:component-scan base-package="mysqloperator"/>
<mvc:annotation-driven/>
<mvc:resources mapping="/*.html" location="/"/>
<!--
<bean name="/productInput" class="Controller.InputProductController"/>
<bean name="/productSave" class="Controller.SaveProductController"/>
-->
<!-- 配置数据源 -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<!-- 数据库驱动 -->
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<!-- 连接数据库的URL 数据库名为已经创建好的User -->
<property name="url" value="jdbc:mysql://localhost/Product"/>
<!-- 连接数据库的用户名 -->
<property name="username" value="root"/>
<!-- 连接数据的密码 -->
<property name="password" value="123"/>
</bean>
<!-- 配置JDBC模板 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!-- 默认必须使用数据源 -->
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="dbOperator" class="mysqloperator.DBOperator">
<property name="jdbcTemplate" ref="jdbcTemplate"/>
</bean>
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp" />
</bean>
</beans>
商品表单视图(ProductForm.jsp)文件如下:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>商品信息</title>
</head>
<body>
<div id="global">
<form action="productSave" method="post">
<fieldset>
<legend>Add a product</legend>
<p>
<label for="name">Product Name:</label>
<input type="text" id="name" name="name" tabindex="1">
</p>
<p>
<label for="description">Description:</label>
<input type="text" id="description" name="description" tabindex="2">
</p>
<p>
<label for="price">Price:</label>
<input type="text" id="price" name="price" tabindex="3">
</p>
<p id="buttons">
<input id="reset" type="reset" tabindex="4">
<input id="submit" type="submit" tabindex="5" value="Add Product">
</p>
</fieldset>
</form>
</div>
</body>
</html>
商品详细信息表单(ProductDetail.jsp)问价如下:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Save Product</title>
</head>
<body>
<div id="global">
<h4>The product has been saved.</h4>
<p>
<h5>Details:</h5>
Product Name: ${product.name }<br />
Description: ${product.description } <br />
Price: $${product.price }
</p>
</div>
</body>
</html>
最后在Tomcat服务器下运行该web程序,报logging版本冲突异常(You have more than one version of 'org.apache.commons.logging.Log' visible,),将导入的jar包中的commons-logging-1.2.jar删除即可,并在浏览器地址栏中输入:http://localhost:8081/SpringMVC/productInput,即可实现对ProductForm.jsp视图的访问,然后输入商品信息,点击Add Product按钮,即可将商品信息添加到数据库(需要提前创建数据库(User)和数据库中的表(t_product(id,name,description,price))),并从数据库中查询插入信息并在ProductDetail.jsp视图中显示。

Spring MVC---基于注解的控制器的更多相关文章
- spring mvc 基于注解的使用总结
本文转自http://blog.csdn.net/lufeng20/article/details/7598801 概述 继 Spring 2.0 对 Spring MVC 进行重大升级后,Sprin ...
- Spring MVC基于注解@Controller和@RequestMapping开发的一个例子
1.创建web项目 2.在springmvc的配置文件中指定注解驱动,配置扫描器 在 Spring MVC 中使用扫描机制找到应用中所有基于注解的控制器类,所以,为了让控制器类被 Spring MVC ...
- spring mvc 基于注解 配置默认 handlermapping
spring mvc 是类似于 Struts 的框架.他们都有一个最主要的功能就是URL路由.URL路由能将请求与响应请求处理逻辑的类(在Struts中即是action,在spring mvc 中即是 ...
- spring MVC之注解开发控制器(二)
开发表单控制器 在传统的Spring MVC开发方法中,是通过扩展SimpleFormController类来创建简单的表单控制器.这样就定义了基本的表单处理流程,并允许通过覆盖几个生命周期方法来定制 ...
- Spring:基于注解的Spring MVC
什么是Spring MVC Spring MVC框架是一个MVC框架,通过实现Model-View-Controller模式来很好地将数据.业务与展现进行分离.从这样一个角度来说,Spring MVC ...
- 基于spring mvc的注解DEMO完整例子
弃用了struts,用spring mvc框架做了几个项目,感觉都不错,而且使用了注解方式,可以省掉一大堆配置文件.本文主要介绍使用注解方式配置的spring mvc,之前写的spring3.0 mv ...
- SpringMVC传统风格控制器和基于注解的控制器
SpringMVC的DispatcherServlet 之前说过springMVC是使用Servlet作为控制器,就是这个用于调度的DispatcherServlet了.这个是servlet,可以根据 ...
- Spring MVC学习总结(2)——Spring MVC常用注解说明
使用Spring MVC的注解及其用法和其它相关知识来实现控制器功能. 02 之前在使用Struts2实现MVC的注解时,是借助struts2-convention这个插件,如今我们使 ...
- springMVC基于注解的控制器
springMVC基于注解的控制器 springMVC基于注解的控制器的优点有两个: 1.控制器可以处理多个动作,这就允许将相关操作写在一个类中. 2.控制器的请求映射不需要存储在配置文件中.使用re ...
随机推荐
- Linux下查看使用频率最高的十个命令
这个shell是在linux吧一个小伙伴发的,链接已找不到,挺有意思的,隔段时间运行一次,可以看看自己最近都干了什么. [shell] history | awk '{CMD[$2]++;count+ ...
- 《Programming Hive》读书笔记(两)Hive基础知识
<Programming Hive>读书笔记(两)Hive基础知识 :第一遍读是浏览.建立知识索引,由于有些知识不一定能用到,知道就好.感兴趣的部分能够多研究. 以后用的时候再具体看.并结 ...
- Android在View拉丝工艺和invalidate()和其他相关方法
转载请注明出处:http://blog.csdn.net/qinjuning 前言: 本文是我读<Android内核剖析>第13章----View工作原理总结而成的,在此膜拜下作者 . ...
- 微软 PowerShell Script Explorer
微软 PowerShell Script Explorer 满血复活,正式发布 一年前的今天,微软在其Windows PowerShell官方博客声明中止 ‘Script Explorer’ 应用程序 ...
- c#后台输出javascript语句和一些通用验证的类
大家在用MVC的时候,经常会用到MODEL层的验证或者是正则表达式,我这边看到了一篇不错的文章,转载过来http://blog.csdn.net/accpxcb/article/details/311 ...
- LaTex代码生成器
latex代码生成器 希腊字母 \alpha \beta \gamma \delta \epsilon \zeta \eta \theta \iota \kappa \lambda \mu \nu \ ...
- html页面显示服务器时间
全局变量 var lblTimer; var d; ready事件里面写 lblTimer = $("#lbltimer"); d = new Date('<%=DateTi ...
- vs2013
vs2013使用初体验 刚安装好vs2013 , 初步体验了一把, 下面是我目前感受到的改变(对比vs2012) 1. 任务栏图标变了 (左边vs2013, 右边vs2012) 2. 开始界 ...
- jQuery获取动态生成的元素
需求描述:页面上可以动态添加数据,比如table,点击按钮可以动态添加行.又或页面 加载时table数据是通过ajax从后台获取的.而这时我们想要获取其中的某个值,又该如何获取呢? 如果是要通过某个事 ...
- 异常信息:java.lang.OutOfMemoryError: PermGen space
修改TOMCAT_HOME/bin/catalina.sh 在"echo "Using CATALINA_BASE: $CATALINA_BASE""上面 ...