Spring MVC - Controller的创建与使用

控制器Controller是处理器,是真正处理请求的组件

1 创建Controller

一般在src/main/java/com/qdu下建立一个controller包用来存放所有控制器。当创建一个控制器时,首先要记得使用**@Controller**标记将该类注册成为一个控制器类。

然后在SpringMVCConfig类中开启对com.qdu.controller包的扫描,并使用**@EnableWebMvc**注解,这样controller待会要用到的@RequestMapping等的配置会生效。

java 复制代码
@Configuration
@ComponentScan(basePackages = {"com.qdu.controller"})
@EnableWebMvc
public class SpringMVCConfig implements WebMvcConfigurer{
    
    @Override
	public void addResourceHandlers(ResourceHandlerRegistry registry) {
		registry.addResourceHandler("/static/**").addResourceLocations("/static/");
	}

	@Override
	public void configureViewResolvers(ViewResolverRegistry registry) {
		registry.jsp("/WEB-INF/jsp/", ".jsp");
	}

	@Override
	public void addViewControllers(ViewControllerRegistry registry) {
		registry.addViewController("/").setViewName("index");
		registry.addViewController("/toIndex").setViewName("index");
		registry.addViewController("/toPage1").setViewName("page1");
		registry.addViewController("/toPage2").setViewName("page2");
		registry.addViewController("/toPage3").setViewName("page3");
		registry.addViewController("/toNext").setViewName("next");
		registry.addViewController("/toAddStudent").setViewName("add_student");
		registry.addViewController("/toFindStudentPage").setViewName("find_student");
	}

}

可以发现在Spring MVC的配置类中我们也配置了许多视图控制器,用于跳转到对应的JSP页面,如这里的toIndex是跳转到index.jsp,在前端页面的引用方法为:

html 复制代码
<div class="text-center">
    <a href="toIndex" class="btn btn-sm btn-danger">返回首页</a>
</div>

2 关于Get请求和Post请求的映射

在controller中可以使用**@RequestMapping**注解,它默认可以映射所有请求,包括get和post。也可以通过method属性指定当前方法处理的请求的类型,这样方法只能处理对应类型请求。

假设现在有一个控制器TestController1,要在该控制器中处理两数相加的get请求与post请求,方法名分别是cal1与cal2

java 复制代码
@Controller
@RequestMapping("/test1")
public class TestController1 {

    public String cal1(int num1, int num2, Model model) { }

    public String cal2(int num1, int num2, Model model) { }

}

首先对两种方法使用@RequestMapping注解,内容应填入对应的url,也可以用method属性指定请求对应的类型。

java 复制代码
@RequestMapping(value = "/test1/cal1", method = RequestMethod.GET)
public String cal1(int num1, int num2, Model model) { }

@RequestMapping(value = "/test1/cal2", method = RequestMethod.POST)
public String cal2(int num1, int num2, Model model) { }

接下来继续写方法内容,大致过程就是获取请求参数(这里就是要相加的两个数),然后进行加和操作后再返回结果页面。

我们可以从前端的表单看到输入进来的两个数:

html 复制代码
<form action="test1/cal1" class="form-inline text-center bg-danger" id="form1" method="get">
	<h3 class="text-danger">表单1-使用Get提交表单</h3>
	<hr />
	数字1: <input type="text" name="num1" value="100" class="form-control">
	<br><br> 
	数字2: <input type="text" name="num2" value="200" class="form-control"> 
	<br><br> 
	<button class="btn btn-sm btn-danger">计算</button>
</form>

注意观察两个数字的name属性的值即可。

java 复制代码
@RequestMapping(value = "/test1/cal1", method = RequestMethod.GET)
public String cal1(int num1, int num2, Model model) {
    model.addAttribute("jieguo", num1 + num2);
    return "result";
}

这里给前端展示结果的变量取名为"jieguo",故引用时应为${jieguo},代码应如下:

html 复制代码
<h4 class="text-primary">
    计算结果: <span class="text-danger padding5">${jieguo}</span>
</h4>

同时还可以在前端展示请求的url,在cal1方法中加上:

java 复制代码
model.addAttribute("requestUrl", "/test1/cal1");

前端展示的代码应为:

html 复制代码
<h4 class="text-primary">
    请求url: <span class="text-danger padding5">${requestUrl}</span> 
</h4>

最后展示的结果应该为:

请求url:/test1/cal1

计算结果:300

