SpringMVC

1、SpringMVC概述

1.1 回顾MVC设计模式

1.1.1 MVC的概念

一种Web和桌面应用主流的设计模式

M(Model模型)负责数据访问、业务逻辑(dao、service、entity)
​
V(View视图)负责和用户交互、展示数据(页面)
​
C(Controller控制器)负责调用模型、更新视图(servlet-->Controller)

作用:解耦,便于开发和维护

1.1.2 MVC的执行流程

1)用户来访问视图,如:在商品页面点击查看商品的详情
2)视图将请求发送给控制器,控制器调用模型查询商品数据
3)模型将查询到的数据绑定到详情页面上,控制器使页面跳转到详情页面
4)用户看到商品的详情

1.2 Struts2.0和SpringMVC的区别

1.2.1 MVC框架的演变

最早的MVC架构是:Servlet + JSP + JavaBean,这种方式开发项目比较复杂,管理起来很不方便,所以渐渐出现了MVC的框架。早期比较流行的框架是:Struts,Struts从1.0发展为了2.0,后来Spring推出的SpringMVC框架由于更加优秀,慢慢的代替了Struts框架。

1.2.2 Struts2.0和SpringMVC的区别

  1. 实现机制 SpringMVC基于Servlet机制,而Struts2基于Filter机制

  2. 拦截机制 SpringMVC是方法级别拦截,每个请求对应一个方法; Struts2是类级别的拦截,每个请求对应一个Action类; SpringMVC执行速度更快

  3. 集成 SpringMVC是Spring体系中的,配置起来更容易,而Struts2需要更多的配置

2、入门案例

1)导入SpringMVC依赖

<!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-webmvc</artifactId>
  <version>5.2.8.RELEASE</version>
</dependency>

2)Spring配置文件

<?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.blb.mvc"></context:component-scan>
        <!--视图解析器 帮助查找视图文件的位置 index 转换为 /WEB-INF/pages/index.jsp -->
        <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <!--配置视图的前缀-->
            <property name="prefix" value="/WEB-INF/pages/"></property>
            <!--配置视图的后缀-->
            <property name="suffix" value=".jsp"></property>
        </bean>
        <!--处理静态资源-->
        <mvc:default-servlet-handler/>
        <!--启动注解配置-->
        <mvc:annotation-driven/>
</beans>

3) web.xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         id="WebApp_ID" version="3.1">
  <display-name>Archetype Created Web Application</display-name>
  <!--配置核心控制器-->
  <servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <!--springmvc的配置文件路径-->
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:spring-mvc.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>

4) 控制器

 /**
      * 自定义控制器
      */
  	  @Controller
      public class MyController {
    
          //配置请求的URL路径/index,请求方法是GET
          @RequestMapping(value = "/index",method = RequestMethod.GET)
          public String toIndex(){
              //视图解析器 : index --> /WEB-INF/page/index.jsp
              return "index";
          }
    
      }

 5) 配置Tomcat运行效果

3、SpringMVC执行流程

1) 用户发送请求

2)前端控制器获得用户请求的URL,发送URL给处理器映射

3)处理器映射将Handler(包装方法信息)返回给前端控制器

4)前端控制器发送Handler给处理器适配器,适配器执行Handler方法

5)执行Handler方法后,返回ModelAndView(逻辑视图)给前端控制器

6)前端控制器将ModelAndView发送给视图解析器,解析出物理视图返回给前端控制器

7)前端控制器渲染视图,发送视图给用户

4、参数处理

4.1 SpringMVC的常用注解

这里介绍几个SpringMVC常用的注解:

  • @Controller 配置控制器类

  • @RequestMapping("URL") 配置请求方法

    属性:

    value 配置请求的URL

    method 配置请求的方法,值包含RequestMethod.GET、RequestMethod.POST等

  • @GetMapping("URL") 配置GET请求方法

    相当于@RequestMapping(value="URL",method=RequestMethod.GET)

    类似的还有:@PostMapping、@DeleteMapping、@PutMapping

  • @RequestParam("名称") 配置请求参数

  • @PathVariable("名称") 配置路径参数

4.2 参数绑定

登录页面

实现参数绑定有多种方式。

​
<html>
<head>
    <title>登录</title>
</head>
<body>
    <span style="color:red">${msg}</span>
    <form action="/user/login" method="post">
        <input name="username" placeholder="请输入用户名"><br>
        <input name="password" placeholder="请输入密码"><br>
        <input type="submit" value="登录">
    </form>
