跳至主要內容

SpringMVC

TenSoFlow...大约 7 分钟后端Spring家族SpringMVC

SpringMVC

简介

SpringMVC技术与Servlet技术功能等同,均属于web层开发技术,作用于表现层(Controller)。

是一种基于Java实现MVC模型的轻量级Web框架。

所需依赖与插件

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
    <scope>provided</scope>
</dependency>

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.2.10.RELEASE</version>
</dependency>

<build>
    <finalName>Stu_SpringMVC</finalName>
    <plugins>
        <plugin>
            <groupId>org.apache.tomcat.maven</groupId>
            <artifactId>tomcat7-maven-plugin</artifactId>
            <version>2.1</version> 
            <configuration>
                <port>80</port> <!-- Tomcat服务器端口号 -->
                <path>/</path> <!-- 项目部署的上下文路径 -->
            </configuration>
        </plugin>
    </plugins>
</build>

入门案例

1.导入相关依赖坐标

2.创建SpringMVC控制器类(等同于servlet功能)

3.初始化SpringMVC环境设定SpringMVC加载对应的Bean

4.写配置类,让Tomcat识别

package com.tensoflow.controller;

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

/**
 * 1. @ClassDescription:
 * 2. @author: TenSoFlow
 * 3. @date: 2023年10月20日 10:30
 */

// 使用@Controller定义Bean
@Controller
public class UserController
{
    // 设置请求路径
    @RequestMapping("/save")
    // 设置当前操作的返回值类型
    @ResponseBody
    public String save()
    {
        System.out.println("user save...");
        return "{'username':'TenSoFlow'}";
    }
}

包扫描问题

Spring需要扫描service、dao、domain层的包而SpringMVC需要扫描controller层的包。SpringConfig配置类中就需要使用数组的方式扫描。不能使用com.tensoflow的方式扫描,因为这会扫描到controller。

配置请求路径的前缀

package com.tensoflow.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
/**
 * 1. @ClassDescription:
 * 2. @author: TenSoFlow
 * 3. @date: 2023年10月20日 10:30
 */
// 使用@Controller定义Bean
@Controller
// 请求路径的前缀
@RequestMapping("/user")
public class UserController
{
    // 设置请求路径
    @RequestMapping("/save")
    // 设置当前操作的返回值类型
    @ResponseBody
    public String save()
    {
        System.out.println("user save...");
        return "{'username':'TenSoFlow'}";
    }
}

Get和Post请求传递参数

传递单个参数

GET请求(一个参数):http://localhost:8080/user/save?name=tensoflowopen in new window

接收 地址参数名与形参变量名要相同

@RequestMapping("/save")
// 设置当前操作的返回值类型
@ResponseBody
public String save(String name)
{
    System.out.println(name);
    return "{'username':'TenSoFlow'}";
}

传递多个参数

GET请求(多个参数):http://localhost:8080/user/save?name=tensoflow&age=18open in new window

接收 地址参数名与形参变量名要相同

@Controller
@RequestMapping("/user")
public class UserController
{
    // 设置请求路径
    @RequestMapping("/save")
    // 设置当前操作的返回值类型
    @ResponseBody
    public String save(String name,int age)
    {
        System.out.println(name);
        System.out.println(age);
        return "{'username':'TenSoFlow'}";
    }
}

Post请求与Get请求差不多,Post请求参数不是写在地址上而是写在Body中。

指定传递多个参数

GET请求(多个参数):http://localhost:8080/user/save?name=tensoflow&age=18open in new window

接收 使用@RequestParam注解指定地址中的name赋值给username

@RequestMapping("/save")
// 设置当前操作的返回值类型
@ResponseBody
public String save(@RequestParam("name") String username, int age)
{
    System.out.println(username);
    System.out.println(age);
    return "{'username':'TenSoFlow'}";
}

实体类接收参数

GET请求(多个参数):http://localhost:8080/user/save?name=tensoflow&age=18open in new window

接收 用实体类接收,实体类中的属性要与地址中的名称对应

    @RequestMapping("/save")
    // 设置当前操作的返回值类型
    @ResponseBody
    public String save(User user)
    {
        System.out.println(user.getName());
        System.out.println(user.getAge());
        return "{'username':'TenSoFlow'}";
    }

嵌套实体类接收参数

GET请求(多个参数):http://localhost:8080/user/save?name=tensoflow&address.name=18open in new window

接收 如果实体类中有另一个实体类,如User类中有private Address address属性,如果想为address中的name属性赋值,则地址中的参数为address.nameopen in new window

@RequestMapping("/save")
// 设置当前操作的返回值类型
@ResponseBody
public String save(User user)
{
    System.out.println(user.getAddress().getName());
    return "{'username':'TenSoFlow'}";
}

数组接收参数

GET请求(多个参数):http://localhost:8080/user/save?name=tensoflow&name=18&name=Staropen in new window

接收 如果需要接收数组则地址中的参数一样即可

@RequestMapping("/save")
// 设置当前操作的返回值类型
@ResponseBody
public String save(String[] name)
{
    for(String username : name)
    {
        System.out.println(username);
    }
    return "{'username':'TenSoFlow'}";
}

集合接收参数