cal2方法的代码大同小异,只需要将method属性的值改为:RequsetMethod.POST

如果觉得使用@RequestMapping注解书写较多,也可使用**@GetMapping、@PostMapping**简化书写。

最后,完整的的TestController1代码如下:

java 复制代码
package com.qdu.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
@RequestMapping("/test1")
public class TestController1 {
	
	@GetMapping("/cal1")
	public String cal1(int num1, int num2, Model model) {
		model.addAttribute("requestUrl", "/test1/cal1");
		model.addAttribute("jieguo", num1 + num2);
		return "result";
	}

	@PostMapping("/cal2")
	public String cal2(int num1, int num2, Model model) {
		model.addAttribute("requestUrl", "/test1/cal2");
		model.addAttribute("jieguo", num1 + num2); 
		return "result"; 
	}

}

一定要注意,这里的

java 复制代码
return "result"

是指跳转到result.jsp页面,原理在创建和配置Spring MVC框架构建Web应用这篇文章中提到过

因为WEB-INF/jsp目录下的页面是不能直接访问,需要经过控制器跳转,而且最一开始的Spirng MVC配置类中,我并没有给result.jsp配置对应的视图控制器,而是应该在得出计算结果之后,由对应的控制器控制跳转到结果界面。

最后有一个小区别,我们观察浏览器的url栏,发现get请求和post请求的url并不一样:

get请求会显示出请求参数及其值:

而post请求则不会:

3 控制器类方法的接受参数

3.1 参数名与请求参数同名

控制方法参数可以是任何类型,可以保持参数名和请求参数名同名来接收对应的参数,常规类型转换会自动完成。

请看接下来的例子,前端请求两个数num1、num2,返回二者相加的结果,控制器类方法的参数也为num1、num2

前端:

html 复制代码
<a href="test2/req1?num1=11&num2=12">1.  任意类型-方法参数名和请求参数名同名</a>

在这一章节中使用的TestController2的代码初始化如下:

java 复制代码
@Controller
@RequestMapping("/test2")
public class TestController2 {

    @Autowired
    private ExamService examService;

}

控制器类方法req1:(注意,req1的参数应该与前端的一样,为num1、num2)

java 复制代码
@GetMapping("/req1")
public String req1(int num1, int num2, Model model) {
    model.addAttribute("jieguo", num1 + num2);
    return "result";
}

3.2 请求参数名和方法参数名不同名

若前端发来的请求参数名与控制器类的方法参数不同名,则应使用**@RequestParam**注解指定请求参数的信息。

假如在前端,传请求参数的代码为:

html 复制代码
<a href="test2/req2?number1=21&number2=22">2.  使用@RequestParam注解</a>

可以看到前端的请求参数名为number1、number2,但是在控制器类方法中,我仍然想用num1、num2当方法参数,可以这样写:

java 复制代码
@GetMapping("/req2")
public String req2(
        @RequestParam(value = "number1", defaultValue = "0") int num1, 
        @RequestParam(value = "number2", defaultValue = "0") int num2,
        Model model) {
    model.addAttribute("jieguo", num1 + num2);
    return "result";
}

value或name属性: 指定请求参数的名称

defaultValue属性: 指定当该请求参数没有提供的时候,使用什么默认值

requird属性: 指定该请求参数是否必须要提供,默认是true,不提供会抛出异常,对于可选的参数可设置为false

3.3 接收一个请求参数的多个值

有时候一个参数会有多个值,比如我们使用复选框来提交的数据。

假设我们前端让用户选取自己的爱好有哪些,可以多选,前端会传来多个请求参数hobbies的值。对于这多个hobbies的值,我们可以用一个String\[\]数组来接受。

java 复制代码
@GetMapping("/req3")
public String req3(String[] hobbies, Model model) {
    model.addAttribute("hobbies", hobbies);
    return "hobby_page";
}

在前端hobby_page展示爱好,使用<c:forEach>遍历hobbies数组:

html 复制代码
<h4 class="text-primary">
    结果:
    <span class="text-danger padding5">
        <c:forEach items=${hobbies} var="hobby">
            ${hobby}
        </c:forEach>
    </span>
</h4>

3.4 获取请求对象与响应对象

有的时候除了获取请求参数,还可能需要操作请求,可以直接获取请求对象

可以使用HttpServletRequest或ServletRequest类型来获取请求对象

可以使用HttpServletResponse或ServletResponse类型来获取响应对象

前端的请求参数为:

