欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

SpringMVC——RestFul风格的CRUD

程序员文章站 2022-07-15 15:47:43
...

一、基础配置
 1、由于要使用RestFul风格的提交方式,所以要配置HiddenHttpMethodFilter,将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>
<!-- 前端控制器的配置 -->
<servlet>
    <servlet-name>springDispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>springDispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>  

 2、springDispatcherServlet-servlet.xml的配置

<!-- 自动扫面的包 -->
<context:component-scan base-package="com.bdm.springmvc"/>
<!-- 视图解析器 -->
<bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/views/"/>
    <property name="suffix" value=".jsp"/>
</bean>
<!-- 由于要引入jQuery等外部文件,必须有此配置,否则springmvc的视图解析器会将外部文件的引入当成对服务器资源的访问 -->
<mvc:default-servlet-handler/>
<!-- 有了mvc:default-servlet-handler就必须要有这个配置 -->
<mvc:annotation-driven/>  

二、增删改查
 1、查询
  前端:index.jsp

<a href="${pageContext.request.contextPath }/emps">Show Employee List</a>  

  后台方法:

@RequestMapping(value = "/emps", method = RequestMethod.GET)
public String listEmps(Map<String, Object> map) {
    map.put("employees", empDao.getAll());
    return "list";
}  

  结果页面:list.jsp

<c:if test="${requestScope.employees == null }">
    <h2>NOTHING TO SHOW</h2>
</c:if>
<c:if test="${requestScope.employees != null }">
    <table>
        <tr>
            <th>ID</th>
            <th>LastName</th>
            <th>Email</th>
            <th>Gender</th>
            <th>Dept</th>
            <th>Edit</th>
            <th>Delete</th>
        </tr>
        <c:forEach items="${requestScope.employees}" var="emp">
            <tr>
                <td>${emp.id }</td>
                <td>${emp.lastName }</td>
                <td>${emp.email }</td>
                <td>${emp.gender == '1' ? '男' : '女' }</td>
                <td>${emp.department.departmentName }</td>
                <td>
                    <a href="${pageContext.request.contextPath }/emps/${emp.id}">Edit</a>
                </td>
                <td>
                    <a class="delA" href="${pageContext.request.contextPath }/emps/${emp.id}">Del</a>
                       <!-- 这个表单是将delete的get请求转变为DELETE请求需要的 -->
                    <form class="delForm" action="${pageContext.request.contextPath }/emps/${emp.id}" method="post">
                        <input type="hidden" name="_method" value="delete"/>
                    </form>
                </td>
            </tr>
        </c:forEach>
    </table>
    <br/>
    <a href="${pageContext.request.contextPath }/emp">ADD</a>
</c:if>  

 2、添加
  前台:list.jsp

<a href="${pageContext.request.contextPath }/emp">ADD</a>

  后台:点击添加后先转到一个信息填写的表单页面

@RequestMapping(value = "/emp")
public String input(Map<String, Object> map) {
    // 准备回显的数据
    map.put("depts", deptDao.getDepartments());
    map.put("genders", getGenders());
    map.put("employee", new Employee());
    return "input";
}  

  表单填写页面:input.jsp

<form:form action="${pageContext.request.contextPath }/emps" modelAttribute="employee" method="post">
    Name:<form:input path="lastName"/><br/><br/>
    Email:<form:input path="email"/><br/><br/>
    Gender:<form:radiobuttons path="gender" items="${genders }"/><br/><br/>
    Depts:<form:select path="department.id" items="${depts }" itemLabel="departmentName" itemValue="id"/><br/><br/>
    <input type="submit" value="提交">
</form:form>  

  表单填好后的处理:

@RequestMapping(value = "/emps", method = RequestMethod.POST)
public String addEmp(Employee employee) {
    empDao.save(employee);
     //重定向到列表页
    return "redirect:emps";
}  

 3、修改
  请求超链接:

<a href="${pageContext.request.contextPath }/emps/${emp.id}">Edit</a>

  进入修改信息的表单:此处使用了PathVariable风格的url,可以轻松的获取到传递的id

@RequestMapping(value = "/emps/{empId}")
public String edit(@PathVariable("empId") Integer id, Map<String, Object> map) {
    map.put("genders", getGenders());
    map.put("depts", deptDao.getDepartments());
    map.put("employee", empDao.get(id));
    return "edit";
}  

  表单中有个隐藏域保存id的值,还有一个_method隐藏域:

<form:form action="${pageContext.request.contextPath }/emps" modelAttribute="employee" method="post">
    <input type="hidden" name="id" value="${employee.id }"/>
    <input type="hidden" name="_method" value="put"/>
    Name:<form:input path="lastName"/><br/><br/>
    Email:<form:input path="email"/><br/><br/>
    Gender:<form:radiobuttons path="gender" items="${genders }"/><br/><br/>
    Depts:<form:select path="department.id" items="${depts }" itemLabel="departmentName" itemValue="id"/><br/><br/>
    <input type="submit" value="提交">
