SpringMvc---RESTFul风格

SpringMvc---RESTFul

REST:Representational State Transfer,表现层资源状态转移。

RESTFul是一种风格,通过请求方式界定对服务器资源的操作,不使用问号键值对的方式携带参数,而是在URL地址上通过路径的方式告诉服务器要请求的资源和其他参数【前面在学习Request Mapping时学习过,RequestMapping注解支持请求路径中有占位符,比如这样( @Request( /请求路径/{占位符}/{占位符} ) )】

,通过请求方式确定要对资源进行的操作。就是说在收到请求后,拿着请求去controller找对应的方法,根据请求方式找不一样的处理方法。即使所有的请求路径都一样,但是通过请求方式区分它们对资源的操作。

GET请求是请求资源【查】、POST请求是添加资源【增】、PUT请求是更新资源【改】、DELETE请求是删除资源【删】。这是RESTFul风格的规定,使用这个操作资源为了整个程序风格的一致性,这个风格也可以不用,但是现在用这个风格的用的多

将要发送给服务器的数据作为 URL 地址的一部分,以保证整体风格的一致性。

操作传统方式REST风格
查询操作 getUserById?id=1 user/1-->get请求方式
保存操作 saveUser user-->post请求方式
删除操作 deleteUser?id=1 user/1-->delete请求方式
更新操作 updateUser user-->put请求方式

 

使用HiddenHttpMethodFilter

因为浏览器不能发送put和delete请求,所以就需要用到HiddenHttpMethodFilter这个类,通过他的转换就能达到发送put和delete的请求的目标,见名知意,这个FIlter类是用hidden隐藏域完成工作的,怎么完成得看源码。但是在设置这个HiddenHttpMethodFilter时要注意,要把它设置在CharacterEncodingFilter后面,因为Filter执行的顺序是根据在web.xml的注册顺序决定的,在HiddenHttpMethodFilter得到参数后即使设置了字符集也没有用了,就会出现乱码问题。

 

HiddenHttpMethodFilter源码中

在源码中能发现这个HiddenHttpMethodFilter和CharacterEncodingFilter继承的都是OncePerRequestFilter,就是都是处理请求的类,而这个OncePerRequestFilter则是继承了另一个GenericFilterBean【通用过滤器bean】,发现这个GenericFilterBean实现了Filter,对filter的方法进行了处理,实现了init、destory方法,而OncePerRequestFilter继承了GenericFilterBean,里面又实现了doFilter方法。

在HiddenHttpMethodFilter中的doFilterInternal就是处理请求的具体操作

首先,就能看见他在方法里新建了一个HttpRequest对象requestToUse来代替请求传过来的request对象

根据底下的if判断条件就能知道需要请求首先要是POST请求,后面的那个条件不用管。

在执行进if中后,可以看见首先会获取传过来的参数methodParam,发现他是一个常量,值是" _method "

再往下就能看见另一个if的判断是进入一个工具类,具体执行的这个方法的效果就是返回上面得到的请求参数ParamValue,并且判断是否为空。

然后将获取到的请求参数全部大写并传值给定义的一个变量method

然后判断大写后的内容是不是和ALLOWED_METHODS这个list集合中的一个相同【集合中就三个值PUT、DELETE、PATCH】,相同就通过。也说明在post请求传递参数时,参数的name是: _method,value只能是这三个里面的某一个,看到这里就能去用了,首先用form表单提交请求和参数,用hidden隐藏域传递参数名为 _method的参数,让他的值为"put\delete\patch",就能将post请求转化为其中的一个请求方式,进而处理资源

最后调用HttpMethodRequestWrapper【请求 方式封装器】将大写后的请求方式代替请求传递过来时的请求方式

调用DoFilter方法将新创建的请求对象和响应对象放行【传递回去】。

 

这里要好好学习HttpMethodRequestWrapper中的思想