html 复制代码
<a href="test2/req4?num1=41&num2=42">4.  请求对象(HttpServletRequest)和响应对象(HttpServletResponse)</a>

在控制器方法中,使用HttpServletRequest类型的req获取请求对象,进而得到请求参数num1、num2

java 复制代码
@GetMapping("/req4")
public String req4(Model model, HttpServletRequest req, HttpServletResponse resp) {
    int num1 = Integer.parseInt(req.getParameter("num1"));
    int num2 = Integer.parseInt(req.getParameter("num2"));
    model.addAttribute("jieguo", num1 + num2);
    return "result";
}

3.5 包含所有请求参数的Map集合

有的时候可能需要获取所有的请求参数(请求参数比较多的时候,而且个数不定的时候),可以直接使用一个Map<String, String>集合获取所有的请求参数。但是该参数前面必须添加@RequestParam注解说明这个Map集合用于封装所有的请求参数

java 复制代码
@GetMapping("/req5")
public String req5(@RequestParam Map<String, String> map, Model model) {
    int num1 = Integer.parseInt(map.get("num1"));
    int num2 = Integer.parseInt(map.get("num2"));
    model.addAttribute("jieguo", num1 + num2);
    return "result";
}

3.6 会话对象HttpSession

3.6.1 介绍会话对象

可以发现,我们之前的控制器类方法中都有一个参数Model对象,放入Model对象的数据是请求范围的数据,默认跳转页面是以请求转发的形式跳转页面。

可以直接加一个HttpSession类型的参数,用于获取当前会话对象,以操作当前会话对象

java 复制代码
@GetMapping("/req6_1")
public String req6_1(int number, HttpSession session) {
    session.setAttribute("jieguo", number * number);
    return "result";
}

3.6.2 HttpSession对象获取会话对象中属性

如果希望获取会话范围的属性或操作会话,可以直接获取会话对象,进而操作会话

java 复制代码
@GetMapping("/req6_2")
public String req6_2(HttpSession s) {
    System.out.println("~~~~~~~~~~~~~~~jieguo:" + s.getAttribute("jieguo"));
    return "hint";
}

在这里,我们会在控制台输出6_1中number * number的结果:

3.6.3 @SessionAttribute注解获取会话对象中属性

如果希望获取会话范围的属性,也可使用@SessionAttribute注解修饰的方法参数来获取一个会话范围的属性,可以直接使用对应类型接收会话属性。

需要指定获取的属性的名称,如这里的jieguo

java 复制代码
@GetMapping("/req6_3")
public String req6_3(@SessionAttribute("jieguo") int result) {
    System.out.println("***************jieguo:" + result);
    return "hint";
}

3.7 Model、ModelMap、Map

如果控制器方法中需要返回一些数据显示到页面上,可以使用Model或ModelMap或Map对象,作用一样,但是每个类型提供的方法不同

可以根据选择,通常使用Model即可,这三个对象中的数据都是请求范围的数据

java 复制代码
@GetMapping("/req7")
public String req7(Model model, ModelMap mm, Map map) {
    model.addAttribute("msg1", "这是使用Model对象添加的属性");
    mm.addAttribute("msg2", "这是使用ModelMap对象添加的属性");
    map.put("msg3", "这是使用Map对象添加的属性");
    return "message";
}

3.8 路径变量@PathVariable

3.8.1 单个参数

对于REST风格的路径req8/8 ,如果某一级表示的是参数值,则使用{变量名}来表示这是一个路径变量/路径参数

前端我们设定的url为test2/req8/8,我们要将最后这个8设定为路径变量

html 复制代码
<a href="test2/req8/8">8.  使用@PathVariable(路径变量)-单个参数</a>

我们在控制器方法添加了一个参数number(使用对应类型即可),用于接收路径变量num的值:

java 复制代码
@GetMapping("/req8/{num}")
public String req8(Model model, @PathVariable("num") int number) {
    model.addAttribute("jieguo", number * number);
    return "result";
}

3.8.2 单个参数 - url写法

对于url:/req9/9/square

java 复制代码
//如果方法参数名和路径变量名同名,则使用@PathVariable注解的时候就不需要指定路径变量的名称了
@GetMapping("/req9/{num}/square")
public String req9(@PathVariable int num, Model model) {
    model.addAttribute("jieguo", num * num);
    return "result";
}

3.8.3 多个路径变量/参数

对于url:/req10/10/add/100,我想将10与100分别设为路径变量,分别命名为num1、num2,直接在方法声明多个参数即可