</body>
</html>

​

4.2.1 参数直接绑定

直接定义和表单元素name相同的参数

@Controller
@RequestMapping("user")
public class UserController {

    @PostMapping("/login")
    public void login(String username, String password){...}
}

4.2.2 @RequestParam注解绑定参数

如果名称不一样,可以通过@RequestParam注解配置参数

@PostMapping("/login")
public void login(@RequestParam("username")String uname, 
	@RequestParam("password")String pwd){
	...
}

4.2.3 对象绑定参数

通过对象也可以进行参数绑定 实体类

public class User {

    private String username;
    private String password;
    ...
}

方法定义

@PostMapping("/login")
public void login(User user){
	...
}

4.2.4 @PathVariable绑定参数

通过URL的路径也可以实现参数绑定,需要给参数添加@PathVariable注解

在URL中可以使用{name}来定位参数的位置,name是@PathVariable注解中配置的名称

@GetMapping("/login/{username}/{password}")
public void login(@PathVariable("username")String username,
					@PathVariable("password")String password){
    System.out.println(username);
    System.out.println(password);
}

在浏览器输入:http://localhost:8080/user/login/admin/123456

可以看到账号和密码的输出,当然登录不适合将账号和密码添加到URL中,这里只是测试

4.2.5 通过Map集合进行参数绑定

在实体类中添加Map集合

public class UserVO {

    private Map<String,String> user = new HashMap<>();
    //get、set
}

修改表单name为: 集合名[‘属性名’]

<input name="user['username']" placeholder="请输入用户名"><br>
<input name="user['password']" placeholder="请输入密码"><br>

修改方法

@PostMapping("/login")
public void login(UserVO userVO){
    String username = userVO.getUser().get("username");
    String password = userVO.getUser().get("password");
}

4.2.6 通过List集合进行参数绑定

修改集合为List

public class UserVO {

    private List<String> user = new ArrayList<>();
    //get、set
}

修改表单name为: 集合名[下标]

<input name="user[0]" placeholder="请输入用户名"><br>
<input name="user[1]" placeholder="请输入密码"><br>

修改方法

@PostMapping("/login")
public void login(UserVO userVO){
    String username = userVO.getUser().get(0);
    String password = userVO.getUser().get(1);
}

4.3 参数绑定的中文乱码问题

SpringMVC提供了过滤器来设置编码 在web.xml中配置

<!--编码过滤器-->
<filter>
    <filter-name>encodingFilter</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>encodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

4.4 自定义类型转换器

在进行参数绑定时,会自动完成完成基本类型(如byte、short、 int、long、float、double、boolean 、char )以及String类型的数据转换。

因为SpringMVC提供了大量内置的类型转换器Converter,来帮助进行参数在类型转换,如果我们需要完成某些特殊的数据格式的处理,就需要自定义类型转换器。

案例:表单输入id-name-age-subject格式的字符串,绑定到Student类型的参数。

实体类

public class Student {

    private Long id;
    private String name;
    private Integer age;
    private String subject;
    ...get/set
 }

自定义转换器

/**
 * 学生类型转换器,将id-name-age-subject格式字符串转换为Student对象
 */
public class StudentConverter implements Converter<String, Student> {

    @Override
    public Student convert(String s) {
        //按-分割字符串
        String[] strings = s.split("\\-");
        if(strings.length != 4){
            throw new IllegalArgumentException("字符串不符合学生信息格式要求");
        }
        //返回Student对象
        Student student = new Student();
        student.setId(Long.valueOf(strings[0]));
        student.setName(strings[1]);
        student.setAge(Integer.valueOf(strings[2]));
        student.setSubject(strings[3]);
        return student;
    }
}

注册转换器,修改springmvc的annotation-driver配置

<!--注册类型转换器-->
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
    <property name="converters">
        <list>
            <bean class="com.blb.mvc.converter.StudentConverter"/>
        </list>
    </property>
</bean>
<mvc:annotation-driven conversion-service="conversionService"/>

控制器

@PostMapping("/saveStudent")
public void saveStudent(Student student){
    System.out.println(student.getId());
    System.out.println(student.getName());
    System.out.println(student.getAge());
    System.out.println(student.getSubject());
}

页面

<form action="/saveStudent" method="post">
    <input name="student" placeholder="请输入学生信息"><br>
    <input type="submit" value="提交">
</form>

