04-springMVC(中)

基于spring4

 

 RESTRUL_CRUD_需求(非常重要)

给的工具集:为了方便说明,我们不使用数据库,也不使用aop的事务,用现成的javabean类和dao工具类,里面有数据和具体的增删改查方法。

 

 

 

package com.atguigu.bean;

public class Employee {

    private Integer id;
    private String lastName;

    private String email;
    //1 male, 0 female
    private Integer gender;
    
    private Department department;
    
    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public Integer getGender() {
        return gender;
    }

    public void setGender(Integer gender) {
        this.gender = gender;
    }

    public Department getDepartment() {
        return department;
    }

    public void setDepartment(Department department) {
        this.department = department;
    }

    public Employee(Integer id, String lastName, String email, Integer gender,
            Department department) {
        super();
        this.id = id;
        this.lastName = lastName;
        this.email = email;
        this.gender = gender;
        this.department = department;
    }

    public Employee() {
    }

    @Override
    public String toString() {
        return "Employee [id=" + id + ", lastName=" + lastName + ", email="
                + email + ", gender=" + gender + ", department=" + department
                + "]";
    }
    
    
}
Employee

 

package com.atguigu.bean;

public class Department {

    private Integer id;
    private String departmentName;

    public Department() {
    }
    
    public Department(int i, String string) {
        this.id = i;
        this.departmentName = string;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getDepartmentName() {
        return departmentName;
    }

    public void setDepartmentName(String departmentName) {
        this.departmentName = departmentName;
    }

    @Override
    public String toString() {
        return "Department [id=" + id + ", departmentName=" + departmentName + "]";
    }
    
}
Department

 

package com.atguigu.dao;

import com.atguigu.bean.Department;
import org.springframework.stereotype.Repository;

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


@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();
    }
    //按部门id查一个
    public Department getDepartment(Integer id){
        return departments.get(id);
    }
    
}
DepartmentDao

 

package com.atguigu.dao;

import com.atguigu.bean.Department;
import com.atguigu.bean.Employee;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

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


@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")));
        employees.put(1002, new Employee(1002, "E-BB", "bb@163.com", 1, new Department(102, "D-BB")));
        employees.put(1003, new Employee(1003, "E-CC", "cc@163.com", 0, new Department(103, "D-CC")));
        employees.put(1004, new Employee(1004, "E-DD", "dd@163.com", 0, new Department(104, "D-DD")));
        employees.put(1005, new Employee(1005, "E-EE", "ee@163.com", 1, new Department(105, "D-EE")));
    }
    
    private static Integer initId = 1006;

    /**
     * 员工保存和更新
     * */
    public void save(Employee employee){
        if(employee.getId() == null){
            employee.setId(initId++);
        }
        //根据部门id单独查出部门信息设置到员工对象中,页面提交只需要提交部门的id
        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);
    }
}
EmployeeDao

 

项目要求:

.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 第一步:构建一个框架,先导包,蓝色部分的是第一步导的,剩下那两个等下再导。

1.———— 

 

 

2.————配置web.xml文件。

    1)配置前端控制器 DispatcherServlet。

    2)配置拦截器字符集,utf-8。

    3)配置 HiddenHttpMethodFilter 把 post 请求转为 delete 或 put 请求。

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    <!--配置字符集,拦截器一定在前-->
    <filter>
        <filter-name>characterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>utf-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <!--配置org.springframework.web.filter.HiddenHttpMethodFilter:可以把 post 请求转为 delete 或 put 请求-->
    <!--导包servlet-api.jar-->
    <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>
web.xml

 

3.————由于我没有给DispatcherServlet设置初始化值,所以会自动配置到 "<NAME> - servlet.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:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
    <!--配置自动扫描的包-->
    <context:component-scan base-package="com.atguigu">
    </context:component-scan>
    <!--配置视图解析器:如何把handler方法返回值(本例中就是"success")解析为实际的物理视图-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/views/">
        </property>
        <property name="suffix" value=".jsp">
        </property>
    </bean>
  </beans>
dispatcher-servlet.xml

 