java 复制代码
@GetMapping("/req10/{num1}/add/{num2}")
public String req10(@PathVariable int num1, @PathVariable int num2, Model model) {
    model.addAttribute("jieguo", num1 + num2);
    return "result";
}

3.8.4 *通配符

使用 * 通配符匹配一级路径

诸如此路径:/req11/*/square/111,这个路径可以匹配/req11/user/square/111,也可以匹配/req11/admin/square/111

假设在前端有这两个请求:

html 复制代码
<a href="test2/req11/user/square/111">11.1.  使用@PathVariable(路径变量)-通配符*</a></li>
<a href="test2/req11/admin/square/112">11.2.  使用@PathVariable(路径变量)-通配符*</a>

在这里,路径最后的数为路径变量num,要在控制器方法中得到num*num,除此之外只有第三级user与admin不同,可以用一个*通配符来匹配这一级路径。

java 复制代码
@GetMapping("/req11/*/square/{num}")
public String req11(Model model, @PathVariable int num) {
    model.addAttribute("jieguo", num * num);
    return "result";
}

3.8.5 **通配符

使用 ** 通配符匹配任意多级路径

诸如这两个路径:

/req12/aaa/bbb/ccc/ddd/121/square

/req12/ddd/122/square

我们可以发现,路径中的数字为路径变量num,在控制器方法中得到num*num,其余部分只在/req12与/{num}之间的路径不同,但是这之间并不只是单级路径,而是多级路径,要使用 ** 通配符来匹配:

java 复制代码
@GetMapping("/req12/**/{num}/square")
public String req12(Model model, @PathVariable int num) {
    model.addAttribute("jieguo", num * num);
    return "result";
}

3.9 对象类型

控制器类方法参数支持对象类型,在有以下类似的情形可以使用对象类型参数:

要提交多个数据,每个请求参数与实体类的参数一一对应,诸如我们前端有一个表单,用来收集学生的个人信息:

html 复制代码
<form action="test2/req13" class="form-inline" method="post">
    <span>学号:</span><input type="text" name="sid" value="2019208888" class="form-control" placeholder="在此输入学号">
    <br><br>
    <span>姓名:</span><input type="text" name="sname" value="anna" class="form-control" placeholder="在此输入姓名">
    <br><br>
    <span>密码:</span><input type="text" name="spassword" value="123456" class="form-control" placeholder="在此输入密码">
    <br><br>
    <span>性别:</span>
    <select name="sgender" class="form-control fixedWidth">
        <option value="男">男</option>
        <option value="女">女</option>
    </select>
    <br><br>
    <span>班级:</span>
    <select name="sbatch" class="form-control fixedWidth">
        <option value="19软件J01">19软件J01</option>
        <option value="19软件BD01">19软件BD01</option>
        <option value="19软件BD02">19软件BD02</option>
        <option value="19软件BD03">19软件BD03</option>
    </select>  
    <br><br>
    <span>生日:</span>
    <input type="date" name="sdob" class="form-control" value="2001-12-03">
    <br><br>
    <input type="submit" value="添 加" class="btn btn-sm btn-primary">
</form>

在这里我们还有一个实体类Student,Student类中的每一个参数与表单中的每一请求参数一一对应:

java 复制代码
public class Student {

	private String sid;
	private String sname; 
	private String spassword;
	private String sgender;
	private String sbatch;
	
	//所有的请求参数都是以字符串的形式提交,字符串转成double、int等类型会自动转换
	//但是不能自动转换成Date类型
	//使用@DateTimeFormat注解后,字符串类型的请求参数就可以转换成Date类型 
	@DateTimeFormat(pattern="yyyy-MM-dd")
	private Date sdob;

	public Student() {
	}

	public Student(String sid, String sname, String spassword, String sgender, String sbatch, Date sdob) {
		this.sid = sid;
		this.sname = sname;
		this.spassword = spassword;
		this.sgender = sgender;
		this.sbatch = sbatch;
		this.sdob = sdob;
	}

	public String getSid() {
		return sid;
	}

	public void setSid(String sid) {
		this.sid = sid;
	}

	public String getSname() {
		return sname;
	}

	public void setSname(String sname) {
		this.sname = sname;
	}

	public String getSpassword() {
		return spassword;
	}

	public void setSpassword(String spassword) {
		this.spassword = spassword;
	}

	public String getSgender() {
		return sgender;
	}