GET请求(多个参数):http://localhost:8080/user/save?name=tensoflow&name=18&name=Staropen in new window

接收 如果需要接收集合则地址中的参数名一样并且加上@RequestParam注解

@RequestMapping("/save")
// 设置当前操作的返回值类型
@ResponseBody
public String save(@RequestParam List<String> name)
{
    for(String username : name)
    {
        System.out.println(username);
    }
    return "{'username':'TenSoFlow'}";
}

Json数据传递参数

所需依赖

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

首先导入依赖然后在SpringMvcConfig上加上@EnableWebMvc注解,并在参数前加上@RequestBody注解(用于接收JSON数据格式),此时的请求应该是在Boby中选用raw下的JSON数据发送。

@Configuration
@ComponentScan("com.tensoflow.controller")
@EnableWebMvc
public class SpringMvcConfig
{

}

传递日期参数

默认格式传递日期

GET请求:http://localhost:8080/user/save?date=2002/8/9open in new window

接收

@RequestMapping("/save")
// 设置当前操作的返回值类型
@ResponseBody
public String save(Date date)
{
    System.out.println(date);
    return "{'username':'TenSoFlow'}";
}

指定格式传递日期

GET请求:http://localhost:8080/user/save?date=2002-10-9open in new window

接收

@RequestMapping("/save")
// 设置当前操作的返回值类型
@ResponseBody
public String save(@DateTimeFormat(pattern = "yyyy-MM-dd") Date date)
{
    System.out.println(date);
    return "{'username':'TenSoFlow'}";
}

响应

响应页面

@RequestMapping("/toJumpPage")
public String save()
{
    System.out.println("to ...");
    return "index.jsp";
}

响应字符串

@RequestMapping("/toText")
@ResponseBody
public String save()
{
    System.out.println("to ...");
    return "TenSoFlow";
}

响应JSON数据

@RequestMapping("/toJSON")
@ResponseBody
public User save()
{
    User user = new User();
    user.setName("TenSoFlow");
    user.setAge(21);
    return user;
}

REST风格

REST(Representational State Transfer)表现形式状态转换。能隐藏资源的访问行为,无法通过地址得知对资源是何种操作。书写简化。

使用

无参

POST请求:http://localhost:8080/usersopen in new window

此时只能Post请求才行

@RequestMapping(value = "/users", method = RequestMethod.POST)
@ResponseBody
public String save()
{
    System.out.println("save...");
    return "{'name':'TenSoFlow'}";
}

有参

Delete请求:http://localhost:8080/users/1open in new window

@RequestMapping(value = "/users/{id}", method = RequestMethod.DELETE)
@ResponseBody
public String delete(@PathVariable Integer id)
{
    System.out.println(id);
    return "{'name':'TenSoFlow'}";
}

最终简化形式

package com.tensoflow.controller;
import com.tensoflow.domain.User;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import java.util.Date;
import java.util.List;
/**
 * 1. @ClassDescription:
 * 2. @author: TenSoFlow
 * 3. @date: 2023年10月20日 10:30
 */
@RequestMapping("/users")
// 是@Controller和@ResponseBody的结合
@RestController
public class UserController
{
    // 设置请求路径
    @PostMapping
    public String save()
    {
        System.out.println("save...");
        return "{'name':'TenSoFlow'}";
    }

    @DeleteMapping("/{id}")
    public String delete(@PathVariable Integer id)
    {
        System.out.println(id);
        return "{'name':'TenSoFlow'}";
    }
}

表现层数据封装(Result)

package com.tensoflow.util;
/**
 * 1. @ClassDescription:
 * 2. @author: TenSoFlow
 * 3. @date: 2023年10月23日 9:15
 */
public class Result
{
    private String message;
    private Integer code;
    private Object data;

    public Result()
    {
        
    }

    public Result(Integer code, Object data)
    {
        this.code = code;
        this.data = data;
    }

    public Result(String message, Integer code, Object data)
    {
        this.message = message;
        this.code = code;
        this.data = data;
    }
}

异常处理器

所有的异常均抛到表现层处理

package com.tensoflow.controller;

import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

/**
 * 1. @ClassDescription:
 * 2. @author: TenSoFlow
 * 3. @date: 2023年10月23日 9:34
 */
@RestControllerAdvice
public class ProjectExceptionAdvice
{
    // 填你希望处理的异常种类
    @ExceptionHandler(Exception.class)
    public void doException(Exception ex)
    {
        System.out.println("嘿嘿,异常你哪里跑!");
    }
}

这个类的位置要让SpringMVC扫描到

拦截器

概念

拦截器(Interceptor)是一种动态拦截方法调用的机制,在SpringMVC中动态拦截控制器方法的执行。

作用

1.在指定的方法调用前后执行预先设定的代码

2.阻止原始方法的执行

拦截器与过滤器

package com.tensoflow.controller.interceptor;

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 1. @ClassDescription:
 * 2. @author: TenSoFlow
 * 3. @date: 2023年10月23日 10:40
 */
@Component
public class ProjectInterceptor implements HandlerInterceptor
{
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception
    {
        System.out.println("preHandle");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception
    {
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception
    {
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }
}

多拦截器工作流程

评论
  • 按正序
  • 按倒序
  • 按热度
Powered by Waline v2.15.8