在HttpMethodRequestWrapper类中,他继承了HttpServletRequestWrapper,里面定义了一个method属性,通过有参构造,调用了父类的有参构造,并且把在doFilterInternal方法中处理后的【大写后的method】通过this赋值给类里面的成员变量。最后通过getMethod【这个方法被重写了】把成员变量的那个method返回给上面的方法。总的来说就是偷梁换柱,把本来传过来的post请求换成参数中的_method大写后的结果,最后由新的requestToUse代替之前的request对象方法并在后续的所有处理这个请求的过程中被调用,调用的就是这个替换后的requestToUse。

 

public class HiddenHttpMethodFilter extends OncePerRequestFilter {
    private static final List<String> ALLOWED_METHODS;
    public static final String DEFAULT_METHOD_PARAM = "_method";
    private String methodParam = "_method";
​
    public HiddenHttpMethodFilter() {
    }
​
    public void setMethodParam(String methodParam) {
        Assert.hasText(methodParam, "'methodParam' must not be empty");
        this.methodParam = methodParam;
    }
​
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        HttpServletRequest requestToUse = request;
        if ("POST".equals(request.getMethod()) && request.getAttribute("javax.servlet.error.exception") == null) {
            String paramValue = request.getParameter(this.methodParam);
            if (StringUtils.hasLength(paramValue)) {
                String method = paramValue.toUpperCase(Locale.ENGLISH);
                if (ALLOWED_METHODS.contains(method)) {
                    requestToUse = new HiddenHttpMethodFilter.HttpMethodRequestWrapper(request, method);
                }
            }
        }
​
        filterChain.doFilter((ServletRequest)requestToUse, response);
    }
​
    static {
        ALLOWED_METHODS = Collections.unmodifiableList(Arrays.asList(HttpMethod.PUT.name(), HttpMethod.DELETE.name(), HttpMethod.PATCH.name()));
    }
​
    private static class HttpMethodRequestWrapper extends HttpServletRequestWrapper {
        private final String method;
​
        public HttpMethodRequestWrapper(HttpServletRequest request, String method) {
            super(request);
            this.method = method;
        }
​
        public String getMethod() {
            return this.method;
        }
    }
}

 

 

 

 

web.xml中

<!--注册过滤器,规定字符编码格式-->
<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>forceResponseEncoding</param-name>
        <param-value>true</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>CharacterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
​
​
<!--配置 HiddenHttpMethodFilter -->
<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>

 

 

在controller中

@Controller
public class RestFulController {
​
    @RequestMapping(value = "/testRest_get", method = RequestMethod.GET)
    public String testRest1() {
​
        return "show";
​
    }
​
    @RequestMapping(value = "/testRest_post", method = RequestMethod.POST)
    public String testRest2(String username, String password) {
​
        System.out.println("username:" + username + "," + password);
        return "show";
​
    }
​
    @RequestMapping(value = "/testRest_put", method = RequestMethod.PUT)
    public String testRest3(String username, String password) {
​
        System.out.println("username:" + username + "," + password);
        return "rest_put";
​
    }
​
    @RequestMapping(value = "/testRest_delete", method = RequestMethod.DELETE)
    public String testRest4(String username, String password) {
​
        System.out.println("username:" + username + "," + password);
        return "rest_delete";
​
    }
​
}

 

 

在html中

<form th:action="@{/testRest_put}" method="post">
    <input type="hidden" name="_method" value="PUT"/>
    用户名:<input type="text" name="username"/><br>
    密 码:<input type="password" name="password"/><br>
    <input type="submit" value="put请求提交">
</form>
<form th:action="@{/testRest_delete}" method="post">
    <input type="hidden" name="_method" value="delete"/>
    用户名:<input type="text" name="username"/><br>
    密 码:<input type="password" name="password"/><br>
    <input type="submit" value="delete请求提交">
</form>
 

 

使用RESTFul风格

做一个简单的增删改查,通过请求方式区别操作

首先创建一个空的maven工程,配置pom.xml文件

pom.xml中

pom文件中引入依赖、规定打包方式

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
​
    <groupId>org.example</groupId>
    <artifactId>SpringMvc_03_rest_responseConverter</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>
