关闭

SpringMVC CRUD

133人阅读 评论(0) 收藏 举报
分类:

需求说明

某公司有几个部门,每个部门有若干个员工。要求实现添加员工信息,删除员工信息,修改员工信息(lastName字段不可修改),删除员工信息。要求采用REST风格。
这里写图片描述

准备工作

1.把 hello-world例子实现,确保环境搭建好了;
2.写bean:

public class Department {
    private Integer id;
    private String departmentName;

public class Employee {

    private Integer id;
    //@NotEmpty
    private String lastName;

    //@Email
    private String email;
    //1 male, 0 female
    private Integer gender;

    private Department department;
    }

3.写dao,模拟持久层

package com.csu.dao;
//2016年12月26日AdministratorDepartmentDao.java

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.stereotype.Repository;

import com.csu.bean.Department;

@Repository
public class DepartmentDao {

private static Map<Integer, Department> departments = null;

    static{
        departments = new HashMap<Integer, Department>();

        departments.put(101, new Department(101, "D-AA"));
        departments.put(102, new Department(102, "D-BB"));
        departments.put(103, new Department(103, "D-CC"));
        departments.put(104, new Department(104, "D-DD"));
        departments.put(105, new Department(105, "D-EE"));
    }

    public Collection<Department> getDepartments(){
        return departments.values();
    }

    public Department getDepartment(Integer id){
        return departments.get(id);
    }
}
package com.csu.dao;

import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.csu.bean.Department;
import com.csu.bean.Employee;

//2016年12月26日AdministratorEmployeeDao.java
@Repository
public class EmployeeDao {

private static Map<Integer, Employee> employees = null;

    @Autowired
    private DepartmentDao departmentDao;

    static{
        employees = new HashMap<Integer, Employee>();

        employees.put(1001, new Employee(1001, "E-AA", "aa@163.com", 1, new Department(101, "D-AA"), null, null));
        employees.put(1002, new Employee(1002, "E-BB", "bb@163.com", 1, new Department(102, "D-BB"), null, null));
        employees.put(1003, new Employee(1003, "E-CC", "cc@163.com", 0, new Department(103, "D-CC"), null, null));
        employees.put(1004, new Employee(1004, "E-DD", "dd@163.com", 0, new Department(104, "D-DD"), null, null));
        employees.put(1005, new Employee(1005, "E-EE", "ee@163.com", 1, new Department(105, "D-EE"), null, null));
    }

    private static Integer initId = 1006;

    public void save(Employee employee){
        if(employee.getId() == null){
            employee.setId(initId++);
        }

        employee.setDepartment(departmentDao.getDepartment(employee.getDepartment().getId()));
        employees.put(employee.getId(), employee);
    }

    public Collection<Employee> getAll(){
        return employees.values();
    }

    public Employee get(Integer id){
        return employees.get(id);
    }

    public void delete(Integer id){
        employees.remove(id);
    }


}

显示所有员工的信息

1.做页面
做一个表格用来显示。
list.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    记得导入标签!
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<!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>
这里的javascript是为了后面要将POST转PUT用的 ,可以先不要
<script type="text/javascript" src="scripts/jquery-1.9.1.min.js"></script>
<script type="text/javascript">
    $(function(){
        $(".delete").click(function(){
            //alert("click!");
            var href = $(this).attr("href");
            alert(href);
            $("form").attr("action", href).submit();           
            return false;
        });
    })
</script>
</head>
<body>
    <form action="", method="POST">
        <input type="hidden" name="_method" value="DELETE">
    </form>

    <!-- <a href="helloworld">test hello</a> -->
    <c:if test="${empty requestScope.employees }">
        没有任何员工信息.
    </c:if>

    <c:if test="${!empty requestScope.employees }">
        <table border="1" cellpadding="10" cellspacing="0">
            <tr>
                <th>ID</th>
                <th>LastName</th>
                <th>Email</th>
                <th>Gender</th>
                <th>Department</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 == 0 ? 'Female' : 'Male' }</td>
                    <td>${emp.department.departmentName }</td>
                    <td><a href="emp/${emp.id}">Edit</a></td>
                    <td><a class="delete" href="emp/${emp.id}">Delete</a></td>
                </tr>
            </c:forEach>
        </table>
    </c:if>

    <br><br>

    <a href="emp">Add New Employee</a>
</body>
</html>

index.jsp

<a href="showList">showList</a>

2.写Handler
EmployeeHandler.class

@RequestMapping("/showList")
    public ModelAndView showList() {
        ModelAndView modelAndView = new ModelAndView("list");

        //添加模型数据到 ModelAndView 中.
        modelAndView.addObject("employees", employeeDao.getAll());
        //return "list";
        return modelAndView; 
    }

效果
这里写图片描述

新增一个员工

1.做页面
通过 SpringMVC 的表单标签可以实现将模型数据 中的属性和 HTML 表单元素相绑定,以实现表单数据更便捷编辑和表单值的回显。

    1. WHY 使用 form 标签呢 ?
    可以更快速的开发出表单页面, 而且可以更方便的进行表单值的回显
    2. 注意:
    可以通过 modelAttribute 属性指定绑定的模型属性,
    若没有指定该属性,则默认从 request 域对象中读取 command 的表单 bean
    如果该属性值也不存在,则会发生错误。
报错: Neither BindingResult nor plain target object for bean name 'command' available as request attribute。

input.jsp (新增和修改共用一个页面了)

