zoukankan      html  css  js  c++  java
  • 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配置文件上
  • 相关阅读:
    开发必会系列:加密
    开发必会系列:《Java多线程编程实战》读书笔记
    基础教材系列:Linux原理《趣谈linux》极客时间笔记
    安全测试系列:《web安全深度剖析》读书笔记
    基础教材系列:《计算机网络自顶向下方法》读书笔记
    开发必会系列:《spring实战(第4版)》读书笔记
    开发必会系列:《设计模式》读书笔记
    性能测试面试问答:问题定位思路
    linux命令---dstat强大的性能监测工具(通用的系统资源统计工具:可以实时的监控cpu、磁盘、网络、IO、内存等使用情况。)
    Java中System.setProperty()用法
  • 原文地址:https://www.cnblogs.com/zhuxiang1029/p/12989273.html
Copyright © 2011-2022 走看看