4.————写test包进行测试。

package com.atguigu.test;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * Created by Zhuxiang on 2020/6/2.
 */
@Controller
public class hello2 {
    @RequestMapping("/hello")
    public String hello(){
        System.out.println("hellon world");
        return "success";
    }
}
hello2

加上一个 <a href="/springMVC(web项目名)/hello">hello</a>

写上views里的success.jsp

success.jsp里加上success page这行字。

5.————配置tomcat服务器,启动服务器,进入index.jsp页面后点击a标签

成功进入success页面。测试框架完成。

下图为工程全貌图,可以帮助大家理解步骤。

 

 

第二步:显示所有员工信息

1————index.jsp页面里(在html标签外面)加上<jsp:forward page="/emps"></jsp:forward>转发到控制层,获得所有员工信息。

2————

@Controller
public class EmployeeControl {
    @Autowired
    EmployeeDao employeeDao;

    @RequestMapping("emps")
    public String getEmps(Model model){
        Collection<Employee> all = employeeDao.getAll();
        model.addAttribute("emps",all);
        return "list";
    }

}
EmployeeControl

3————return到list页面。这个时候需要导包

 

 循环获得数据需要用 c 标签里的 c:forEach。

而springmvc也提供了一个form标签,用来简化表单。

(下面代码还写了增,删,改。但目前先看查的部分)

<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<body>
<h1>员工列表</h1>
<table border="1" cellpadding="5" 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="${emps}" var="emp">
        <tr>
            <td>${emp.id}</td>
            <td>${emp.lastName}</td>
            <td>${emp.email}</td>
            <td>${emp.gender==0?"女":"男"}</td>
            <td>${emp.department.departmentName}</td>
            <td>Edit</td>
            <td>
               delete
            </td>
        </tr>
    </c:forEach>
</table>
<a href="">添加</a>
list.jsp

 

启动tomcat,页面上出现

 

 第三步:添加员工信息

 1————点击添加。转发到 'toAddEmp' 方法里,看需求不难发现,部门选择下拉框的值是动态生成的。我们还没学到ajax之前,可以先用老办法,直接查出所有下拉框的值,保存到请求域中,传到 save 页面里。

 加上下面的代码,自动装配。

@Autowired
DepartmentDao departmentDao;

    @RequestMapping("toAddEmp")
    public String toAddPage(Model model){
        Collection<Department> departments = departmentDao.getDepartments();
        model.addAttribute("deps",departments);
        //把command放到请求域中。
//        model.addAttribute("command",new Employee(null,"张三","haha@guigu.com",0,departmentDao.getDepartment(101)));
        //因为form标签给command改了个名字,所以这么放。
        model.addAttribute("employee",new Employee());
        return "save";
    }
EmployeeControl

  2————开始编写 save.jsp 

      要点:

      1.springmvc提供的form标签。

      2.请求域中的固定对象 command

<%--
  Created by IntelliJ IDEA.
  User: Administrator
  Date: 2020/6/3
  Time: 7:15
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<html>
<head>
    <title>save</title>
</head>
<body>
<%--springMVC的表单标签
        通过springMVC的表单标签可以实现将模型数据中的属性和html表单元素相绑定
        以实现表单数据更便捷的编辑和表单值的回显
        1)springmvc认为,表单数据中的每一项最终都是要回显的。
           path指定的是一个属性;这个属性是从隐含模型(请求域中取出的某个对象中的属性)
           path指定的每一个属性,请求域中必须有一个对象,拥有这个属性;
           所以单纯像下面这样写,跑起来就报错了,
           因为请求域里缺少一个对象,这个对象就是请求域中的command,
           由于command是固定名字,不好听,所以我们可以重新命名。用form的modelAttribute属性。
--%>
<!--记得导包jsp-api,action里推荐写绝对路径,下面是获得项目路径的代码-->
<%
    request.setAttribute("project",request.getContextPath());