5、页面数据绑定

5.1 EL实现后台数据绑定

在JSP页面中可以通过EL表达式来绑定后台的数据,后台数据可以保存到:

  1. 将数据保存到HttpServletRequest、HttpSession、ServletContext中

  2. 在参数中定义Model参数保存数据

  3. 在参数中定义Map参数保存数据

5.2 页面跳转

页面跳转的两种方式:

  1. 请求转发

    forward:url

  2. 重定向

    redirect:url

5.3 登录案例

首页

<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
    <title>首页</title>
</head>
<body>
    <h1>Hello ${user.username}你好</h1>
</body>
</html>

模拟登录,使用User来获得参数,保存User对象到HttpSession,重定向到首页后,可以从首页读取用户名;

保存错误信息到Model对象中,请求转发到登录页面后,可以读取Model中的数据

@PostMapping("/login")
public String login(User user,HttpSession session,Model model){
    if("admin".equals(user.getUsername()) && "123".equals(user.getPassword())){
        //保存用户数据到Session中
        session.setAttribute("user",user);
        //重定向到首页
        return "redirect:/index";
    }
    //保存错误提示数据到Model
    model.addAttribute("msg","账号或密码错误");
    //请求转发到当前页
    return "forward:/login";
}

5.4 处理ServletAPI

SpringMVC还支持以原生ServletAPI作为形参,包括:

  • HttpServletRequest

  • HttpServletResponse

  • HttpSession

  • java.security.Principal

  • Local

  • InputStream

  • OutputStream

  • Reader

  • Writer

使用HttpServletRequest获得参数,将用户名保存到Session中

@PostMapping("/login")
public String login(HttpServletRequest req,HttpSession session){
    String username = req.getParameter("username");
    String password = req.getParameter("password");
    session.setAttribute("username",username);
    return "redirect:/test";
}

@SessionAttribute

通过@SessionAttribute注解,可以读取Session中的用户名

@PostMapping("/test")
public String test(@SessionAttribute("username")String username){
    System.out.println(username);
    return "/index";
}

@ModelAttribute

@ModelAttribute可以将模型数据注入到方法参数中

定义方法,在方法上加@ModelAttribute,将返回的User对象作为模型

@ModelAttribute("user")
public User getUser(){
    User user = new User();
    user.setUsername("admin");
    user.setPassword("123");
    return user;
}

在方法的参数上加入@ModelAttribute,注入模型对象

@RequestMapping("/test2")
public void test2(@ModelAttribute("user")User user){
    System.out.println(user);
}

6、SpringMVC和Ajax交互

目前后台和前端进行通信主要的数据格式是:JSON

6.1 JSON简介

JSON是JavaScript的对象,代码简洁,可读性很高

格式有两种:

  1. 单个对象

    {“name”:"张三","age":"20"}

  2. 对象数组

    [{“name”:"张三","age":"20"},{“name”:"李四","age":"20"}]

Java后台和前端Ajax通信时,经常需要接受JSON参数,也可能需要返回JSON给Ajax

6.2 相关的注解

SpringMVC和Ajax通信的相关注解

  • @RequestBody

    定义在参数前面,用于接收JSON格式的对象

  • @ResponseBody

    定义在方法前面,用于将数据返回给Ajax

6.3 案例

下面案例演示如何接收Ajax的JSON参数,以及如何返回JSON给Ajax

1) 导入依赖

SpringMVC需要JSON解析的相关依赖

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.9.5</version>
</dependency>

2)用户对象

public class User {

    private String username;
    private String password;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }

    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }

    public User() {
    }
}

3) 控制器,在参数中添加了@RequestBody,方法前添加@ResponseBody

将会接收一个User对象参数,然后返回一个User集合给Ajax

/**
 * 自定义控制器
 */
@Controller
public class MyController {

    @ResponseBody
    @RequestMapping("/ajax")
    public List<User> ajaxTest(@RequestBody User user) {
        System.out.println("收到了JSON对象:"+user);
        //返回JSON集合给ajax
        List<User> users = Arrays.asList(new User("user-1","123"),
                new User("user-2","123"),
                new User("user-3","123"));
        return users;
    }
}

4) user.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
    <title>首页</title>