​
    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
​
    <dependencies>
        <!-- SpringMVC -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.3.1</version>
        </dependency>
​
        <!-- 日志 -->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.3</version>
        </dependency>
​
        <!-- ServletAPI -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>
​
        <!-- Spring5和Thymeleaf整合包 -->
        <dependency>
            <groupId>org.thymeleaf</groupId>
            <artifactId>thymeleaf-spring5</artifactId>
            <version>3.0.12.RELEASE</version>
        </dependency>
​
        <!--解析json的依赖-->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.12.3</version>
        </dependency>
​
    </dependencies>
​
</project>

 

 

IDEA中

配置完了,刷新一下pom文件导入依赖后,进入项目结构中添加web.xml文件,记得把web.xml文件设置一下路径,使它出现在main下的webapp下,没有也不要紧,在设置后IDEA会自动创建,目录和文件。前提是在pom中设置打包方式为war

 

 

 

在web.xml中

在web.xml文件中配置字符编码过滤器、请求转换过滤器、请求控制器,并设置过滤请求的范围、在请求控制器中用初始化参数声明SpringMvc配置文件的位置。

<?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">
<!--设置字符编码过滤器-->
    <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>forceResponseEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
<!--设置请求转换过滤器-->
    <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>DispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:SpringMvc03.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    
    <servlet-mapping>
        <servlet-name>DispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    
</web-app>

 

 

创建SpringMvc的配置文件

在配置文件中添加context、mvc这两个命名空间,开启组件扫描,设置视图解析器,设置视图控制器,开启mvc的注解驱动,开放对静态资源的访问。

<?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 http://www.springframework.org/schema/context/spring-context.xsd
                           http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
​
    <context:component-scan base-package="xlw.com.SpringMvc03"></context:component-scan>
​
    <!-- 配置Thymeleaf视图解析器 -->
    <bean id="viewResolver" class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
        <property name="order" value="1"/>
        <property name="characterEncoding" value="UTF-8"/>
        <property name="templateEngine">
            <bean class="org.thymeleaf.spring5.SpringTemplateEngine">
                <property name="templateResolver">
                    <bean class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">
​
                        <!-- 视图前缀 -->
                        <property name="prefix" value="/WEB-INF/templates/"/>
​
                        <!-- 视图后缀 -->
                        <property name="suffix" value=".html"/>
                        <property name="templateMode" value="HTML5"/>
                        <property name="characterEncoding" value="UTF-8"/>
                    </bean>
                </property>
            </bean>
        </property>
    </bean>
​
    <!--设置视图控制器-->
    <mvc:view-controller path="/" view-name="index"></mvc:view-controller>
​
    <!--开启mvc的注解驱动-->
    <mvc:annotation-driven/>
​
    <!--开启默认的servlet处理器,开放对静态资源的访问-->
    <mvc:default-servlet-handler/>
​
​
</beans>

 

 

创建bean、Dao、Controller

bean中

package xlw.com.SpringMvc03.bean;
​
public class Employee {
​
    private Integer id;
    private String lastName;
​
    private String email;
    //1 male, 0 female
    private Integer gender;
​
    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 Employee(Integer id, String lastName, String email, Integer gender) {
        super();
        this.id = id;
        this.lastName = lastName;
        this.email = email;
        this.gender = gender;
    }
​
    public Employee() {
    }
}

 

 

Dao中

没有链接数据库,用Map做的演示,效果差不多

package xlw.com.SpringMvc03.dao;
​
import org.springframework.stereotype.Repository;
import xlw.com.SpringMvc03.bean.Employee;
​
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
​
@Repository
public class EmployeeDao {
​
    private static Map<Integer, Employee> employees = null;
​
    static{
        employees = new HashMap<Integer, Employee>();
​
        employees.put(1001, new Employee(1001, "E-AA", "aa@163.com", 1));
        employees.put(1002, new Employee(1002, "E-BB", "bb@163.com", 1));
        employees.put(1003, new Employee(1003, "E-CC", "cc@163.com", 0));
        employees.put(1004, new Employee(1004, "E-DD", "dd@163.com", 0));
        employees.put(1005, new Employee(1005, "E-EE", "ee@163.com", 1));
    }
​
    private static Integer initId = 1006;
​
    public void save(Employee employee){
        if(employee.getId() == null){
            employee.setId(initId++);
        }
        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);
    }
}

 

 