%>
<form:form action="${project}/emp" method="post" modelAttribute="employee">
    <!-- path就是原来html-input的name项,需要写path,
         1)当做原生的name项
         2)自动回显隐含模型中某个对象对应的这个属性的值
    -->
    LastName:<form:input path="lastName"/><br/>
    Email:<form:input path="email"/><br/>
    gender: <form:radiobutton path="gender" value="1"/><form:radiobutton path="gender" value="0"/><!--
        items指定要遍历的集合:自动遍历,遍历出的每一个元素是一个department对象
        itemLabel="属性";指定遍历出的这个对象的哪个属性是作为option标签体的值
        itemValue="属性";指定遍历出的这个对象的哪个属性是作为option提交的值
    -->
    dept:<form:select path="department.id" items="${deps}"
                      itemLabel="departmentName"
                      itemValue="id"/>
    <input type="submit" value="提交">
</form:form>

<%--<form action="${project}/emp" method="post" modelAttribute="employee">--%>
<%--    LastName:<input type="text" name="lastName">--%>
<%--    <br/>--%>
<%--    Email:<input type="text" name="email">--%>
<%--    <br/>--%>
<%--    Gender:<input type="radio" name="gender" value="1">Male--%>
<%--    <input type="radio" name="gender" value="0">Female--%>
<%--    <br/>--%>
<%--    Department:--%>
<%--    <select name="department.id">--%>
<%--        <c:forEach items="${deps}" var="dept">--%>
<%--            <option value="${dept.id}">${dept.departmentName}</option>--%>
<%--        </c:forEach>--%>
<%--    </select>--%>
<%--    <br/>--%>
<%--    <input type="submit" value="提交">--%>
<%--</form>--%>
</body>
</html>
save.jsp

3————输入信息,点击提交。进入emp映射,为了满足 restful 风格,映射里加上,增加的,method = RequestMethod.POST

    @RequestMapping(value = "emp",method = RequestMethod.POST)
    public String addEmp(Employee employee){
        System.out.println("要添加的员工"+employee);
        employeeDao.save(employee);
        //返回列表页面,重定向到查询所有员工的请求
        return "redirect:/emps";
    }
EmployeeControl

 

第四步:修改员工信息

1————在list页面里点击修改,查询员工再到修改页面 edit.jsp里,(用 rest 风格发送参数,如:emp/${emp.id})

    //查询员工来到修改页面
    @RequestMapping(value = "/emp/{id}",method = RequestMethod.GET)
    public String getEmp(@PathVariable("id") Integer id,Model model){
        Employee employee = employeeDao.get(id);
        model.addAttribute("employee",employee);
        Collection<Department> departments = departmentDao.getDepartments();
        model.addAttribute("departments",departments);
        return "edit";
    }
EmployeeControl

2————编写edit.jsp

      要点:

      1. rest风格,'修改' 为put 。表单必须加上<input type="hidden" name="_method" value="put">。

      2.留下id的隐藏域。

<%--
  Created by IntelliJ IDEA.
  User: Administrator
  Date: 2020/6/3
  Time: 16:19
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%
    request.setAttribute("ctp",request.getContextPath());
%>
<form:form action="${ctp}/emp/${employee.id}" method="post" modelAttribute="employee">
    <input type="hidden" name="_method" value="put">
    <!--如果不加id发送,id的值就是null,最好加上id-->
    <!--但是隐藏域不够安全,浏览器f12加检查元素可以修改,所以lastName就不用隐藏域了-->
    <form:hidden path="id"/>
    Email:<form:input path="email"/><br/>
    gender: <form:radiobutton path="gender" value="1"/><form:radiobutton path="gender" value="0"/>女
    dept:<form:select path="department.id" items="${departments}"
                      itemLabel="departmentName"
                      itemValue="id"/>
    <input type="submit" value="提交">
</form:form>
</body>
</html>
edit.jsp

3————用 rest 风格接收参数   value = "/emp/{id}",method = RequestMethod.PUT

      要点:

      1. 根据题目要求,lastname不允许被修改,但是表单提交又需要它。重要数据最好不要用隐藏域。

          用上@ModelAttribute注解,在每个方法执行之前根据 id 查出employee。

    @ModelAttribute
    public void myModelAttribute(@RequestParam(value = "id",required = false) Integer id,Model model){
        if(id!=null){
            Employee employee = employeeDao.get(id);
            model.addAttribute("employee",employee);
        }
    }

