环境说明
- JDK 17
- SpringMVC 6.0.6
- Tomcat 10.0.12
- Thymeleaf 3.1.2.RELEASE
环境准备
添加 SpringMVC 依赖和 Thymeleaf 依赖:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>6.0.6</version>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring6</artifactId>
<version>3.1.2.RELEASE</version>
</dependency>
配置视图解析器和控制器
配置视图解析器,将对应的ViewResolver
注册为Bean(Thymeleaf模板视图解析器配置步骤:模板解析器->模板引擎->视图解析器):
@EnableWebMvc
@ComponentScan("com.example.controller")
@Configuration
public class WebConfig {
//配置模板解析器Bean
@Bean
public SpringResourceTemplateResolver templateResolver(){
SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
//需要解析的HTML页面文件存放的位置,默认是webapp目录下,如果是类路径下需要添加classpath:前缀
resolver.setPrefix("/");
resolver.setSuffix(".html"); //需要解析的后缀名称
resolver.setCharacterEncoding("UTF-8");
return resolver;
}
//配置模板引擎Bean
@Bean
public SpringTemplateEngine springTemplateEngine(ITemplateResolver resolver){
SpringTemplateEngine engine = new SpringTemplateEngine();
engine.setTemplateResolver(resolver);
return engine;
}
// 使用ThymeleafViewResolver作为视图解析器解析HTML页面
@Bean
public ThymeleafViewResolver thymeleafViewResolver(SpringTemplateEngine engine){
ThymeleafViewResolver resolver = new ThymeleafViewResolver();
resolver.setOrder(1);
resolver.setCharacterEncoding("UTF-8");
resolver.setTemplateEngine(engine);
return resolver;
}
}
创建一个Controller,编写方法处理对应地址的请求:
@Controller
public class HelloController {
@RequestMapping("/index")
public ModelAndView index(){
// 返回ModelAndView对象,返回后会经过视图解析器进行处理,这里填入视图名称
return new ModelAndView("index");
}
}
然后在类路径根目录(webapp)下创建一个 html 文件:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>测试</title>
</head>
<body>
<p>欢迎来到GayHub全球最大同性交友网站</p>
</body>
</html>
启动即可访问前端界面。
在Controller 中我们还可以直接向Model模型层进行提供数据:
@RequestMapping("/index")
public ModelAndView index(){
ModelAndView modelAndView = new ModelAndView("index");
modelAndView.getModel().put("key", "33525我和你");
return modelAndView;
}
Thymeleaf 可以收到传递的数据进行解析:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>测试</title>
</head>
<body>
<p>欢迎来到GayHub全球最大同性交友网站</p>
<div th:text="${key}"></div>
</body>
</html>
另外,为了方便,可以在Controller 中直接返回View名称,SpringMVC会将其自动包装为ModelAndView对象(一定要保证视图名称下面出现横线并且按住Ctrl可以跳转,配置才是正确的):
@RequestMapping("/index")
public String index(){
return "index";
}
也可以单独添加一个Model作为形参进行设置,SpringMVC通过依赖注入会自动帮助我们传递实例对象:
@RequestMapping("/index")
public String index(Model model){
model.addAttribute("key", "我和你");
return "index";
}
最后由于我们的页面中可能会有一些静态资源如 css、js等,这里需要配置一下,让静态资源通过Tomcat提供的默认Servlet进行解析,我们需要让配置类实现一下WebMvcConfigurer
接口,这样在Web应用程序启动时,会根据我们重写方法里面的内容进行进一步的配置:
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable(); //开启默认的Servlet
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// 匹配到resourceHandler,将URL映射至location
// 配置静态资源的访问路径,放行静态资源
registry.addResourceHandler("/static/**")
.addResourceLocations("/static/");
}
修改html 文件:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>测试</title>
<!-- 引用静态资源,这里使用Thymeleaf的网址链接表达式,Thymeleaf会自动添加web应用程序的名称到链接前面 -->
<script th:src="@{/static/test.js}"></script>
</head>
<body>
<p>欢迎来到GayHub全球最大同性交友网站</p>
<div th:text="${key}"></div>
</body>
</html>
创建test.js 文件:
window.alert("欢迎来到GayHub全球最大同性交友网站")
启动服务器并访问页面,页面在加载时就会显示一个弹窗。
相关注解
@RequestMapping注解
// 处理多个请求
@RequestMapping({"/index", "/test"})
// 通配符
?:表示任意一个字符,如@RequestMapping("/index/x?")可以匹配/index/xa、/index/xb等。
*:表示任意0-n个字符,如@RequestMapping("/index/*")可以匹配/index/lbwnb、/index/yyds等。
**:表示当前目录或基于当前目录的多级目录,比如@RequestMapping("/index/**")可以匹配/index、/index/xxx等。
// 限定请求方式
@RequestMapping(value = "/index", method = RequestMethod.POST)
衍生注解:@PostMapping、@GetMapping等
// 使用params属性来指定请求必须或不能携带哪些请求参数,也可以直接设定值
@RequestMapping(value = "/index", params = {"username", "!password"})
// header属性用法与params一致,但是它要求的是请求头中需要或者不能携带什么内容
@RequestMapping(value = "/index", headers = "!Connection")
@RequestParam和@RequestHeader详解
// 获取请求中的参数:为方法添加一个形式参数,并在形式参数前面添加@RequestParam注解
// 如果参数名称与形式参数名称相同,即使不添加@RequestParam也能获取到参数值
// 一旦添加@RequestParam,那么此请求必须携带指定参数,
// 也可以将require属性设为false来将属性设定为非必须,或者为参数设定一个默认值
@RequestMapping(value = "/index")
public ModelAndView index(@RequestParam("username") String username){
// 如果需要使用Servlet原本的一些类,直接添加HttpServletRequest或HttpServletResponse等为形式参数即可
@RequestMapping(value = "/index")
public ModelAndView index(HttpServletRequest request){
// 还可以直接将请求参数传递给一个实体类,必须携带set方法或是构造方法中包含所有参数,请求参数会自动根据类中的字段名称进行匹配
@RequestMapping(value = "/index")
public ModelAndView index(User user){
@CookieValue和@SessionAttrbutie
通过使用@CookieValue
注解,我们也可以快速获取请求携带的Cookie信息,@SessionAttrbutie同理:
@RequestMapping(value = "/index")
public ModelAndView index(HttpServletResponse response,
@CookieValue(value = "test", required = false) String test){
System.out.println("获取到cookie值为:"+test);
response.addCookie(new Cookie("champion", "theshy"));
return new ModelAndView("index");
}
@RequestMapping(value = "/index")
public ModelAndView index(@SessionAttribute(value = "test", required = false) String test,
HttpSession session){
session.setAttribute("champion", "theshy");
System.out.println(test);
return new ModelAndView("index");
}
重定向和请求转发
// 只需要在视图名称前面添加一个前缀即可
@RequestMapping("/index")
public String index(){
return "redirect:home";
}
@RequestMapping("/hello")
public String index(){
return "forward:home";
}
@RequestMapping("/home")
public String home(){
return "home";
}
Bean 的作用域
Spring 中涉及到了Bean 的单例和多例模式,Spring MVC 对Bean 的作用域作了进一步的划分:
- request:每次HTTP请求使用request作用域定义的Bean都将产生一个新实例,请求结束后Bean也消失。
- session:对于每一个会话,使用session作用域定义的Bean都将产生一个新实例,会话过期后Bean也消失。
- global session:不常用。
@Bean
@RequestScope // @SessionScope 同理
public TestBean testBean(){
return new TestBean();
}
@Controller
public class MainController {
@Resource
TestBean bean;
@RequestMapping(value = "/index")
public ModelAndView index(){
System.out.println(bean);
return new ModelAndView("index");
}
}
Restful 风格
Restful 风格的设计允许将参数通过URL拼接传到服务端,目的是让URL看起来更简洁实用,并且可以充分使用多种HTTP请求方式(POST/GET/PUT/DELETE),来执行相同请求地址的不同类型操作。即我们可以直接从请求路径中获取参数:
http://localhost:8080/mvc/index/123456
@RequestMapping("/index/{str}")
public String index(@PathVariable String str) {
System.out.println(str);
...