</form:form> 

  请求的处理:对于修改和删除都需要先根据id到数据库查询要修改或删出的对象,要先调用@ModelAttribute注解的方法,将对象置于隐含域中

@ModelAttribute
public void getEmpById(@RequestParam(value = "id", required = false) Integer id, Map<String, Object> map) {
    if (id != null) {
        Employee emp = empDao.get(id);
        map.put("employee", emp);
    }
}  

  调用完有@ModelAttribute注解的方法后再调用修改的方法:方法和添加很像,只不过method有添加的post变为修改的put

@RequestMapping(value = "/emps", method = RequestMethod.PUT)
public String putEdit(Employee employee) {
    empDao.save(employee);
    return "redirect:emps";
}  

 4、删除
  使用jquery先使原来的删除超链接失效,再让其发送DELETE方式的请求,需要一个提交方式是DELETE的表单辅助

<script type="text/javascript">
    $(function(){
        $(".delA").click(function(){
            var flag = confirm("你真的要删除这个员工的信息吗?");
            if(flag){
                $(".delForm").submit();
            }
            return false;
        });
    })
</script>  
<a class="delA" href="${pageContext.request.contextPath }/emps/${emp.id}">Del</a>
<!-- 这个表单是将delete的get请求转变为DELETE请求需要的 -->
<form class="delForm" action="${pageContext.request.contextPath }/emps/${emp.id}" method="post">
    <input type="hidden" name="_method" value="delete"/>
</form> 

  后台的删除操作:会先调用@ModelAttribute注解的getEmpById()方法将对象置于隐含域中

@RequestMapping(value = "/emps/{empId}", method = RequestMethod.DELETE)
public String delete(@PathVariable("empId") Integer id) {
    empDao.delete(id);
    return "redirect:/emps";
}  

三、总结
 1、流程简易分析
  ①添加:点击超链接->进入handler,准备需在表单中显示的数据(性别、部门、表单中添加时接收参数的对象:不要以为添加时不需要一个对象,因为表单中使用了form:form的modelAttribute属性,该属性的值即是此处置于隐含域中的对象的key,然后表单中的path都指向该对象的属性)->填写好表单后提交到后台调用dao的save方法完成保存,看下表单

<form:form action="${pageContext.request.contextPath }/emps" modelAttribute="employee" method="post">
    Name:<form:input path="lastName"/><br/><br/>
    Email:<form:input path="email"/><br/><br/>
    Gender:<form:radiobuttons path="gender" items="${genders }"/><br/><br/>
    Depts:<form:select path="department.id" items="${depts }" itemLabel="departmentName" itemValue="id"/><br/><br/>
    <input type="submit" value="提交">
</form:form>  

  ②修改和删除:修改和删除的操作执行之前会调用@ModelAttribute注解的方法(实际上只要Handler中有@ModelAttribute注解的方法,则所有请求处理方法都会调用使用@ModelAttribute注解的方法),将要操作的对象根据id查找出来并置于隐含域中(该隐含域的功能有点类似于struts2中的值栈),修改可以先点击超链接进入到一个修改的表单中,将表单的提交方式修改为PUT即可,而对于删除,由于没有一个表单使其发送DELETE方式的请求,所以需要借助于jQuery使原来的超链接失效,转而发送一个表单的DELETE请求(需要一个表单辅助)
  ③查询:略
 2、注意点:
  ①、RestFul风格的请求方式不仅可以根据请求的url区别,还可以根据请求的方式(get、post、put、delete)区别
  ②在引入了外部文件时,必须在springmvc的ioc容器中做如下配置:

<!-- 由于要引入jQuery等外部文件,必须有此配置,否则springmvc的视图解析器会将外部文件的引入当成对服务器资源的访问 -->
<mvc:default-servlet-handler/>
<!-- 有了mvc:default-servlet-handler就必须要有这个配置 -->
<mvc:annotation-driven/>  

  ③在重定向的时候,有时不加/也可以,但是最好加上:return “redirect:/emps”;

Tip:表单中的modleAttribute属性的值并不是随便取的,也不是类名的首字母小写,而是从隐含域中取得的,在进去input.jsp或者edit.jsp等有表单的页面之前,都会调用一个方法,在该方法中会往隐含域中放一个对象用以接收请求参数和回显数据,表单中的modleAttribute属性的值就是此时放入Map或其他隐含域中的键的值,也就是说它只是一个名字而已,必须和放入到隐含域中的对象名一致,否则就会出错。其中的path属性是modleAttribute中的对象的属性名,相当于从这个对象中获取数据,有则回显,没有则不回显。