	public void setSgender(String sgender) {
		this.sgender = sgender;
	}

	public String getSbatch() {
		return sbatch;
	}

	public void setSbatch(String sbatch) {
		this.sbatch = sbatch;
	}

	//对于java对象,如果有日期类型的属性,转换成json的时候,默认是以毫秒的形式显示时间
	//对于日期时间类型的数据,可以添加@JsonFormat来指定转成json的时候
	//日期时间是什么格式,还可以指定时区
	@JsonFormat(pattern="yyyy-MM-dd",timezone = "GMT+8")
	public Date getSdob() {
		return sdob;
	}

	public void setSdob(Date sdob) {
		this.sdob = sdob;
	}

	@Override
	public String toString() {
		return "Student [sid=" + sid + ", sname=" + sname + ", spassword=" + spassword + ", sgender=" + sgender
				+ ", sbatch=" + sbatch + ", sdob=" + sdob + "]";
	}
}

我们要将前端获得的学生信息进行展示:

java 复制代码
@GetMapping("/req13")
public String req13(Student s) {
    System.out.println("学生信息:"+s);
    return "hint";
}

3.10 获取Cookie值

在这里为了简化,不再自行创建cookie,每个web程序都会放置一个名为JSESSIONID的cookie到客户端

为了获取某个Cookie的值,可以给控制器方法添加参数,用于获取Cookie的值

用于获取Cookie值的参数需要使用@CookieValue注解修饰,并指定Cookie的名称

java 复制代码
@GetMapping("/req14")
public String req14(@CookieValue("JSESSIONID") String sessionId) {
	System.out.println("*******************sessionId:"+sessionId);
	return "hint"; 
}

4 控制器类方法的返回参数

4.1 String

从前端接受一个数并返回这个数的平方,控制器类的方法为String类型

前端发送请求的代码为:

html 复制代码
<a href="test3/req3_1?number=31">3.1. String</a>

控制器类方法代码:

java 复制代码
@GetMapping("/req3_1")
public String req3_1(int number, Model model) {
    model.addAttribute("jieguo", number * number);
    return "result";
}

在默认情况下,最后的return "result"是指要跳转的视图的名称。

但有些情况下,我们希望控制器方法返回的内容为响应正文的内容,而不是跳转的视图名称,此时可以使用@ResponseBody注解修饰该方法。

java 复制代码
// produces属性用于指定返回的响应内容的MIME类型和字符集编码
@GetMapping("/req4_1", produces = "text/html;charset=utf-8")
@ResponseBody
public String req4_1(String name) {
    return "<h1>Hello, " + name + "</h1>";
}

4.2 ModelAndView

这里控制器类的方法为ModelAndView类型,返回ModelAndView类型的mv。将结果和要跳转的视图都封装到ModelAndView中,最后返回这个ModelAndView。

java 复制代码
@GetMapping("/req3_2")
public ModelAndView req3_2(int number) {
    ModelAndView mv = new ModelAndView();
    mv.setViewName("result");
    mv.addObject("jieguo", number * number);
    return mv;
}

4.3 Integer、int、Double、double、Float、float、Boolean、boolean等

java 复制代码
@GetMapping("/req4_2")
@ResponseBody
public Integer req4_2(int number) { return number * number; }

4.4 单个对象:如Student、Dog、Product、Course等

Spring MVC默认使用Jackson作为json处理器,来转换java对象和json数据。只要添加jackson的依赖,java对象就会被自动转换为json对象。

如果返回一个对象(封装器类型和String等除外),则数据默认会被转换成json格式