</head>
<body>
    <input id="username" placeholder="请输入用户名"><br>
    <input id="password" placeholder="请输入密码"><br>
    <button>测试</button>
    <script  type="text/javascript" src="/js/jquery-3.3.1.js"></script>
    <script>
        //点击测试
        $("button").click(function () {
            var json = {username:$("#username").val(),password:$("#password").val()};
            $.ajax({
                type: "post",
                dataType: "json",//数据为JSON格式
                url: "/ajax",
                contentType: "application/json;charset=UTF-8",//指定消息请求类型
                data: JSON.stringify(json),//将json对象转成json对象
                success: function (data) {
                    console.log(data);
                }
            });
        });
    </script>
</body>
</html>

测试结果可以看到后台接收到Ajax传递的用户对象,后台返回的Ajax集合也在浏览器控制台输出了。

1、拦截器

1.1 拦截器概念

类似于JavaWeb中的Filter过滤器,用于过滤请求,可以对不符合要求的请求进行拦截

拦截器和过滤器的区别:

1)过滤器的使用范围比拦截器大,JavaWeb项目都可以使用,拦截器只能在SpringMVC使用

2)拦截器效率高于过滤器

1.2 拦截器的使用

1) 实现HandlerInterceptor接口

2)实现方法

1)导入依赖

2.1.1 传统的Servlet文件上传