<%@page import="java.util.HashMap"%>
<%@page import="java.util.Map"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    ***记得导入标签!***
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<!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>
pageContext:${pageContext.request.contextPath }
<form:form action="${pageContext.request.contextPath }/emp" method="POST" **modelAttribute="employee"**>
        <c:if test="${employee.id == null }">
        lastName: <form:input path="lastName"/><br><br>
        </c:if>

        <c:if test="${employee.id != null }">
            not empty!
            <form:hidden path="id"/>
            <input type="hidden" name="_method" value="PUT">
        </c:if>

        email: <form:input path="email"/>

        <% 
            Map<String, String> genders = new HashMap();
            genders.put("1", "Male");
            genders.put("0", "Female"); 
            request.setAttribute("genders", genders);
        %><br><br>
        **自动绑定**
        Gender:<form:radiobuttons path="gender" items="${genders }" value=""/><br><br>
        **因为要显示所有部门供选择,座椅点击新增链接时不能直接到页面,必须由handler获取所有部门之后再转向页面。**
        Department:<form:select path="department.id" items="${departments }" itemLabel="departmentName" itemValue="id">
        </form:select><br><br>

        <%-- Birth: <form:input path="birth"/><br><br>

        <br>
        Salary: <form:input path="salary"/><br><br>
        <br> --%>
        <input type="submit" value="Submit"/>
    </form:form>
</body>
</html>

2.写handler

@RequestMapping(value="/emp",method=RequestMethod.PUT)
    public String save(Employee employee) {
        System.out.println(employee);
        employeeDao.save(employee);
        **一般情况下,控制器方法返回字符串类型的值会被当成逻辑视图名处理,如果返回的字符串中带 forward: 或 redirect: 前缀时,SpringMVC 会对他们进行特殊处理:将 forward: 和
redirect: 当成指示符,其后的字符串作为 URL 来处理
redirect:success.jsp:会完成一个到 success.jsp 的重定向的操作 –forward:success.jsp:会完成一个到 success.jsp 的转发操作**
        return "redirect:/showList";
    }

这里写图片描述

修改员工信息

1.回显至编辑页面

<td><a href="emp/${emp.id}">Edit</a></td>
体现rest风格,以前的做法是用问号带参数
    @RequestMapping(value="/emp/{id}",method=RequestMethod.GET)
    public String input(**@PathVariable("id") Integer id**, Map<String,Object> map) {
        System.out.println(id);
        Employee employee=employeeDao.get(id);
        System.out.println(employee);
        map.put("employee", employee);
        map.put("departments", departmentDao.getDepartments());
        return "input";
    }

这里写图片描述
2.提交修改
可以看到 下面这个方法和新增时用的一毛一样的,但是,新增时用的可是PUT,此处用的POST,另外一个区别,save方法里面可是有区分的哦。

@RequestMapping(value="/emp",method=RequestMethod.POST)
    public String save(Employee employee) {
        System.out.println(employee);
        employeeDao.save(employee);
        return "redirect:/showList";
    }
public void save(Employee employee){
        if(employee.getId() == null){
            employee.setId(initId++);
        }
    employee.setDepartment(departmentDao.getDepartment(employee.getDepartment().getId()));
        employees.put(employee.getId(), employee);
    }

由于lastName 字段不可修改,所以在修改时页面上没有lastName的框,那么提交到handler的时候,employee的lastaName是空的,如果不做任何处理,直接替换原来那个employee,那么以后这个employee的lastName字段将一直是空的。
解决方案是,先从数据库里根据ID把employee值给满上,模型数据在这个基础上进行填充。
这里写图片描述
此处可用@ModelAttribute实现,在Handler中加入方法:

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

在请求任何其他handler方法时,都会先执行一下这个方法。
可以看到,该方法传了个id,如果没有写 required=false,并且请求的方法不带id的话,那么会报错。
这样就不担心什么字段是空的了。

删除员工信息

1.需要把GET转POST,POST再转DELETE。(为了优雅的rest 牺牲巨大~)

为实现POST转PUT或者DELETE,必须在web.xml配置:

<!-- 配置 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>
<td><a class="delete" href="emp/${emp.id}">Delete</a></td>
<form action="", method="POST">
        <input type="hidden" name="_method" value="DELETE">
    </form>
<script type="text/javascript">
    $(function(){
        $(".delete").click(function(){
            //alert("click!");
            var href = $(this).attr("href");
            alert(href);
            $("form").attr("action", href).submit();           
            return false;
        });
    })
</script>

以上javascript代码需要引用jquery:

<script type="text/javascript" src="scripts/jquery-1.9.1.min.js"></script>

这个库文件属于静态资源,当客户端请求访问该静态资源辅助实现功能时,遇到web.xml里的

<!-- Map all requests to the DispatcherServlet for handling -->
    <servlet-mapping>
        <servlet-name>springDispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

显然系统把请求静态资源也误以为是请求某一个handler方法,而实际上并没有对应jquery的handler方法,所以会报错。

优雅的 REST 风格的资源URL 不希望带 .html 或 .do 等后缀 •
若将 DispatcherServlet 请求映射配置为 /,则 Spring MVC 将捕获 •
WEB 容器的所有请求,包括静态资源的请求, SpringMVC 会将他
们当成一个普通请求处理,因找不到对应处理器将导致错误。
可以在 SpringMVC 的配置文件中配置

<mvc:annotation-driven></mvc:annotation-driven>

如果不加这一句,静态资源是没问题,但是普通的请求会被玩坏。原因尚不明,待研究。

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:29014次
    • 积分:1083
    • 等级:
    • 排名:千里之外
    • 原创:81篇
    • 转载:11篇
    • 译文:0篇
    • 评论:1条
    最新评论