Controller中

注入Dao属性

@Controller
public class RestfulController {
​
    @Autowired
    private EmployeeDao employeeDao;
    }

 

 

 

下面的controller处理增删改查的请求是同一个,只是用请求方式区别他们处理资源的方式

 

index.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
</head>
<body>
<h1>hello</h1>
<a th:href="@{/employee}">查看全部员工信息</a>
<a th:href="@{/addEmployee}">添加员工</a>
</body>
</html>

 

 

1)、显示所有数据【GET请求查询】

controller中

首先设置请求映射和请求类别,调用Dao中的方法得到数据,用model作为形参将数据保存起来,在页面通过model保存的数据的key值获取数据并显示出来。

@RequestMapping(value = "/employee",method = RequestMethod.GET)
public String showAllEmployee(Model model){
    Collection<Employee> employees = employeeDao.getAll();
    model.addAttribute("employees",employees);
    return "show";
}
 

 

html中

使用thymeleaf语法中的each进行循环遍历,指定遍历的数据源,用 . 从数据源中取出指定属性,最后显示在页面上

<table id="DataTable" border="1" cellspacing="0" style="text-align: center">
    <tr>
        <th colspan="5">AllEmployees</th>
    </tr>
    <tr>
        <td>id</td>
        <td>lastName</td>
        <td>email</td>
        <td>gender</td>
        <td>操作</td>
    </tr>
    <tr th:each="employee : ${employees}">
        <td th:text="${employee.id}"></td>
        <td th:text="${employee.lastName}"></td>
        <td th:text="${employee.email}"></td>
        <td th:text="${employee.gender}"></td>
        <td>
            <a th:href="">修改</a>
            <a th:href="">删除</a>
        </td>
    </tr>
</table>

 

 

2)、添加内容【POST请求处理添加请求】

在Controller中

有两个方法是因为先要跳转到添加页面,然后再执行表单添加,处理添加操作的方法会接收到很多参数,所以就可以使用实体类获取参数,只要保证参数名和bean中的属性名一致就行。得到参数后用Dao中方法把整个bean装进去。

@RequestMapping("/addEmployee")
    public String toAddEmployee(){
        return "addEmployee";
    }
​
    @RequestMapping(value = "/employee",method = RequestMethod.POST)
//    使用实体类获取表单提交过来的参数,只要保证表单提交的参数名和实体类中的属性名一致就可以
    public String addEmployee(Employee employee){
        employeeDao.save(employee);
//        重定向到显示所有页面查看添加效果
        return "redirect:/employee";
    }

 

 

在html页面中

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>添加</title>
</head>
<body>
<form th:action="@{/employee}" method="post">
  lastName: <input type="text" name="lastName"><br>
  email: <input type="email" name="email"><br>
  gender:<input type="radio" name="gender" value="0">woman</input>
  <input type="radio" name="gender" value="1">man</input>
  <input type="submit" value="确定">
</form>
</body>
</html>
 

 

3)删除内容【DELETE请求处理】

在html中

a)、请求参数的拼接

delete需要返回操作的资源的id进行删除操作,RESTFul风格里面是将参数拼接在路径中,在控制器处理请求映射时用占位符接收参数。所以不能用?或()传递参数。

这时就要用 斜杠请求路径斜杠参数 的形式把参数拼接进路径中传递给控制器方法 这里拼接可以用这种拼接形式: @{斜杠请求路径斜杠}+${参数} ,IDEA中这个加号会显示有错,但是实际使用不影响,就是看着不好看 也可以用这样的: @{单引号斜杠请求路径斜杠单引号+${参数}} ,将请求和参数以路径形式拼接起来 这是thymeleaf的语法

 

