目录
2.1 发送请求中携带数据的key与方法参数的name必须一致
四、注册Servlet三大组件 Servlet/Filter/Listener
一、 静态资源映射规则
只要静态资源放在类路径下: called /static (or /public or /resources or /METAINF/resources
访问 : 当前项目根路径/ + 静态资源名
二、enjoy模板引擎
什么是enjoy模板引擎?
Enjoy 模板引擎是一个 Java 的模板引擎,旨在简化模板的创建和渲染。它的设计目标是提供一个高效、易用的解决方案,适用于生成动态 HTML 或其他文本格式。Enjoy 模板引擎有一些特点和功能,使其在处理模板和动态内容时非常有用。
为什么使用enjoy模板引擎?
1. 简洁的语法
- 变量插值:通过
{{ variable }}
语法来插入变量的值。- 条件判断:使用
{{#if condition}} ... {{/if}}
语法来进行条件判断。- 循环:使用
{{#each items}} ... {{/each}}
语法来循环遍历集合。- 宏定义:定义可复用的模板片段。
2. 高性能
Enjoy 模板引擎经过优化,具有较高的性能,适合处理大规模的模板渲染需求。如果性能是关键考虑因素,它的高效性可能是一个优势。
3. 灵活性
Enjoy 提供了丰富的功能,比如条件判断、循环、宏定义等,使得模板能够处理复杂的逻辑。它允许在模板中进行各种自定义操作,从而提高了灵活性。
4. 易于集成
Enjoy 模板引擎设计上考虑了与不同 Java 应用程序集成的需求。它可以与各种 Java 应用程序和框架兼容,适合用于 Web 应用、服务器端渲染等场景。
5. 小巧轻便
相比于一些大型的模板引擎,Enjoy 可能更加轻量化。这意味着它有较少的依赖和较低的内存开销,对于需要简化配置和减少资源占用的项目尤为合适。
6. 可扩展性
Enjoy 提供了自定义扩展的功能。你可以根据项目的需求自定义模板引擎的行为和功能,例如添加自定义的模板指令或函数。
适用场景
- 高性能 Web 应用:需要快速生成动态 HTML 内容的 Web 应用。
- 服务器端渲染:需要在服务器端处理和渲染模板的场景。
- 资源受限的环境:资源有限或对内存占用有严格要求的环境
1.将页面保存在templates目录下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
成功
</body>
</html>
2.添加坐标
<dependencies>
<dependency>
<groupId>com.jfinal</groupId>
<artifactId>enjoy</artifactId>
<version>5.0.3</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
3.开启配置
@Configuration
public class EnjoyConfig {
@Bean(name = "jfinalViewResolver")
public JFinalViewResolver getJFinalViewResolver() {
// 创建用于整合 spring boot 的 ViewResolver 扩展对象
JFinalViewResolver jfr = new JFinalViewResolver();
// 对 spring boot 进行配置
jfr.setSuffix(".html");
jfr.setContentType("text/html;charset=UTF-8");
jfr.setOrder(0);
// 设置在模板中可通过 #(session.value) 访问 session 中的数据
jfr.setSessionInView(true);
// 获取 engine 对象,对 enjoy 模板引擎进行配置,配置方式与前面章节完全一样
Engine engine = JFinalViewResolver.engine;
// 热加载配置能对后续配置产生影响,需要放在最前面
engine.setDevMode(true);
// 使用 ClassPathSourceFactory 从 class path 与 jar 包中加载模板文件
engine.setToClassPathSourceFactory();
// 在使用 ClassPathSourceFactory 时要使用 setBaseTemplatePath
// 代替 jfr.setPrefix("/view/")
engine.setBaseTemplatePath("/templates/");
// 更多配置与前面章节完全一样
// engine.addDirective(...)
// engine.addSharedMethod(...);
return jfr;
}
}
4.编写代码
/**
*
*@RequestMapping
* 意义:处理用户的请求,相似于doget与dopost
* 位置:
* 类上:一级目录
* 方法:二级目录
* 例如:user/save
* user/delete
* student/save
* student/delete
* 属性:
* value = "",path = ""
* 表示请求路径
* =========================
* method=常量,此请求的类型(get,post),若不设置则此请求适配所有的请求方式
* =========================
* params = ""
* 限制请求参数,例如:params={"msg1","msg2"}表示请求路径中必须携带参数名为msg1与msg2的参数
*
* 注意:1.超链接默认发送的是get请求
* 2.所有请求所携带的参数格式均为:key = value
*
* @DeleteMapping删除
* @PutMapping 修改
* @GetMapping 查询
* @PostMapping 新增
*
* @RequestMapping可以点击查看源码
* @Target({ElementType.METHOD, ElementType.TYPE})
* METHOD==代表修饰方法,TYPE==代表修饰类
* */
@Controller
public class UserController {
@RequestMapping(value="/init")//二级目录
public String userInit(){
System.out.println("==========进入了springMVC的控制器=========");
System.out.println("调用业务层,调用持久层");
return "success";//返回方法执行完要跳转的页面名称
}
@RequestMapping(value="/show1",method ={RequestMethod.POST})
public String show1(){
System.out.println("==========进入了springMVC的控制器=========");
System.out.println("使用post方式发送请求进入");
return "success";//返回方法执行完要跳转的页面名称
}
@RequestMapping(value="/show2",params = {"msg1=aa","msg2=bb"})
public String show2(){
System.out.println("==========进入了springMVC的控制器=========");
System.out.println("限制请求携带的参数");
return "success";//返回方法执行完要跳转的页面名称
}
//使用postman测试
@GetMapping("/show3")
public String show3(){
System.out.println("==========进入了springMVC的控制器=========");
System.out.println("必须使用get方式请求");
return "success";//返回方法执行完要跳转的页面名称
}
@PostMapping("/show4")
public String show4(){
System.out.println("==========进入了springMVC的控制器=========");
System.out.println("必须使用post方式请求");
return "success";//返回方法执行完要跳转的页面名称
}
@DeleteMapping("/show5")
public String show5(){
System.out.println("==========进入了springMVC的控制器=========");
System.out.println("必须使用delete方式请求");
return "success";//返回方法执行完要跳转的页面名称
}
@PutMapping("/show6")
public String show6(){
System.out.println("==========进入了springMVC的控制器=========");
System.out.println("必须使用put方式请求");
return "success";//返回方法执行完要跳转的页面名称
}
}
三、springMVC
1.请求处理
2.参数绑定
springMVC请求参数的绑定:
绑定的机制:SpringMVC 绑定请求参数的过程是通过把表单提交请求参数,作为控制器中方法参数进行绑定的
2.1支持数据类型
1.基本类型参数:
包括基本类型和 String 类型
Emp:
public class Emp implements Serializable {
private int eid;
private String ename;
private String esex;
Dep:
public class Dep implements Serializable {
private int did;
private String dname;
测试页面 one.html
<!DOCTYPE html>
<html lang="cn" xmlns:th="http://www.thymeleaf.org">
<head>
<title>Title</title>
</head>
<body>
<h1>springMVC控制器方法参数作用:接受用户请求中的数据</h1>
<hr/>
<h3>基本类型和 String 类型作为参数</h3>
<a href="/one/show1?msg1=9527">发送请求1</a>
<a href="/one/show2?msg1=jdk&msg2=9527">发送请求2</a>
success.html:
<!DOCTYPE html>
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>spring成功页面</h1>
</body>
</html>
OneController:
@Controller
@RequestMapping("/one")
public class OneController {
/**
* 进入one.html页面
* */
@RequestMapping("/show")
public String show(){
return "one";
}
/***********************基本类型和 String 类型作为参数*********************************/
@RequestMapping("/show1")
public String show1(String msg1){
System.out.println("=====接受到用户发送数据为:"+msg1+"=======");
return "success";
}
@RequestMapping("/show2")
public String show2(String msg1,int msg2){
System.out.println("=====接受到用户发送数据为:"+msg1+"=======");
System.out.println("=====接受到用户发送数据为:"+msg2+"=======");
return "success";
}
2.POJO类型参数:
包括实体类,以及关联的实体类
Emp:
public class Emp implements Serializable {
private int eid;
private String ename;
private String esex;
//emp依赖的dep对象
private Dep dept;
one.html:
<h3>POJO 类型作为参数</h3>
<a href="/one/show3?eid=1&ename=甜甜&esex=女">发送请求3</a>
<form action="/one/show4" method="post">
员工编号:<input type="text" name="eid" ><br/>
员工姓名:<input type="text" name="ename" ><br/>
员工性别:<input type="text" name="esex" ><br/>
部门编号:<input type="text" name="dept.did" ><br/>
部门名称:<input type="text" name="dept.dname" ><br/>
<input type="submit" value="发送请求4"/>
</form>
<form action="/one/map" method="post">
员工编号:<input type="text" name="eids"><br/>
员工姓名:<input type="text" name="enames"><br/>
员工性别:<input type="text" name="esexs"><br/>
<input type="submit" value="发送请求4(map)"/>
</form>
OneController:
/***********************POJO 类型作为参数*********************************/
//单一对象
@RequestMapping("/show3")
public String show3(Emp emp){
System.out.println("=====接受到用户发送数据为:"+emp+"=======");
return "success";
}
//对象嵌套
@RequestMapping("/show4")
public String show4(Emp emp){
System.out.println("=====接受到用户发送数据为:"+emp+"=======");
return "success";
}
//@RequestParam
@RequestMapping("/map")
public String map(@RequestParam Map map){
System.out.println(map);
return "success";
}
3.数组和集合类型参数:
包括 List 结构和 Map 结构的集合(包括数组)
Dep:
public class Dep implements Serializable {
private int did;
private String dname;
//依赖员工集合
private List<Emp> mylist;
private Map<String, Emp> myMap;
one.html:
<h3>POJO 类中包含集合类型参数</h3>
<form action="/one/show5" method="post">
部门编号:<input type="text" name="did" ><br/>
部门名称:<input type="text" name="dname" ><br/>
员工编号1:<input type="text" name="mylist[0].eid" ><br/>
员工姓名1:<input type="text" name="mylist[0].ename" ><br/>
员工性别1:<input type="text" name="mylist[0].esex" ><br/>
员工编号2:<input type="text" name="mylist[1].eid" ><br/>
员工姓名2:<input type="text" name="mylist[1].ename" ><br/>
员工性别2:<input type="text" name="mylist[1].esex" ><br/>
员工编号3:<input type="text" name="myMap['one'].eid" ><br/>
员工姓名3:<input type="text" name="myMap['one'].ename" ><br/>
员工性别3:<input type="text" name="myMap['one'].esex" ><br/>
员工编号4:<input type="text" name="myMap['two'].eid" ><br/>
员工姓名4:<input type="text" name="myMap['two'].ename" ><br/>
员工性别4:<input type="text" name="myMap['two'].esex" ><br/>
<input type="submit" value="发送请求5"/>
</form>
OneController:
/*********************POJO 类中包含集合类型参数*********************************/
@RequestMapping("/show5")
public String show5(Dep dep){
System.out.println("=====接受到用户发送数据为:"+dep+"=======");
return "success";
}
结果:
=====接受到用户发送数据为:Dep{did=1, dname='测试部', mylist=[Emp{eid=1, ename='熊大', esex='男', dept=null}, Emp{eid=2, ename='熊二', esex='女', dept=null}], myMap={one=Emp{eid=3, ename='光头强', esex='男', dept=null}, two=Emp{eid=4, ename='翠花', esex='女', dept=null}}}=======
OneController:
@RequestMapping("/show6")
public String show8(int[] nums){
System.out.println("=====接受到用户发送数据为:"+ Arrays.toString(nums) +"=======");
return "success";
}
one.html:
<a href="/one/show6?nums=123&nums=456&nums=789">发送请求6</a>
4.使用 ServletAPI 对象作为方法参数
- HttpServletRequest 、
- HttpServletResponse 、
- HttpSession 、
- java.security.Principal 、
- Locale 、
- InputStream、
- OutputStream 、
- Reader、
- Writer
/*********************使用 ServletAPI 对象作为方法参数*********************************/
@RequestMapping("/show7")
public String show7(HttpServletRequest request, HttpServletResponse response){
// request.setCharacterEncoding("UTF-8");
// response.setCharacterEncoding("UTF-8");
System.out.println(request);
System.out.println(response);
request.getParameter("msg1");
HttpSession session = request.getSession();
System.out.println(session);
session.setAttribute("","");
try {
response.sendRedirect("重定向");
} catch (IOException e) {
e.printStackTrace();
}
ServletContext applaction = session.getServletContext();
return "success";
}
}
one.html:
<h3>使用 ServletAPI 对象作为方法参数</h3>
<a href="/one/show7">发送请求7</a>
2..使用要求
2.1 发送请求中携带数据的key与方法参数的name必须一致
2.2 数据类型合法
3.springMVC常用注解
1.@RequestParam
1.1 作用:
- 把请求中指定名称的参数给控制器中的形参赋值。
- 如果页面标签名称和方法参数名称不一致,可以使用此注解实现
1.2 属性:
- name属性:设置参数名称
- defaultValue属性:设置默认值
- required属性:设置是否为必传
案例:
@Controller
@RequestMapping("/one")
public class OneController {
/**
* @RequestParam("名称必须与页面标签或者url地址key名称一致")
* */
@RequestMapping("/show1")
public String show1(@RequestParam(name="msg1") String msg){
System.out.println("=====接受到用户发送数据为:"+msg+"=======");
return "success";
}
@RequestMapping("/show2")
public String show2(@RequestParam("msg1") String msg, @RequestParam("msg2") int num){
System.out.println("=====接受到用户发送数据为:"+msg+"=======");
System.out.println("=====接受到用户发送数据为:"+num+"=======");
return "success";
}
@RequestMapping("/show3")
public String show4(@RequestParam(name = "uname",defaultValue = "暂无用户") String name){
System.out.println("账号:"+name);
return "success";
}
2.@RequestBody
2.1 作用:
- 用于获取"请求体"内容。直接使用得到是 key=value&key=value...
- 结构的数据,并可以转换为对象
2.2 属性:
- required:是否必须有请求体。默认值是:true。
/**
* 前后端分离
* @RequestBody可以将json ===》 javaBean
* 注意:
* 1.前端不能使用GET方式提交数据,GET方式无请求体
* {
* "eid":101,
* "ename":"詹姆斯邦德",
* "esex":"绅士"
* }
*
* * */
@RequestMapping("/show4")
public String show4(@RequestBody Emp emp){
System.out.println("=========="+emp+"==========");
return "success";
}
3.@PathVaribale
3.1 作用:
- 用于绑定 url 中的占位符。例如:请求 url 中 /delete/{id},
- 这个{id}就是 url 占位符。url 支持占位符是 spring3.0 之
- 后加入的。是 springmvc 支持 rest 风格 URL 的一个重要标志
3.2 属性:
- value:用于指定 url 中占位符名称。
- required:是否必须提供占位符。
- Restful是一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件。
- 主要用于客户端和服务器交互类的软件,基于这个风格设计的软件可以更简洁,更有层次,
- 更易于实现缓存机制等。
Restful风格的请求是使用“url+请求方式”表示一次请求目的的,HTTP 协议里面四个表示操作方式的动词如下:
- GET:用于获取资源
- POST:用于新建资源
- PUT:用于更新资源
- DELETE:用于删除资源
例如:
新增 POST http://localhost:8080/user/用户名/用户密码/用户性别
查询 GET http://localhost:8080/user/用户ID
删除 delete http://localhost:8080/user/用户ID
修改 put http://localhost:8080/user/用户ID/用户名/用户密码/用户性别
localhost:8080/login?uname=王老师&upwd=123
localhost:8080/login/王老师/123
@PostMapping("/show5/{uname}/{pwd}")
public String show5(@PathVariable("uname") String msg1, @PathVariable("pwd") String msg2){
System.out.println(msg1);
System.out.println(msg2);
return "success";
}
@PostMapping("/show6/{uname}/{pwd}")
public String show6(@PathVariable String uname, @PathVariable String pwd){
System.out.println(uname);
System.out.println(pwd);
return "success";
}
}
4.@RequestHeader
4.1 作用:
- 用于获取请求消息头。
4.2 属性:
- value:提供消息头名称
- required:是否必须有此消息头
@Controller
@RequestMapping("/two")
public class TwoController {
/**
* 获取头信息
* 只获取头信息中的Accept-Language对应的数据(记得使用浏览器测试)
* */
@RequestMapping("/show1")
public String show1(@RequestHeader(value="msg1") String msg){
System.out.println(msg);
return "success";
}
}
4.数据传递
返回值为:字符串
/**
* 返回值为:字符串
* */
@Controller
@RequestMapping("/string")
public class StringController_01 {
/**
* 进入首页
* */
@RequestMapping("/show")
public String show(){
return "index";
}
/*
* 充当试图的逻辑名称,默认页面跳转为请求转发方式
* */
@RequestMapping("/show1")
public String show1(){
System.out.println("=========show1=========");
return "success_String";
}
/*
* 作充当一次请求转发或重定向
* */
@RequestMapping("/show2")
public String show2(){
System.out.println("=========show2=========");
return "redirect:show1";
}
@RequestMapping("/show3")
public String show3(){
System.out.println("=========show3=========");
return "forward:show1";
}
@RequestMapping("/show4")
public String show4(HttpServletRequest request){
System.out.println("=========show4=========");
//1.查询数据库(模拟)
Emp emp = new Emp(1,"张毅老师","男");
//2.获取session
request.getSession().setAttribute("emp",emp);
return "success_String";
}
}
返回值为:json
@ResponseBody 对象====>json
位置:1.类
2.方法
@RequestBody json====>对象
位置:方法参数
@RestController = @Controller + @ResponseBody
@Controller
@RequestMapping("/json")
public class JsonController_02 {
/**
*
* @ResponseBody 对象====>json
* 位置:1.类
* 2.方法
*
*
* @RequestBody json====>对象
* 位置:方法参数
*
* @RestController = @Controller + @ResponseBody
*
* */
@RequestMapping("/show1")
@ResponseBody
public List<Emp> show1(){
//1模拟数据库
Emp emp1 = new Emp(1,"张毅老师","男");
Emp emp2 = new Emp(2,"张毅老师","男");
Emp emp3 = new Emp(3,"张毅老师","男");
List<Emp> list = new ArrayList<>();
list.add(emp1);
list.add(emp2);
list.add(emp3);
return list;
}
@RequestMapping("/show2")
@ResponseBody
public String show2(){
return "helloWorld";
}
}
5.文件上传
5.1 添加坐标
<!--文件上传-->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>
画页面 index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>文件上传</title>
</head>
<body>
文件上传:
<ol>
<li>坐标</li>
<li>制作页面-form表单编码</li>
<li>通过*****接受文件</li>
</ol>
<hr/>
<form action="fileupload" method="post" enctype="multipart/form-data">
用户名:<input name="uname"/><br/>
图片:<input name="upic" type="file"/><br/>
<input type="submit" value="上传"/>
</form>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>文件上传</title>
</head>
<body>
成功页面
<!-- <span>#(session.picname)</span>-->
</body>
</html>
UserController:
package com.ztt.springboot_web_05.controller;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;
/**
* @author 甜甜
* @version 1.0
* @since 2024/8/12
*/
@Controller
public class UserController {
//进入测试页面
@RequestMapping("/show")
public String show(){
return "index";
}
//文件上传
@RequestMapping("/fileupload")
public String fileupload(String uname, MultipartFile upic, HttpServletRequest request){
System.out.println("用户名:"+uname);
System.out.println(upic);
System.out.println(upic.getOriginalFilename());
System.out.println(upic.getName());
return "success";
}
}
四、注册Servlet三大组件 Servlet/Filter/Listener
而由于 Spring Boot 默认是以 jar 包的方式运行嵌入式Servlet容器来启动应用,没有web.xml文件, Spring提供以下Bean来注册三大组件
- ServletRegistrationBean 注册自定义
- Servlet FilterRegistrationBean 注册自定义Filter
- ServletListenerRegistrationBean 注册自定义Listener
MyFilter:
package com.ztt.springboot_web_06.Filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
@WebFilter(urlPatterns = {"/*"})
public class MyFilter implements Filter{
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.println("============请求过滤");
request.setCharacterEncoding("utf-8");
//分水岭
chain.doFilter(request, response);
response.setCharacterEncoding("utf-8");
System.out.println("============响应过滤");
}
}
MyListener:
package com.ztt.springboot_web_06.listener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionAttributeListener;
@WebListener
public class MyListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
ServletContextListener.super.contextInitialized(sce);
System.out.println("-------------MyListener inited !");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
ServletContextListener.super.contextDestroyed(sce);
System.out.println("----------------MyListener Destroy !");
}
}
MyServlet:
package com.ztt.springboot_web_06.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/myServlet")
public class MyServlet extends HttpServlet {
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOException {
System.out.println("进入servlet");
resp.getWriter().println("<h1>hello world</h1>");
};
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
}
如果使用传统 @WebFilter...实现注册也可以 条件:
1.一定是自定义组件
2.启动类添加@ServletComponentScan
五、切换为其他嵌入式Servlet容器
SpringBoot 默认针对Servlet容器提供以下支持:
- Tomcat(默认使用)
- Jetty :支持长连接项目(如:聊天页面)[ˈdʒeti]
- Undertow : 不支持 JSP , 但是并发性能高,是高性能非阻塞的容器[ˈʌndətəʊ]
默认Tomcat容器
在spring-boot-starter-web启动器中默认引入了tomcat容器
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<version>2.1.0.RELEASE</version>
<scope>compile</scope>
</dependency>
切换 Jetty 容器
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!-- 排除tomcat容器 -->
<exclusions>
<exclusion>
<artifactId>spring-boot-starter-tomcat</artifactId>
<groupId>org.springframework.boot</groupId>
</exclusion>
</exclusions>
</dependency>
<!--引入其他的Servlet容器-->
<dependency>
<artifactId>spring-boot-starter-jetty</artifactId>
<groupId>org.springframework.boot</groupId>
</dependency>
使用外置Servlet容器Tomcat9.x
嵌入式Servlet容器:运行启动类就可启动,或将项目打成可执行的 jar 包
优点:简单、快捷;
缺点:默认不支持JSP、优化定制比较复杂使用定制器, 还需要知道 每个功能 的底层原理
外置Servlet容器:配置 Tomcat, 将项目部署到Tomcat中运行