Spring RestFul
查询所有用户
@Controller
public class RestFulAction {
@Resource(name="userDao")
private IUserDao dao ;
/**
* 查询所有用户
* @param request请求对象的attributeMap,键为属性名,值为属性值。
* @return 跳转到list页面.jsp
*/
@RequestMapping("/userList")
public String list(Map<String,Object> map
){
List<User> users = dao.getAllUser();
map.put("users", users);
return "list";
}
添加功能的实现
/**
* 注册用户功能输入页面的路径映射,因为跳转过去的user页面使用了form:标签,所以要从控制器跳转过去页面才不会出错
* @param map 请求域对象属性Map
* @return 跳转到注册页面user.jsp
*/
@RequestMapping(value="/user",method=RequestMethod.GET)
public String input(Map<String,Object> map){
map.put("xx", "xx");
map.put("user",new User());
return "user";
}
/**
* 注册页面输入框填写完毕后执行的用户添加到数据库的操作
* @param u 从页面穿过来的包含了User对象各个属性值的参数
* @return 添加成功,重定向到显示用户列表的控制器来跳转到list.jsp页面
*/
@RequestMapping(value="/user",method=RequestMethod.POST)
public String add(
User u
){
dao.addUser(u);
return "redirect:/userList";
}
RestFul删除
SpringMvc静态资源:
1.为什么会有这样的问题:
优雅的Rest风格的资源URL不希望带.html或者.do后缀,若将所有路径映射阻拦,包括静态资源,SpringMvc会将他们当成一个普通请求处理
所以要这么设置;当没有被spring映射当前请求,交给tomcat的defaultServlet来处理即可;
<!-- springMvc会判断是否被映射过,如果有映射过就给个回复,如果没有被映射过(静态资源),
则就去调用tomcat默认的servlet,交由这个default,servlet来处理 default-servlet-name="default"
这个方法主要是用来对付调用静态页面,例如js和html等
-->
<mvc:default-servlet-handler />
删除功能
由于一般只能接收Post和get请求,所以我们需要做一定的转换,讲post或者get转化成delete以及put等表单提交方式;特别是像删除功能,点击超链接来链接到服务器,但是由于==超链接==是get方法,所以我们需要进行一定的转化;
Spring Mvc里面给出的转换方法只有从Post转化到Delete或者Put,在web.xml配置下面一段;
<!-- 配置HiddenHttpMethodFiter:把Post请求转为Delete,Put -->
<filter>
<filter-name>HiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HiddenHttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
接下来的思路就是将get 请求转换成Post请求类型,所以我们要引入一个隐藏表单,表单里面的输入框的值就是要执行的方法;
==_method貌似是spring能识别的RequestMethod参数;
==将这个值设置为Delete,则进行删除;
然后使用java script,点击超链接时提交这个表单
$(function(){
$(".delete").click(function(){
var href = $(this).attr("href")
$("form").attr("action",href).submit()
return false;
});
});
<form action="" method="post">
<input type="hidden" name="_method" value="DELETE"/>
</form>
<td><a class="delete" href="user/${u.id }">删除</a></td>
RestFul修改,表单回填思路
修改东西,则其实就相当于要重新输入一次对象的属性,那么就要到添加页面去执行操作,但是修改需要一个对象的id,所以如果用添加页面的路径映射则不能获取对象现有属性,所以要另外进行==输入页面==的映射,下面做一个添加页面和修改页面的输入路径映射的不同
添加功能的输入页面的映射
/**这个是添加页面,为什么要put一个对象进去呢,因为使用spring的form标签来输出jsp页面的话,需要设定一个modelAttribute表单属性
<form:form action="${pageContext.request.contextPath}/user" method="POST" modelAttribute="user">
那么这样做的表单就需要进入这个jsp页面时有对应的user所指的对象,并且在form表单里面使用的 form空间的path要和该对象的属性名称一致,不然会报错;
map.put("user",new User())相当于传一个空白对象模板过去让用户填写表单
*/
@RequestMapping(value="/user",method=RequestMethod.GET)
public String input(Map<String,Object> map){
map.put("xx", "xx");
map.put("user",new User());
return "user";
}
修改功能的输入页面的映射
@RequestMapping(value="/user/{id}",method=RequestMethod.GET)
public String updateInput(
@PathVariable("id") int id,
Map<String,Object> map
){
map.put("user", dao.getUserById(id));
return "user";
}
修改页面输入完毕后执行修改操作方法
/**
* 判断传过来的东西带不带id,如果带id的话就把页面穿过来的modelAttribute=user对应的对象根据id从数据库中查出来完整的数据
* 就不用在表单域中把每个参数都写上来。
* @param id 对象id
* @param map 请求域map(也是modelAttribute对应的对象),将里面的对象属性使用dao作为原始数据,然后表单传过来的对象属性数据作为修改后的数据,
* 于是在下列修改方法中得到的User u,基本属性是建立与这个u上面,把这个user作为原始数据,
* 然后表单传过来的对象与原本有的u进行比较,看是否有变动的地方,如果有就进行修改,因为ModelAttribute定义在方法上,表名这个方法相当于init(),
* 每个请求进来的时候先执行这个方法 *
*
* @RequestParam(value="id",required=false),这个是传参 当required为false 时 使用这个注解可以不传这个参数 true时必须
*/
@ModelAttribute
public void getUser(@RequestParam(value="id",required=false) Integer id,
Map<String,Object> map
){
if(id!=null){
map.put("user", dao.getUserById(id));
System.out.println("这里是初始化User方法:" + map.get("user"));
}
}
/**
* 修改属性页面填写完毕后所到达的方法,这里配合用ModelAttribute注解的getUser方法来完善穿过来的User 对象的属性,
* @param u 表单提交上来要修改的对象属性,相当于执行了多次u.setXXX
* @return
*/
@RequestMapping(value="/user",method=RequestMethod.PUT)
public String update(
User u
){
System.out.println("这里是修改方法:" + u);
dao.updateUser(u);
return "redirect:/userList";
}
完整的web.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">
<display-name>springmvc</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:config/spring/spring*.xml</param-value>
</init-param>
<load-on-startup></load-on-startup>
</servlet>
<!-- 拦截了所有的uri,包括.js,.html,都当做spring请求来处理js.html称之为静态资源 -->
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- 配置HiddenHttpMethodFiter:把Post请求转为Delete,Put -->
<filter>
<filter-name>HiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HiddenHttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
完整的Spring-core.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<!-- 扫描spring注解 -->
<context:component-scan base-package="com.wang"></context:component-scan>
<!-- springMvc会判断是否被映射过,如果有映射过就给个回复,如果没有被映射过(静态资源),
则就去调用tomcat默认的servlet,交由这个default,servlet来处理 default-servlet-name="default"
-->
<mvc:default-servlet-handler />
<!-- MVC注解驱动,挂载自动转换器 -->
<mvc:annotation-driven conversion-service="tcs"
validator="localValidator" />
<!-- 提供事务注解支持 -->
<tx:annotation-driven transaction-manager="transactionManager" />
<!-- 配置 -->
<!-- 读取硬盘上的项目目录中的配置文件 -->
<bean
class="org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:database.properties</value>
</list>
</property>
</bean>
<!-- 数据源(第三方dhcp数据源连接池) -->
<bean id="dbcp_dateSource" class="org.apache.commons.dbcp.BasicDataSource">
<!-- 通过${driver}获取配置信息,还需要从本地读取配置文件 -->
<property name="driverClassName" value="${driver}"></property>
<property name="url" value="${url}"></property>
<property name="username" value="${username}"></property>
<property name="password" value="${password}"></property>
<property name="defaultAutoCommit" value="false"></property>
<property name="initialSize" value="5"></property>
</bean>
<!-- 基于hibernate的Session工厂 -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<!-- 数据源,在这里使用了第三方的连接池当做数据源 ,该参考类要实现了sql.dateSource接口 -->
<property name="dataSource" ref="dbcp_dateSource">
</property>
<!-- 将hibernate的设置参数引入Spring配置,如此就不用单独设置hibernate配置文件 -->
<property name="hibernateProperties">
<props>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
</props>
</property>
<!-- 要扫描的包,导入包内注解好映射的实体类 -->
<property name="packagesToScan" value="com.wang.model"></property>
</bean>
<!-- Hibernate事务管理器的配置 -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<!-- 日期转换器 -->
<bean id="tcs"
class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<list>
<bean class="com.wang.conversion.DateConverter">
<!-- set注入一个日期格式化工具 -->
<property name="sdf">
<!-- 该工具是一个SimpleDateFormat类 -->
<bean class="java.text.SimpleDateFormat">
<!-- 该格式化工具创建时使用构造器注入,加入格式 -->
<constructor-arg value="yyyy-MM-dd"></constructor-arg>
</bean>
</property>
</bean>
<!-- 另一种方法 <bean class="com.wang.conversion.DateConverter"> </bean> -->
</list>
</property>
</bean>
<!-- 验证器 -->
<bean id="localValidator"
class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
<property name="validationMessageSource" ref="messageSource"></property>
</bean>
<!-- 文件上传支持 -->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 文件最大大小byte -->
<property name="maxUploadSize" value="10200000"></property>
</bean>
<!-- jsp参数配置 -->
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<!-- 自定义全局异常处理 -->
<!-- 国际化 -->
<bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="res.app.app_res"></property>
</bean>
</beans>
完整的一个RestFul风格增删改查Handle(也叫Action,Servlet)
package com.wang.action;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import com.wang.dao.IUserDao;
import com.wang.model.User;
@Controller
public class RestFulAction {
@Resource(name="userDao")
private IUserDao dao ;
/**
* 查询所有用户
* @param request请求对象的attributeMap,键为属性名,值为属性值。
* @return 跳转到list页面.jsp
*/
@RequestMapping("/userList")
public String list(Map<String,Object> map
){
List<User> users = dao.getAllUser();
map.put("users", users);
return "list";
}
/**
* 注册用户功能输入页面的路径映射,因为跳转过去的user页面使用了form:标签,所以要从控制器跳转过去页面才不会出错
* @param map 请求域对象属性Map
* @return 跳转到注册页面user.jsp
*/
@RequestMapping(value="/user",method=RequestMethod.GET)
public String input(Map<String,Object> map){
map.put("xx", "xx");
map.put("user",new User());
return "user";
}
/**
* 注册页面输入框填写完毕后执行的用户添加到数据库的操作
* @param u 从页面穿过来的包含了User对象各个属性值的参数
* @return 添加成功,重定向到显示用户列表的控制器来跳转到list.jsp页面
*/
@RequestMapping(value="/user",method=RequestMethod.POST)
public String add(
User u
){
dao.addUser(u);
return "redirect:/userList";
}
/**
* 删除功能的实现,只有_method参数为DELETE才能执行本方法
* @param id 需要删除的对象id
* @return 重定向到用户列表
*/
@RequestMapping(value="/user/{id}",method=RequestMethod.DELETE)
public String delete(
@PathVariable("id") int id
){
dao.deleteUser(id);
return "redirect:/userList";
}
/**
* 从用户列表点击修改所去的填写修改属性的页面,但是由于页面不一定是每个属性都要修改,所以传过去的对象属性不一定全部都会取出来
* @param id 绑定在超链接里面穿过来的id
* @param map 请求域对象属性集合
* @return 修改用户资料界面user.jsp,因为这个jsp页面使用了form:标签,所以实现了自动读取请求域中蕴含对象属性值的功能,表单回填的思路也基于此
*/
@RequestMapping(value="/user/{id}",method=RequestMethod.GET)
public String updateInput(
@PathVariable("id") int id,
Map<String,Object> map
){
map.put("user", dao.getUserById(id));
return "user";
}
/**
* 判断传过来的东西带不带id,如果带id的话就把页面穿过来的modelAttribute=user对应的对象根据id从数据库中查出来完整的数据
* 就不用在表单域中把每个参数都写上来。
* @param id 对象id
* @param map 请求域map(也是modelAttribute对应的对象),将里面的对象属性使用dao作为原始数据,然后表单传过来的对象属性数据作为修改后的数据,
* 于是在下列修改方法中得到的User u,基本属性是建立与这个u上面,把这个user作为原始数据,
* 然后表单传过来的对象与原本有的u进行比较,看是否有变动的地方,如果有就进行修改,因为ModelAttribute定义在方法上,表名这个方法相当于init(),
* 每个请求进来的时候先执行这个方法 *
*
* @RequestParam(value="id",required=false),这个是传参 当required为false 时 使用这个注解可以不传这个参数 true时必须
*/
@ModelAttribute
public void getUser(@RequestParam(value="id",required=false) Integer id,
Map<String,Object> map
){
if(id!=null){
map.put("user", dao.getUserById(id));
System.out.println("这里是初始化方法:" + map.get("user"));
}
}
/**
* 修改属性页面填写完毕后所到达的方法,这里配合用ModelAttribute注解的getUser方法来完善穿过来的User 对象的属性,
* @param u 表单提交上来要修改的对象属性,相当于执行了多次u.setXXX
* @return
*/
@RequestMapping(value="/user",method=RequestMethod.PUT)
public String update(
User u
){
System.out.println("这里是修改方法:" + u);
dao.updateUser(u);
return "redirect:/userList";
}
}
完整的一个 注册,修改用户的form标签的使用页面
<%@page import="java.util.Map"%>
<%@page import="java.util.HashMap"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<!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>Insert title here</title>
</head>
<body>
<!-- 1.why使用form标签
可以更快速的开发出表单页面,而且可以更方便的进行表单的回显;
2:可以通过modelAttrbute属性制定绑定的模型属性,
若没有制定该属性,则默认从request对象中读取command的表单bean
如果该属性值也不存在,则会发生错误
3modelAttribute和map里面放的"user"一致,必须存在这么一个对象
如果有跨对象,对象里面嵌套对象,可以这样写,user.deparment.id
-->
<form:form action="${pageContext.request.contextPath}/user" method="POST" modelAttribute="user">
<!-- path属性对应html表单的标签的name属性值 -->
<c:if test="${user.id == null }">
登录名<form:input path="name"
/><br>
</c:if>
<c:if test="${user.id != null }">
<form:hidden path="id"/>
<!-- 为什么不用form标签的hidden,因为modelAttrbibute对应的对象中没有_method这个属性 -->
<input type="hidden" name="_method" value="PUT">
</c:if>
密码<form:input path="password"/><br>
生日<form:input path="birthday"/><br>
<%
Map<String,String> gender = new HashMap();
gender.put("1", "男");
gender.put("0","女");
request.setAttribute("sex", gender);
%>
<!-- delimiter表示分隔符,可以用"<br>"来换行 -->
性别<form:radiobuttons path="sex" items="${sex}"/><br>
<!-- 下拉列表 注意,使用了form:标签,注释的话也会来识别你注释的代码是不是有写错了。
<form:select path="department.id" items="${departments }" itemLabel="departmentName" itemValue="id">
</select>
-->
<input type="submit" value="提交">
</form:form>
</body>
</html>