本文章是用来记录自己学习知识时所记录的笔记,并不是对springMVC的完全讲解,用于自己后续复习使用,本文包括后续的文章可能会在基础上不断更新和完善,主要偏向于实际应用的例子。
目录
创建Java项目的5种方式
1、普通Java项目 2、普通JavaWeb项目 3、maven Java项目 4.maven JavaWeb项目 5、springboot项目
创建tomcat项目的流程
(一)配置项目结构
1.创建web项目
2.打开项目结构->模块->添加一个Web框架
3.项目结构->工件->添加Web应用程序:归档(或者在第二步下面可以直接点击创建工件)
(二)配置Tomcat服务器
1.右上角当前文件-编辑,+ 号,添加本地Tomcat服务器
2.添加好后,右边导航栏第二个部署-添加刚才创建好的工件
3.配置服务器的内容
(三)写代码
1.在web目录下(自动生成的),编写一个index.jsp文件作为首页【至此,已经完成了一个简单的web访问界面】
2.在web目录下创建一个WEB-INF目录,里面再编写一个web.xml文件
web.xml文件的作用:
- Servlet 配置
-
- 注册和映射 Servlet 类,指定 URL 路径与 Servlet 类的对应关系。如:
- 所有url以.do结尾都会被拦截,交给controller处理
- 配置 Servlet 的初始化参数和加载顺序。
- 注册和映射 Servlet 类,指定 URL 路径与 Servlet 类的对应关系。如:
- 过滤器(Filter)配置
-
- 定义请求和响应的预处理 / 后处理逻辑,例如字符编码过滤、权限验证等。
- 指定过滤器的应用顺序和作用路径。
- 监听器(Listener)配置
-
- 注册 Web 应用生命周期事件的监听器,例如会话创建 / 销毁、应用启动 / 停止等。
- 安全约束
-
- 定义受保护的资源路径和访问权限。
- 配置用户认证方式(如表单认证、HTTP 基本认证)和角色权限。
3.编写从web.xml中配置的springmvc文件
4.从springmvc文件中配置扫包路径以及视图解析器:
5.此时便再写其他业务代码,如controller包。如果需要写界面,需要写在web/WEB-INF下,但这里面的页面资源不可以随意访问(如url访问),必须通过 Servlet 或控制器转发:JSP 需作为服务器端视图被调用,例如通过RequestDispatcher.forward()
或 Spring MVC 的ModelAndView
。如
返回了suc后,会在视图解析器中拼接上前后缀,然后返回对应的界面。/WEB-INF/pages/suc.jsp
【遇到的问题】
更改web目录后,一共需要变动如下三个地方:
项目结构->模块->新建一个web,改动如下两个地方:
紧接着点击工件,一定要把原来的删除!,然后新建一个,不要在上一步自己生成工件,会有问题,在工件新建一个Web应用程序 -展开型,然后选择原模块,创建好以后,再重新配置下Tomcat中的部署
这样就都完成了
@RequestMapping的使用
RequestMapping注解的作用是建立请求URL和处理方法之间的对应关系
RequestMapping注解可以作用在方法和类上
- 作用在类上:第一级的访问目录
- 作用在方法上:第二级的访问目录
- 细节:路径可以不编写 / 表示应用的根目录开始
属性:
path:指定请求路径的url
value:和path一样
param:匹配请求参数的条件
如@RequestMapping(params = "id")
(必须包含参数id
)
method:请求方法:GET、POST
如@RequestMapping(method = RequestMethod.POST)
记得在controller代码前一定加上@controller注解,不然无法识别到!
请求参数的绑定:
1.绑定机制
- 表单提交的数据都是k-v形式的,如username=hao&password=123
- SpringMVC的参数绑定过程是把表单提交的请求参数,作为 controller 中的方法的参数进行绑定的
- 要求:提交表单的name和controller参数的名称是相同的
2.支持的数据类型
- 基本数据类型和字符串类型
- 实体类型(JavaBean,即自定义的类)
- 集合数据类型(List、map集合等)
实体类型(JavaBean):
1.提交表单的name要和JavaBean实体类中属性名称一致(即如果一个User实体类中有name属性,那么提交的表单名称也必须是name)
2.如果一个JavaBean实体类中包含其他的引用类型,那么表单的name属性需要编写成:对象.属性 例如:address.name
集合数据类型(List、map集合等)
如果集合的属性是实体类,那么编写方式是编写方式:list[0].属性。如list[0].name
代码:
User实体类:
Address实体类:
前端jsp代码:
后端controller代码:
注意,在后端:
1,RequestMapping最前面可以加斜线,比如:@RequestMapping("/testPath")
2,RequestMapping最前面可以不加斜线,比如:@RequestMapping(“testPath”)
3,RequestMapping最前面可以加很多斜线,比如:@RequestMapping("///testPath")
因为spring框架都会进行处理,///test///testPath和/test/testPath按斜线分割后都是{“test”,“testPath”}
但如果在前端,/就是可加可不加了:
加了 '/' 表示从服务器根路径开始,而不加 '/' 表示从相对路径开始
例如我在tomcat中配置
如果是第一个,会变成绝对路径,从根开始访问,点击提交后跳转到
但是第二个,提交的话,会根据上下文进行拼接:
整体就是这样的区别
关于传输日期:
如果前端传入一个日期字符串,如2025/7/2,那么后端在输出Date形式的时候,会输出如下格式:
如果想要格式化为指定格式的日期,可以在controller中加一层处理
或者可以自定义类型转化器,
一、使用@DateTimeFormat注解
这样前端必须使用yyyy-MM-dd的形式,不然会报错
二、如果想自定义数据类型转换,可以实现Converter的接口
因为spring是组件形式的,因此需要注册使其生效,在springmvc.xml配置文件中编写配置
常用注解
@RequestParam注解
作用:把url请求中的指定名称的参数传递给控制器中的形参赋值,加在控制器参数前面
属性
- value:请求参数中的名称
- required:请求参数中是否必须提供此参数,默认值是true,必须提供
代码如下:
@Controller
public class helloController {
@RequestMapping("/hello.do")
public String hello(@RequestParam(value = "username",required = false,defaultValue = "abc")
String name){
System.out.println("SpringMVC! " + name);
return "suc";
}
}
当我启动服务,访问对应的url时,第一次我先不加参数,访问如下url:
查看后端输出:此时应该采用的默认值abc,因为没有指定username
当我在请求中加入参数:
再次查看后端输出
@RequestBody注解
1、作用:该注解用于获取请求体中的内容(GET方法不可以!),加在控制器参数前面
2、属性:required:是否必须有请求体,默认值是true
3、代码如下:
@Controller
public class helloController {
@RequestMapping("/hello.do")
public String hello(@RequestBody String body){
System.out.println("Body Content: " + body);
return "suc";
}
}
我使用postman进行测试,在Body中加入“test”字符串
后端便成功获取到body的内容了,注意不写body会返回400,如果required=true
@PathVariable注解
1、作用:用于从请求的url路径中提取动态参数,并将其绑定在控制器的方法参数上。
它主要用于处理 RESTful 风格的 URL,通过占位符的形式在 URL 中定义变量,使 URL 更加灵活和语义化。
2、属性:指定url中占位符的名称
3、代码如下:
@Controller
public class helloController {
@RequestMapping("/hello.do/{id}")
public String hello(@PathVariable(value="id") Integer id){
System.out.println("PathVariable: " + id);
return "suc";
}
}
当我访问这个指定url时,可以看到结果输出了2,正如预期
@RequestHeader注解
1、作用:获取指定请求头的值
2、属性:value:请求头的名称
3、代码如下:
@Controller
public class helloController {
@RequestMapping("/hello.do/{id}")
public String hello(@RequestHeader(value="Accept") String accept){
System.out.println("Accept: " + accept);
return "suc";
}
}
@CookieValue注解
1.用于获取指定Cookie名称的值
2、属性:value:cookie的名称
3、代码:
@Controller
public class helloController {
@RequestMapping("/hello.do")
public String hello(@CookieValue(value = "JSESSIONID") String cookie){
System.out.println("CookieValue : " + cookie);
return "suc";
}
}
使用postman进行访问,得到如下输出:
问题:html和jsp的区别
- 运行机制:HTML 运行在客户端,由浏览器解释执行;JSP 运行在服务器端,需要 Web 容器提供运行环境。
- 用途:HTML 侧重于静态数据展示;JSP 侧重于和服务器交互,主要用于动态网页开发。[服务器(如 Tomcat)将 JSP 转换为 Servlet(Java 类)执行 Servlet 中的 Java 代码,生成动态内容]
- 嵌入代码:JSP 是一个特殊的 HTML,相当于在 HTML 中嵌入了 Java 代码。
- 加载速度:HTML 在本地计算机上运行时加载速度更快;JSP 需要与 Web 服务器进行交互,因此加载速度较慢。
- try:用于包裹可能会抛出异常的代码块。
- catch:用于捕获异常并处理异常的代码块。
- finally:用于包含无论是否发生异常都需要执行的代码块。
- throw:用于手动抛出异常。
- throws:用于在方法声明中指定方法可能抛出的异常。
- Exception类:是所有异常类的父类,它提供了一些方法来获取异常信息,如 getMessage()、printStackTrace() 等。
异常处理以及自定义异常
异常类(Exception)有两个主要的子类:IOException 类和 RuntimeException 类。
声明自定义异常处理
先定义自定义异常类
此时可以在程序中可以直接抛这种自定义类型的异常
如 throw new SysException("Error!");但是只能抛出这一种类型的异常,遇到其他的异常还需要再处理。
如果此时再写一个SysExceptionResolver,SysExceptionResolver
的本质是 “统一异常响应格式”,无论什么类型的异常,最终都以相同的格式(跳转到 error
页面,显示 errorMsg
)返回给用户。需要实现HandlerExceptionResolver
类,并实现其中的接口resolveException。
此时便可以处理所有的异常,对于
异常如果是自定义异常(SysException类),那么就直接使用其错误信息;
其他异常(如 NullPointerException、IllegalArgumentException):将其转换为 SysException,并统一处理。
- 对用户友好:无论发生什么异常,用户只会看到统一的错误页面(如 “系统繁忙,请稍后再试”),而不是技术细节(如堆栈跟踪)。
比如在Controller中,不捕捉异常,然后主动触发一个异常,然后会被SysExceptionResolver
捕获异常,比如如下的算数异常,会被捕捉到,然后进入resolveException进行处理。因为不是自定义异常,所以会设置为“系统繁忙,请稍后再试”,然后设置到mv,然后让用户跳转到error界面,同样会加上前后缀。
当我访问http://localhost:9000/test_war_exploded/role/findAll.do的时候,然后就会触发除0算数异常,然后返回给用户error.jsp界面
此时我把controller代码改成自定义类型异常
Java Web的三大组件:
Servlet、Filter(过滤器),Listener(监听器)
拦截器是SpringMVC专属
SpringMVC 拦截器
- SpringMVC框架中的拦截器用于对处理器(controller)进行预处理和后处理的技术。
- 可以定义拦截器链,连接器链就是将拦截器按着一定的顺序结成一条链,在访问被拦截的方法时,拦截器链中的拦截器会按着定义的顺序执行。
- 拦截器和过滤器的功能比较类似,有区别
-
- 过滤器Filter是Servlet规范的一部分,任何框架都可以使用过滤器技术。
- 拦截器是SpringMVC框架独有的。
- 过滤器配置了/*,可以拦截任何资源(包括静态资源,如static/js/*)。
- 拦截器只会对控制器Controller中的方法进行拦截。
- 拦截器也是AOP思想的一种实现方式
- 想要自定义拦截器,需要实现HandlerInterceptor接口,该接口中有三个方法:preHandle、postHandle、afterCompletion
preHandle:是在controller方法执行前执行拦截的方法:
-
- 可以使用request或者response跳转到指定的页面
- return true放行,执行下一个拦截器,如果没有拦截器,执行controller中的方法。(取决与springmvc.xml中的配置的拦截器数量,根据配置的顺序顺序执行)
- return false不放行,不会执行controller中的方法。
- 应用场景:权限拦截:
若用户权限不足,可在postHandle
中转发到error.jsp
或登录页。
postHandle:postHandle是controller方法执行后执行的方法,在JSP视图执行前
-
- 可以使用request或者response跳转到指定的页面
- 如果指定了跳转的页面,那么controller方法跳转的页面将不会显示。
afterCompletion:在JSP执行后执行
-
- request或者response不能再跳转页面了
代码:创建一个软件包,在里面创建一个拦截器类:
创建controller类
在springmvc.xml中配置:
这样当我们访问http://localhost:9000/test_war_exploded/dept/findAll.do的时候,会先执行prehandle方法,再执行controller中的方法,再执行postHandle中的方法,将页面跳转至index.jsp,不再是suc.jsp,最后执行afterCompletion方法
输出结果如下:
配置多个拦截器
再编写一个拦截器
在springmvc.xml中配置
再次输出:
遇到的问题:
1、启动tomcat服务器,当提交上传文件后,服务器一直报500错误。根本原因是commons-fileupload和commons-io找不到,但是在maven中已经成功导入。最后发现是tomcat的lib库中缺少commons-fileupload和commons-io,将这两个jar包放入到tomcat的lib库中即可。
2、前端上传文件时,name属性名字一定要和后端中的参数名称一致,不然参数会为null