//修改员工并重定向到emps
    @RequestMapping(value = "/emp/{id}",method = RequestMethod.PUT)
    //不用edit.jsp隐藏域 也可以用这种方式获得id
    // 入参加上@PathVariable("id")Integer id会自动装配。
    public String updateEmp(Employee employee){
        System.out.println("update"+employee);
        //但是隐藏域不够安全,浏览器f12加检查元素可以修改,所以lastName就不用隐藏域了
        employeeDao.save(employee);
        return "redirect:/emps";
    }
EmployeeControl

 

第五步:删除员工信息

1————在list页面里点击删除,通过删除方法后,返回到emps里,(用 rest 风格发送参数,如:emp/${emp.id})

       问题:

       1,删除是一个a标签,但是按restful风格,必须要post提交一个 name="_method" value="delete" 的组件。怎么办?

       一,把a标签改成form表单。效果达到了,但是页面变得丑陋,代码臃肿。

       二,引入jQuery。点a标签,1.改变表单的action指向  2.提交表单

 

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

 

<%--
  Created by IntelliJ IDEA.
  User: Administrator
  Date: 2020/6/2
  Time: 22:20
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%
    request.setAttribute("ctp",request.getContextPath());
%>
<html>
<head>
    <title>员工列表</title>
    <!--为了不让delete方法丑陋,加入jQuery -->
    <script type="text/javascript" src="${ctp}/scripts/jquery-1.9.1.min.js"></script>
</head>

<body>
<h1>员工列表</h1>
<table border="1" cellpadding="5" 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="${emps}" var="emp">
        <tr>
            <td>${emp.id}</td>
            <td>${emp.lastName}</td>
            <td>${emp.email}</td>
            <td>${emp.gender==0?"女":"男"}</td>
            <td>${emp.department.departmentName}</td>
            <td><a href="${ctp}/emp/${emp.id}">Edit</a></td>
            <td>
                <a href="${ctp}/emp/${emp.id}" class="delBtn">delete</a>
            </td>
        </tr>
    </c:forEach>
</table>
<a href="${ctp}/toAddEmp">添加</a>

<form:form id="deleteForm" action="${ctp}/emp/${emp.id}" method="post">
    <input type="hidden" name="_method" value="delete">
</form:form>

<!--jQuery默认被servlet的拦截器拦截,说ioc没有对应,所以404。
让它被tomcat拦截就行了 dispatcher-servlet.xml加上映射处理-->
<script type="text/javascript">
    $(function () {
        alert("haha");
        $(".delBtn").click(function () {
            //1.改变表单的action指向
            $("#deleteForm").attr("action", this.href);
            //2.提交表单
            $("#deleteForm").submit();
            return false;
        })
    })
</script>
</body>
</html>
list.jsp

      三,静态资源,动态资源访问问题。

    <!--jQuery默认被servlet的拦截器拦截,说ioc没有对应,所以404。
    让它被tomcat拦截就行了-->
    <!--告诉springMVC,不能处理的映射给tomcat处理-->
    <!--    方法一(不推荐):web里的DispatcherServlet里加上下面的4行就行。-->
    <!--    <servlet-mapping>-->
    <!--        <servlet-name>default</servlet-name>-->
    <!--        <url-pattern>*.js</url-pattern>-->
    <!--    </servlet-mapping>-->

    <!--方法二:(推荐)   default是默认的服务器拦截,不要像一个憨逼一样,把自己配的servlet命名成default-->
    <mvc:default-servlet-handler/>
    <!--静态资源可以访问,但是动态映射的请求就不行(访问list 404)-->

    <!--springMVC保证动态请求和静态请求都能访问-->
    <mvc:annotation-driven/>
加到springmvc配置文件上

 

posted @ 2020-05-29 19:31  天才淇露洛  阅读(125)  评论(0编辑  收藏  举报