文章目录
Spring MVC
参考视频:B站狂神,写这个只是方便个人复习,怎么写是我自己的事,我能看懂就行,没要求非要让你看!白嫖还挑刺,是很没有风度的事情。希望做个有风度的“五好青年”!
4、RestFul和Controller
1.控制器Controller
- 控制器复杂提供访问应用程序的行为,通常可以通过接口定义或注解定义两种方法实现。
- 控制器负责解析用户的请求并将其转换为一个模型。
- 在Spring MVC中一个控制器类可以包含多个方法
- 在Spring MVC中,对于Controller的配置方式有很多种
2.实现Controller接口
Controller是一个接口,在org.springframework.web.servlet.mvc包下,接口中只有一个方法;
// 实现该接口的类获得控制器功能
public interface Controller {
// 处理请求且返回一个模型与视图对象
ModelAndView handleRequest(HttpServletRequest var1, HttpServletResponse var2) throws Exception;
}
-
新建一个Moudle,springmvc-04-controller 。将刚才的03拷贝一份, 进行操作!
- 删掉HelloController。
- web.xml
<?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">
<!--1.注册servlet-->
<servlet>
<servlet-name>SpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--通过初始化参数指定SpringMVC配置文件的位置,进行关联-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc-servlet.xml</param-value>
</init-param>
<!-- 启动顺序,数字越小,启动越早 -->
<load-on-startup>1</load-on-startup>
</servlet>
<!--所有请求都会被springmvc拦截 -->
<servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
- springmvc-servlet.xml,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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
<!-- 前缀 -->
<property name="prefix" value="/WEB-INF/jsp/" />
<!-- 后缀 -->
<property name="suffix" value=".jsp" />
</bean>
</beans>
- 编写一个Controller类,ControllerTest.java
package com.github.subei.controller;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
// 定义控制器:只要实现了 Controller 接口类,说则这就是一个控制器了
// 注意点:不要导错包,实现Controller接口,重写方法;
public class ControllerTest implements Controller {
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
//返回一个模型视图对象
ModelAndView mv = new ModelAndView();
mv.addObject("msg","ControllerTest");
mv.setViewName("test");
return mv;
}
}
- 编写完毕后,去Spring配置文件中注册请求的bean;name对应请求路径,class对应处理请求的类。
<bean name="/t1" class="com.github.subei.controller.ControllerTest"/>
- 编写前端test.jsp,注意在WEB-INF/jsp目录下编写,方便对应视图解析器。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
${msg}
</body>
</html>
- 配置Tomcat运行测试,我这里项目发布名配置是/springmvc_04,如果没写,只是一个 / ,则请求不用加项目名,直接运行即可。不影响!
- 测试访问路径:http://localhost:8080/springmvc_04/t1
- 测试成功!!!
- <mark>注</mark>
- 实现接口Controller定义控制器是较老的办法;
- 缺点是:一个控制器中只有一个方法,如果要多个方法则需要定义多个Controller;定义的方式比较麻烦。
3.使用注解@Controller
- @Controller注解类型用于声明Spring类的实例是一个控制器;
- Spring可以使用扫描机制来找到应用程序中所有基于注解的控制器类,为了保证Spring能找到你的控制器,需要在配置文件中声明组件扫描。
<!-- 自动扫描包,让指定包下的注解生效,由IOC容器统一管理 -->
<context:component-scan base-package="com.github.subei.controller"/>
- 增加一个ControllerTest2类,使用注解实现;
package com.github.subei.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller//代表这个类会被spring接管
// 被这个注解的类,中的所有方法,如果返问值是string,并且有具体页面可以跳转,那么就会被视图解析器解析;
public class ControllerTest2 {
// 映射访问路径
@RequestMapping("/t2")
public String index(Model model){
// Spring MVC会自动实例化一个Model对象用于向视图中传值
model.addAttribute("msg", "ControllerTest2");
// 返回视图位置
return "test";
}
}
- 运行tomcat测试。测试路径:http://localhost:8080/springmvc_04/t2
可以发现:两个请求都可以指向一个视图,但是页面结果的结果是不一样的,从这里可以看出视图是被复用的,而控制器与视图之间是弱偶合关系。
注解方式是平时使用的最多的方式!
4.RequestMapping
@RequestMapping
- @RequestMapping注解用于映射url到控制器类或一个特定的处理程序方法。可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。
- 只注解在方法上面。
package com.github.subei.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class ControllerTest3 {
@RequestMapping("/h1")
public String test(){
return "test";
}
}
- 访问路径:http://localhost:8080 / 项目名 /h1
- http://localhost:8080/springmvc_04/h1
- 同时注解类与方法
package com.github.subei.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/s1")
public class ControllerTest3 {
@RequestMapping("/y1")
public String test(Model model){
model.addAttribute("msg","s1/y1");
return "test";
}
}
- 访问路径:http://localhost:8080 / 项目名/ s1/y1 , 需要先指定类的路径再指定方法的路径;
- http://localhost:8080/springmvc_04/s1/y1
5.RestFul
Restful就是一个资源定位及资源操作的风格。不是标准也不是协议,只是一种风格。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。
功能
- 资源:互联网所有的事物都可以被抽象为资源;
- 资源操作:使用POST、DELETE、PUT、GET,使用不同方法对资源进行操作。分别对应 添加、 删除、修改、查询。
传统方式操作资源 :通过不同的参数来实现不同的效果!方法单一,post 和 get
- http://127.0.0.1/item/queryItem.action?id=1 查询,GET
- http://127.0.0.1/item/saveItem.action 新增,POST
- http://127.0.0.1/item/updateItem.action 更新,POST
- http://127.0.0.1/item/deleteItem.action?id=1 删除,GET或POST
使用RESTful操作资源 :可以通过不同的请求方式来实现不同的效果!如下:请求地址一样,但是功能可以不同!
- http://127.0.0.1/item/1 查询,GET
- http://127.0.0.1/item 新增,POST
- http://127.0.0.1/item 更新,PUT
- http://127.0.0.1/item/1 删除,DELETE
案例测试
- 再新建一个类 RestFulController。
package com.github.subei.controller;
import org.springframework.stereotype.Controller;
@Controller
public class RestFulController {
}
- 原来的方式!
package com.github.subei.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class RestFulController {
// 原来的:http://localhost:8080/springmvc_04/add?p1=1&p2=9
// 映射访问路径
@RequestMapping("/add")
public String index( int p1, int p2, Model model){
int result = p1+p2;
// Spring MVC会自动实例化一个Model对象用于向视图中传值
model.addAttribute("msg", "加法结果:"+result);
// 返回视图位置
return "test";
}
}
- 在Spring MVC中可以使用 @PathVariable 注解,让方法参数的值对应绑定到一个URI模板变量上。
package com.github.subei.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class RestFulController {
// 原来的:http://localhost:8080/springmvc_04/add?p1=1&p2=9
// 现在的:http://localhost:8080/springmvc_04/add/45/66
@RequestMapping("/add/{p1}/{p2}")
public String index(@PathVariable int p1, @PathVariable int p2, Model model){
int result = p1+p2;
// Spring MVC会自动实例化一个Model对象用于向视图中传值
model.addAttribute("msg", "加法结果:"+result);
// 返回视图位置
return "test";
}
}
- 测试请求并查看。
- http://localhost:8080/springmvc_04/add/45/66
思考:使用路径变量的好处?
- 使路径变得更加简洁;
- 获得参数更加方便,框架会自动进行类型转换。
- 通过路径变量的类型可以约束访问参数,如果类型不一样,则访问不到对应的请求方法,如这里访问是的路径是/add/9/k,则路径与方法不匹配,而不会是参数转换失败。
- 修改下对应的参数类型,再次测试
package com.github.subei.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class RestFulController {
// 原来的:http://localhost:8080/springmvc_04/add?p1=1&p2=9
// 现在的:http://localhost:8080/springmvc_04/add/45/66
@RequestMapping("/add/{p1}/{p2}")
public String index(@PathVariable int p1, @PathVariable String p2, Model model){
String result = p1+p2;
// Spring MVC会自动实例化一个Model对象用于向视图中传值
model.addAttribute("msg", "字符结果:"+result);
// 返回视图位置
return "test";
}
}
使用method属性指定请求类型
- 用于约束请求的类型,可以收窄请求范围。指定请求谓词的类型如GET, POST, HEAD, OPTIONS, PUT, PATCH, DELETE, TRACE等。
案例测试:
- 增加一个方法
// 映射访问路径,必须是POST请求
@RequestMapping(value = "/home",method = {RequestMethod.POST})
public String index2(Model model){
model.addAttribute("msg", "My warm home!");
return "test";
}
- 使用浏览器地址栏进行访问默认是Get请求,会报错405:
- 将POST修改为GET则正常了;
// 映射访问路径,必须是GET请求
@RequestMapping(value = "/home",method = {RequestMethod.GET})
public String index2(Model model){
model.addAttribute("msg", "My warm home!");
return "test";
}
Spring MVC 的 @RequestMapping 注解能够处理 HTTP 请求的方法, 比如 GET, PUT, POST, DELETE 以及 PATCH。
- 所有的地址栏请求默认都会是 HTTP GET 类型的。
- 方法级别的注解变体有如下几个:组合注解
@GetMapping
@PostMapping
@PutMapping
@DeleteMapping
@PatchMapping
@GetMapping 是一个组合注解,平时使用的会比较多!它所扮演的是 @RequestMapping(method =RequestMethod.GET) 的一个快捷方式。
6.每个程序员都要知道的:小黄鸭调试法
转载自《程序员的那些事》
花了一下午(或一天)在试图解决某个 Bug,后来才知道解决方案很简单,当时就是没有想到。
有个同事正好路过,看到你愁眉苦脸的,问你“怎么了呀?”
“噢,是这样的。我遇到了一个问题,点击这个控件的时……” 当你正准备和同事详细解释的时候,突然灵光一现,你话都没说完,就中断了和同事的倾诉,继续干活了。
同事微微一笑,又走开了。他并没有怪你。
「程序员的那些事」主页君相信大家都有类似的经历。遇到 Bug/问题被卡住了,拉个人过来,和他 blablabla 讲了一通,很多时候中途你就找到了解决办法。
有时候,并不一定要和人倾诉,还可以像其他东西倾诉,强迫自己把遇到的问题,详细地解释出来(一定要说出来)。
其实呢。这种方法,有一个术语:小黄鸭调试法(Rubber Duck Debugging)。
维基百科有解释:小黄鸭调试法是软件工程中使用的调试代码方法之一。就是在程序的调试、纠错或测试过程中,耐心地向小黄鸭解释每一行程序的作用,以此来激发灵感。
名称由来
此概念是参照于一个故事。故事中程序大师随身携带一只小黄鸭,在调试代码的时候会在桌上放上这只小黄鸭,然后详细地向鸭子解释每行代码。