具体用法:

  • preHandle 前置处理

  • postHandle 后置处理

  • afterCompletion 完成后处理

    /**
     * 登录拦截器
     */
    public class LoginInterceptor implements HandlerInterceptor {
    
        /**
         * 前置处理
         */
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    
            //查询session是否保存用户
            User user = (User) request.getSession().getAttribute("user");
            if(user == null){
                //没有登录,重定向到login页面
                response.sendRedirect("/pages/login");
                //返回false,拦截
                return false;
            }
            //返回true,放行
            return true;
        }
    }

    3) 配置拦截器

    <!--配置拦截器-->
        <mvc:interceptors>
            <mvc:interceptor>
                <!--配置拦截的URL请求路径 /**代表所有请求-->
                <mvc:mapping path="/**"/>
                <!--配置不拦截的请求路径-->
                <mvc:exclude-mapping path="/**/login"/>
                <mvc:exclude-mapping path="/**/*.css"/>
                <mvc:exclude-mapping path="/**/*.js"/>
                <mvc:exclude-mapping path="/**/*.png"/>
                <mvc:exclude-mapping path="/**/*.jpg"/>
                <!--配置class-->
                <bean class="com.blb.bookms.interceptor.LoginInterceptor"/>
            </mvc:interceptor>
        </mvc:interceptors>

    2、文件上传下载

    2.1 文件上传

    文件上传分为两种方式:

  • 传统的Servlet文件上传

  • SpringMVC文件上传

  • 2.1.1 传统的Servlet文件上传

    1)导入依赖

    <dependency>
        <groupId>commons-fileupload</groupId>
        <artifactId>commons-fileupload</artifactId>
        <version>1.4</version>
    </dependency>

    2)编写表单

    表单文件上传的三个要素:

  • form标签要添加enctype="multipart/form-data"

  • 提交方法为post

  • input类型为file

    <form  action="/upload" method="post" enctype="multipart/form-data">
        ...
        <input type="file" name="file" >
        ...
    </form>

    2)上传方法

    @Controller
    public class UploadController {
    
        @RequestMapping("/upload")
        public String fileupload(HttpServletRequest request) throws Exception {
            //获取项目的upload目录路径
            String path= request.getSession().getServletContext().getRealPath("/upload/");
            File file=new File(path);
            //判断文件夹是否存在
            if (!file.exists()){
                //创建文件夹
                file.mkdirs();
            }
            //创建上传对象
            ServletFileUpload upload=new ServletFileUpload(new DiskFileItemFactory());
            //获得文件列表
            List<FileItem> fileItems= upload.parseRequest(request);
            for (FileItem item:fileItems){
                //判断文件是不是普通表单项
                if (item.isFormField()){
                    //如果是普通表单项,打印表单项名和值
                    System.out.println(item.getFieldName());
                    System.out.println(item.getString());
                }else{
                    //如果是文件,截取后缀名
                    String filename= item.getName();
                    String suffix = filename.substring(filename.lastIndexOf("."));
                    //创建唯一的文件名
                    String uuid= UUID.randomUUID().toString().replace("-","");
                    filename = uuid + suffix;
                    //完成文件上传
                    item.write(new File(path,filename));
                    System.out.println("上传完毕");
                }
            }
            //跳转到success页面
            return "success";
        }

    2.1.2 SpringMVC文件上传

    依赖和表单和上面一样

    上传方法中使用MultipartFile参数获得上传文件

    @RequestMapping("/upload")
    public String fileupload(HttpServletRequest request, MultipartFile upload) throws Exception {
        //获取项目目录下的upload目录路径
        String path = request.getSession().getServletContext().getRealPath("/upload/");
        System.out.println(path);
        File file = new File(path);
        if (!file.exists()) {
            file.mkdirs();
        }
        //获取上传文件名字
        String filename = upload.getOriginalFilename();
        String suffix = filename.substring(filename.lastIndexOf("."));
        //创建唯一的文件名
        String uuid= UUID.randomUUID().toString().replace("-","");
        filename = uuid + suffix;
        //完成文件上传
        upload.transferTo(new File(path,filename));
        return "success";
    }

    需要在springmvc的配置中添加上传处理器

    <!--上传处理器-->
    <bean class="org.springframework.web.multipart.commons.CommonsMultipartResolver" id="multipartResolver">
        <!--上传文件最大字节数-->
        <property name="maxUploadSize" value="10485760"/>
    </bean>

    2.1.3 SpringMVC多文件上传

    给表单添加多个文件项

    <form action="/upload" method="post" enctype="multipart/form-data">
        <input type="file" name="uploads">
        <input type="file" name="uploads">
        <input type="file" name="uploads">
        <input type="submit" value="MVC多文件上传">
    </form>

    添加MultipartFile数组为参数,参数名和表单name一致

  • @RequestMapping("/upload3")
    public String fileupload3(HttpServletRequest request, MultipartFile[] uploads) throws Exception {
        //获取tomcat项目目录下的upload目录路径
        String path = request.getSession().getServletContext().getRealPath("/upload/");
        System.out.println(path);
        File file = new File(path);
        if (!file.exists()) {
            file.mkdirs();
        }
        for(MultipartFile upload : uploads) {
            //获取上传文件名字
            String filename = upload.getOriginalFilename();
            String suffix = filename.substring(filename.lastIndexOf("."));
            //创建唯一的文件名
            String uuid = UUID.randomUUID().toString().replace("-", "");
            filename = uuid + "-" + suffix;
            //完成文件上传
            upload.transferTo(new File(path, filename));
        }
        return "success";
    }

    2.1.4 SpringMVC其它上传类

    SpringMVC还提供了其它API支持上传:

  • CommonsMultipartResolver 多部分解析器,用于判断请求是否存在上传文件

  • MultipartHttpServletRequest 多部分请求,用于获得文件相关信息

  • 具体用法:

    @RequestMapping("upload4")
    public String  fileupload4(HttpServletRequest request) throws IllegalStateException, IOException
    {
        String path = request.getSession().getServletContext().getRealPath("/upload/");
        //创建多部分解析器
        CommonsMultipartResolver multipartResolver=new CommonsMultipartResolver(
                request.getSession().getServletContext());
        //检查表单是否支持文件上传
        if(multipartResolver.isMultipart(request)){
            //将请求转换为多部分请求,支持上传
            MultipartHttpServletRequest multiRequest=(MultipartHttpServletRequest)request;
            //获取请求中所有的文件名
            Iterator iter=multiRequest.getFileNames();
            while(iter.hasNext()) {
                //遍历所有文件
                MultipartFile file=multiRequest.getFile(iter.next().toString());
                if(file!=null) {
                    //获取上传文件名字
                    String filename = file.getOriginalFilename();
                    String suffix = filename.substring(filename.lastIndexOf("."));
                    //创建唯一的文件名
                    String uuid = UUID.randomUUID().toString().replace("-", "");
                    filename = uuid + suffix;
                    //上传
                    file.transferTo(new File(path,filename));
                }
            }
        }
        return "success";
    }

    2.2 文件下载

    /**
     * 下载控制器
     */
    @Controller
    public class DownloadController {
    
        @RequestMapping("download")
        public void download(String file,  HttpServletResponse response) throws IOException {
            //下载文件的路径
            String path = "D:\\install\\";
            File downFile = new File(path+file);
            if(downFile.exists()){
                //设置浏览器下载内容类型,响应头
                response.setContentType("application/x-msdownload");
                response.setHeader("Content-Disposition","attachment;filename="+file);
                //通过流发送文件
                Files.copy(downFile.toPath(),response.getOutputStream());
            }
        }
    }

    3、RestFul

    3.1 前后端分离

    3.1.1 前后端分离是什么

    前端项目(html5、小程序、移动端),后端项目(java、数据库、tomcat)分开开发和部署

    3.1.2 前后端分离优势

    1)开发分工明确,前端团队和后端团队同时分工合作开发

    2)项目分开部署不同的服务器,如:Tomcat适合部署动态资源,Nginx适合部署静态资源

    3)便于测试和维护

    3.1.3 前后端开发人员的交互方式

    1)设计人员根据需求设计接口,提供接口文档

    1)后端根据接口文档开发后台接口

    2)前端通过接口请求数据,渲染页面