b)、delete请求的发送

因为delete请求是通过a标签发送的,a标签又不能直接发送delete请求,需要通过form表单发送post请求传递隐藏域参数_method=delete,由请求转换器将POST请求换为DELETE请求,所以就要通过a标签控制form表单实现请求提交

要使用到vue技术,先去下载一个vue.js包,将他放在webapp下的static-->js目录下【自己建目录,爱叫什么叫什么,但是至少要有一个目录】,然后用script标签引入文件

再重新写一个script标签进行编码

首先建立一个form表单并设置id,再给table标签设置一个id设置为要操作的容器【它包括a标签】,给删除的a标签绑定一个单击事件@Click,在script标签中new一个Vue对象,用el属性找到容器,methods处理当前的事件,再就是处理单击事件。

 

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>操作</title>
</head>
<body>
<table id="DataTable" border="1" cellspacing="0" style="text-align: center">
    <tr>
        <th colspan="5">AllEmployees</th>
    </tr>
    <tr>
        <td>id</td>
        <td>lastName</td>
        <td>email</td>
        <td>gender</td>
        <td>操作</td>
    </tr>
    <tr th:each="employee : ${employees}">
        <td th:text="${employee.id}"></td>
        <td th:text="${employee.lastName}"></td>
        <td th:text="${employee.email}"></td>
        <td th:text="${employee.gender}"></td>
        <td>
            <!--
            RESTFul风格中的参数是以路径的形式拼接实现传参,这时就不能使用问号或者括号传参数,否则控制器方法就拿不到参数
            这时就要用 斜杠请求路径斜杠参数 的形式把参数拼接进路径中传递给控制器方法
            这里拼接可以用这种拼接形式:   @{斜杠请求路径斜杠}+${参数} ,IDEA中这个加号会显示有错,但是实际使用不影响,就是看着不好看
            也可以用这样的: @{单引号斜杠请求路径斜杠单引号+${参数}}  ,将请求和参数以路径形式拼接起来
            这是thymeleaf的语法
            -->
            <a >修改</a>
            <a @click="deleteEmployee" th:href="@{/employee/}+${employee.id}">删除</a>
        </td>
    </tr>
</table>
​
<!--a标签要控制的表单,用来提交delete请求-->
<form id="deleteForm" method="post">
    <input type="hidden" name="_method" value="DELETE">
</form>
​
<!--引入vue.js文件-->
<SCRIPT type="text/javascript" th:src="@{/static/lib/vue.js}"></SCRIPT>
<!--编写代码达成目的-->
<script type="text/javascript">
    new Vue({
        el:"#DataTable",
        methods:{
            deleteEmployee:function (event){
                //根据id找到要操作的表单
                var deleteform = document.getElementById("deleteForm");
                //把超链接点击事件触发后的href属性赋值给from表单的action属性
                deleteform.action = event.target.href;
                //提交表单
                deleteform.submit();
                //取消表单的默认行为
                event.preventDefault();
            }
        }
    })
</script>
​
</body>
</html>

 

 

在controller中

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

 

 

可能出错的地方:由于当前项目使用maven构建,在第一次运行时就把项目以war包的形式打包在tomcat上运行,而中间有添加了static目录和vue.js文件进去,在执行时找不到vue.js文件,这时查看maven实际运行的目录target中发现并没有static目录,所以就要点开maven项目结构,找到当前项目然后打开Lifecycle,双击package,对项目重新打包并再次重新部署到服务器就可以完成请求到处理的过程。如果还有问题去看看SpringMvc的配置文件中有没有打开静态资源访问,这个在上面说过。

 

4)更新内容【PUT请求处理】

在controller中

一个方法处理数据回显,一个处理修改事务

页面回显数据要接收传回来的id,然后根据id查询这一条数据,那查询结果存进model中,在页面通过key值取出数据