java 复制代码
@GetMapping("/req4_3")
@ResponseBody
public Student req4_3() {
    return new Student(
        return new Student(
            "2019209999","张三","123456","男","19软件J03",Date.valueOf("2001-12-03")
    );
}

再举一个例子,发送ajax请求,返回单个对象。

假设前端有一个表单收集学生的学号,填写学号后能显示该学生的学生信息:

html 复制代码
<form class="form-inline">
                  学号:<input type="text" id="sid" value="2019209991"class="form-control"> 
    &nbsp;&nbsp;
    <input type="button" id="btn" value="查询" class="btn btn-sm btn-danger">
</form>

显示查到的学生信息的前端代码如下:

html 复制代码
<div id="studentInfo">
    <p>学号:<span id="idSpan"></span> </p>
    <p>姓名:<span id="nameSpan"></span> </p>
    <p>密码:<span id="passwordSpan"></span> </p>
    <p>姓名:<span id="genderSpan"></span> </p>
    <p>班级:<span id="batchSpan"></span> </p>
    <p>生日:<span id="dobSpan"></span> </p>
</div>

我们有一个控制器类TestController4,调用StudentService中的方法根据学号查询学生,返回一个Student对象:

java 复制代码
//@RestController是@Controller+@ResponseBody注解的组合
//@RestController说明当前类是个控制器类,并且相当于每个方法前添加@ResonseBody注解
@RestController
@RequestMapping("/test4")
public class TestController4 {
    
    @Autowired 
    StudentService studentService;

    @GetMapping("/req4_7")
    public Student req4_7(String id) {
        return studentService.getOne(id);
    }
}

此时我们回到前端来写ajax部分的代码,根据后端Controller的方法可以得知,请求的url应为/test4/req4_7,请求类型为Get请求

javascript 复制代码
<script>
    $(document).ready(function () {
    
        $("#btn").click(function() {

            //ajax()函数用于发送一个ajax请求
            $.ajax({
                url: "/test4/req4_7",
                type: "GET",
                data: {id : $("#sid").val()},
                success: function (s){
                    //success对应的函数可以添加一个参数,用于接收控制器返回的数据
                    //参数名可以随意命名,但是尽量有意义,这里s用于接收返回的学生数据,是一个json对象
                    $("#idSpan").html(s.sid); //html()函数可用于修改选中元素的内容为指定内容
                    $("#nameSpan").html(s.sname);
                    $("#passwordSpan").html(s.spassword);
                    $("#genderSpan").html(s.sgender);
                    $("#batchSpan").html(s.sbatch);
                    $("#dobSpan").html(s.sdob);
                },
                error: function (req, status, error) {
                    alert("请求失败:" + error);
                }
            });
        });
    });
</script>

4.5 列表:List<Student>、List<Product>等

如果返回的是列表,列表会被转换成json数组

java 复制代码
@GetMapping("/req4_4")
public List<Student> req4_4() {
	List<Student> list=new ArrayList();
	list.add(new Student("2019209991","小胖","123456","男","19软件J01",Date.valueOf("2001-12-03")));
	list.add(new Student("2019209992","小强","123456","男","19软件J01",Date.valueOf("2002-02-09")));
	list.add(new Student("2019209993","小兰","123456","女","19软件J02",Date.valueOf("2003-11-10")));
	list.add(new Student("2019209994","小明","123456","男","19软件J02",Date.valueOf("2000-09-01")));
	list.add(new Student("2019209995","小奇","123456","男","19软件J03",Date.valueOf("2001-07-08")));
	list.add(new Student("2019209996","小红","123456","女","19软件J03",Date.valueOf("2002-11-19")));
	return list;
}

4.6 Map集合:Map<String,String>,Map<String,Student>等

如果返回的是一个Map集合,则该Map对象会被转换成一个json对象

java 复制代码
@GetMapping("/req4_5")
public Map req4_5() {
	Map map=new HashMap();
	map.put("error_code", 101);
	map.put("error_message", "发送的请求参数有错");
	return map;
}

4.7 void类型

返回类型为void,说明返回的响应内容为空

java 复制代码
@GetMapping("/req4_6")
public void req4_6() {
	System.out.println("...................我没返回任何值!!!");
}
相关推荐
BUG指挥官1 天前
Sa-Token和Spring Security对比
java·后端·spring
geminigoth1 天前
Spring AI Alibaba 入门开发一(备份)
java·人工智能·spring
xbgRS1 天前
spring整合mybaits
java·spring·mybatis
ruleslol1 天前
静态依赖注入 VS 动态依赖查询
spring
墨雨晨曦881 天前
Spring AI总结
java·人工智能·spring
用户3126874877201 天前
Spring Boot 异常处理到底怎么玩的?从 DispatcherServlet 到全局兜底的全链路拆解
spring
不才不才不不才1 天前
Spring 源码系列(17): HandlerMapping 与 HandlerAdapter 两大体系
java·后端·spring
(轻舟已过万重山)1 天前
第40章 Spring AI 实战:企业级 AI 应用架构
人工智能·spring·架构
堕落年代2 天前
Ollama CPU 推理大提示词优化实测报告(细致化数据版)
java·后端·spring
cfm_29142 天前
基于OAuth2.0实现微服务SSO单点登录
后端·spring·微服务·架构