3.2 RESTFul

3.2.1 RESTFul是什么

RESTFul是一种网络应用程序的设计风格和开发方式,基于HTTP,可以使用XML格式定义或JSON格式定义。适用于移动互联网厂商作为业务使能接口的场景,实现第三方调用移动网络资源的功能,动作类型为新增、变更、删除所调用资源。

RESTful架构,是目前最流行的一种互联网软件架构。它结构清晰、符合标准、易于理解、扩展方便,所以正得到越来越多网站的采用。

3.2.2 RESTFul架构的特点

1) 每一个URI对应服务器上的一个资源(数据库数据、方法等)

2) 通过不同Http请求方法来区别增删改查操作

  • GET --> 查询

  • POST --> 添加

  • PUT --> 更新

  • DELETE --> 删除

3) 通信的格式是JSON

3.2.3 RESTFul风格的API

传统API设计,常用动词定义API,如:find、get、save、update、delete等

查询所有书籍:
http://域名/book/findAll
查询一本书:
http://域名/book/findById?id=1
添加书籍:
http://域名/book/saveBook
更新书籍:
http://域名/book/updateBook
删除书籍:
http://域名/book/deleteBook?id=1

RESTFul风格API设计,只使用名词,使用不同的请求方法来区别增删改查

查询所有书籍:     GET
http://域名/books
查询一本书:      GET
http://域名/book/1
添加书籍:       POST
http://域名/book
更新书籍:       PUT
http://域名/book
删除书籍:       DELETE
http://域名/book/1

Restful风格的控制器的实现

@RestController定义RestFul风格的控制器,其中所有的方法都直接返回数据,相当于加了@ResponseBody

@RestController
public class BookController {

    @Autowired
    private BookService bookService;
    
    @GetMapping("/books")
    public JsonResult findAll(){
        try {
            List<Book> list = bookService.list();
            return new JsonResult(1,list);
        }catch (Exception ex){
            ex.printStackTrace();
            return new JsonResult(0,null);
        }
    }
    
    @GetMapping("/book/{id}")
    public JsonResult findById(@PathVariable("id")Integer id){
        try {
            Book book = bookService.getById(id);
            return new JsonResult(1,book);
        }catch (Exception ex){
            ex.printStackTrace();
            return new JsonResult(0,null);
        }
    }


    @PostMapping("/book")
    public JsonResult saveBook(@RequestBody Book book){
        try {
            bookService.save(book);
            return new JsonResult(1,null);
        }catch (Exception ex){
            ex.printStackTrace();
            return new JsonResult(0,null);
        }
    }


    @PutMapping("/book")
    public JsonResult updateBook(@RequestBody Book book){
        try {
            bookService.updateById(book);
            return new JsonResult(1,null);
        }catch (Exception ex){
            ex.printStackTrace();
            return new JsonResult(0,null);
        }
    }


    @DeleteMapping("/book/{id}")
    public JsonResult delBook(@PathVariable("id")Integer id){
        try {
            bookService.removeById(id);
            return new JsonResult(1,null);
        }catch (Exception ex){
            ex.printStackTrace();
            return new JsonResult(0,null);
        }
    }
}

3.2.4 浏览器支持DELETE和PUT

浏览器默认只支持GET和POST请求,如果要表单提交DELETE或PUT请求,需要通过SpringMVC的过滤器来实现

web.xml添加:

<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>

HiddenHttpMethodFilter过滤器的作用是:过滤表单中名称为_method的隐藏域,如果值是DELETE就将请求方法转换为DELETE,是PUT就将请求方法转换为PUT。

表单

<form action="/testDelete" method="post">
    <input name="name" placeholder="输入姓名"><br>
    <input type="hidden" name="_method" value="DELETE"/>
    <input type="submit" value="提交">
</form>

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

柚几哥哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值