这里处理修改后传过来的参数一样是通过bean类来接收参数,然后将整个bean存进去,由于id相同,就会把原来的拿一条记录覆盖掉。

@RequestMapping(value = "employee/{id}",method = RequestMethod.GET)
public String ToUpdateEmployee(@PathVariable("id") Integer id,Model model){
    Employee employee = employeeDao.get(id);
    model.addAttribute("employee",employee);
    return "update";
}
​
@RequestMapping(value = "/employee",method = RequestMethod.PUT)
public String update(Employee employee){
    employeeDao.save(employee);
    return "redirect:/employee";
}
 

 

在html中

展示页面

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>修改页面</title>
</head>
<body>
<form th:action="@{/employee}" method="post">
    <input type="hidden" name="_method" th:value="PUT">
    <input type="hidden" name="id" th:value="${employee.id}">
    lastName:<input type="text" name="lastName" th:value="${employee.lastName}"/><br>
    email:<input type="email" name="email" th:value="${employee.email}"/><br>
    <!--
        th:field="${employee.gender}"可用于单选框或复选框的回显
        若单选框的value和employee.gender的值一致,则添加checked="checked"属性
    -->
    gender:<input type="radio" name="gender" value="1" th:field="${employee.gender}">male
    <input type="radio" name="gender" value="0" th:field="${employee.gender}">female<br>
    <input type="submit" value="update"><br>
</form>
</body>
</html>

 

 

修改请求提交页面

修改要回传参数id,这个请求由控制器方法中的那个转发到回显页面的方法接收,因为a标签是get请求

在RESTFul风格中PUT请求处理修改资源的请求

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>操作</title>
</head>
<body>
<table id="DataTable" border="1" cellspacing="0" style="text-align: center">
    <tr>
        <th colspan="5">AllEmployees</th>
    </tr>
    <tr>
        <td>id</td>
        <td>lastName</td>
        <td>email</td>
        <td>gender</td>
        <td>操作</td>
    </tr>
    <tr th:each="employee : ${employees}">
        <td th:text="${employee.id}"></td>
        <td th:text="${employee.lastName}"></td>
        <td th:text="${employee.email}"></td>
        <td th:text="${employee.gender}"></td>
        <td>
            <!--
            RESTFul风格中的参数是以路径的形式拼接实现传参,这时就不能使用问号或者括号传参数,否则控制器方法就拿不到参数
            这时就要用 斜杠请求路径斜杠参数 的形式把参数拼接进路径中传递给控制器方法
            这里拼接可以用这种拼接形式:   @{斜杠请求路径斜杠}+${参数} ,IDEA中这个加号会显示有错,但是实际使用不影响,就是看着不好看
            也可以用这样的: @{单引号斜杠请求路径斜杠单引号+${参数}}  ,将请求和参数以路径形式拼接起来
            这是thymeleaf的语法
            -->
            <a th:href="@{'/employee/'+${employee.id}}">修改</a>
            <a @click="deleteEmployee" th:href="@{/employee/}+${employee.id}">删除</a>
        </td>
    </tr>
</table>
​
<!--a标签要控制的表单,用来提交delete请求-->
<form id="deleteForm" method="post">
    <input type="hidden" name="_method" value="DELETE">
</form>
​
<!--引入vue.js文件-->
<SCRIPT type="text/javascript" th:src="@{/static/lib/vue.js}"></SCRIPT>
<!--编写代码达成目的-->
<script type="text/javascript">
    new Vue({
        el:"#DataTable",
        methods:{
            deleteEmployee:function (event){
                //根据id找到要操作的表单
                var deleteform = document.getElementById("deleteForm");
                //把超链接点击事件触发后的href属性赋值给from表单的action属性
                deleteform.action = event.target.href;
                //提交表单
                deleteform.submit();
                //取消表单的默认行为
                event.preventDefault();
            }
        }
    })
</script>
​
</body>
</html>

 

 

posted @ 2021-11-21 22:20  优质水  阅读(140)  评论(0)    收藏  举报