Java_SSM Learn

xekOnerR Sleep.. zzzZZzZ

Spring

Spring 是一个框架

Spring 注解开发
JAVA/attachments/Pasted image 20260123193906.png

SpringConfig.java 【代替原先 XML】

1
2
3
4
@Configuration  
@ComponentScan("com.xekoner")
public class SpringConfig {
}

@Configuration 注解用于设定当前类为配置类
@ComponentScan("com.xekoner") 注解用于设定扫描路径,此注解只能添加一次; 多个需要使用数组格式: @ComponentScan({"",""})

UserDao.java

1
2
3
4
5
6
@Repository  
public class UserDao {
public void save(){
System.out.println(">>> UserDao.save");
}
}

App.java

1
2
3
4
5
6
7
8
9
public class App {  
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
UserDao userDao = ctx.getBean(UserDao.class);
userDao.save();
}
}

// >>> UserDao.save

依赖注入
UserServices.java

1
2
3
4
5
6
7
8
9
@Service  // 标记服务类
public class UserServices {
@Autowired
private UserDao userDao; // 通过自动装载注解把UserDao找出来后放在userDao变量中
public void doThis(){
System.out.println(">>> UserDao.Do!");
userDao.save();
}
}

随后修改主函数 App.java 的代码逻辑,不去找 UserDao,直接去找 UserServices

1
2
3
4
5
6
7
8
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
UserServices userServices = ctx.getBean(UserServices.class);
userServices.doThis();
}

// >>> UserDao.Do!
// >>> UserDao.save

AOP
面向切面编程,一种编程思想
在不惊动原始设计的基础上为其进行功能增强 (无入侵式)

公用的代码可以提取出来,组成通知类;这个方法叫通知
每一个方法都可以去调用通知类,这叫做连接点
需要执行这个通知的方法找出来定义成切入点
切入点到通知,这叫做切面

案例
导入坐标
pom.xml

1
2
3
4
5
6
7
8
9
10
<dependency>  
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>6.1.3</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>

在 UserDao 中设定一个切入点:
JAVA/attachments/Pasted image 20260123215904.png

UserServices 调用了 UserDao 中的 demo 方法

1
2
3
4
5
6
7
8
9
@Service  
public class UserServices {
@Autowired
private UserDao userDao;
public void doThis(){
System.out.println(">>> UserDao.Do!");
userDao.demo();
}
}

最后以 App 主函数调用 Services 的 doThis 方法【逻辑不变】

1
2
3
4
5
public static void main(String[] args) {  
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
UserServices userServices = ctx.getBean(UserServices.class);
userServices.doThis();
}

切入点想好了之后接下来开始写切面代码:

1
2
3
4
5
6
7
8
9
10
11
12
@Component // 变成 Spring Bean
@Aspect // 告诉 Spring 是一个切面
@EnableAspectJAutoProxy // 开启 AOP 自动代理功能 【不写的话读取不到切面】
public class AdviceDemo {
@Pointcut("execution(void com.xekoner.UserDao.demo())") // 切入点
private void pt(){}

@Before("pt()") // 在pt位置前,也就是demo方法前执行method命令
public void method(){
System.out.println(System.currentTimeMillis());
}
}
JAVA/attachments/Pasted image 20260123220810.png

其中 pt() 仅仅是引用作用,无实际意义

可以看到先运行了 UserServices 中的 doThis 方法
然后切入点运行通知
最后运行 demo 方法

如果在 Services 中把 userDao.demo(); 改为 userDao.save()
那就没有找到切入点也不会去调用通知方法
JAVA/attachments/Pasted image 20260123221123.png

切入点表达式
execution(<public / private> <返回值> <包名><接口名><方法名> <参数>)
比如: execution(void com.xekoner.UserDao.demo())

可以使用 * 匹配任意符号

1
2
3
4
execution(public * com.xekoner.*.UserService.find* (*))
execution(public com.*.*.*.update())
execution(public *..update())
execution(* *..*(..)) 任意的任意的任意的任意(不用仅参考)

Spring MVC

和 Servlet功能等同, 基于JAVA实现的MVC模型的轻量级Web框架

初始案例

导入pom坐标
注意 servlet与tomcat会有冲突,需要指定范围为 provided

1
2
3
4
5
6
7
8
9
10
11
12
<dependency>  
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>

<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>

编写控制类
UserController.java (位于 main.java.con.xekoner.controller)

1
2
3
4
5
6
7
8
9
@Controller // 定义控制类  
public class UserController {
@RequestMapping("/save") // 设置当前操作的访问路径
@ResponseBody // 设置当前操作的返回类型
public String save(){
System.out.println("User Save ... ");
return "{'module':'springmvc'}";
}
}

编写配置类
main.java.com.xekoner.config.SpringMvcConfig

1
2
3
4
@Configuration  
@ComponentScan("com.xekoner.controller")
public class SpringMvcConfig {
}

创建一个容器类
main.java.com.xekoner.config.ServletContainerInitConfig
注意是创建 AnnotationConfigWebApplicationContext 方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class ServletContainerInitConfig extends AbstractDispatcherServletInitializer {  
// 加载SpringMVC配置
@Override
protected WebApplicationContext createServletApplicationContext() {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(SpringMvcConfig.class);
return ctx;
}

// 设置哪些请求归属Spring MVC处理
@Override
protected String[] getServletMappings() {
return new String[]{"/"}; // 表示所有请求都归Spring MVC 处理
}

// 加载Spring 容器配置
@Override
protected WebApplicationContext createRootApplicationContext() {
return null;
}
}
JAVA/attachments/Pasted image 20260125143001.png

传递 List为(Json):

需要添加 jackson 坐标
pom.xml

1
2
3
4
5
<dependency>  
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.19.2</version>
</dependency>

为 Controller添加一个方法

1
2
3
4
5
6
@RequestMapping("/listParamForJson")  
@ResponseBody
public String listParamForJson(@RequestBody List<String> likes){
System.out.println("Json >>> " + likes);
return "{'module':'listParamForJson'}";
}

同时需要在配置中添加

1
2
3
4
5
@Configuration  
@ComponentScan("com.xekoner.controller")
@EnableWebMvc // 需要添加这个
public class SpringMvcConfig {
}
  • 其他参数中的注解
1
2
3
@DateTimeFormat(pattern="yyyy-MM-dd")
@RequestBody // POST
@RequestParam("name") // 指定参数

REST规则开发

接口相同,调用方式不同导致不同的功能

1
2
3
4
5
DELETE /users/1 删除user1
PUT /users 修改user1
POST /users 添加users
GET /users 查询
GET /users 查询

从原先的 @RequestMapping("/save") 改为

1
@RequestMapping(value = "/users",method = RequestMethod.POST)

访问 curl -s -X POST "http://localhost:8080/SpringMVC_war_exploded/users/" 回显

1
>> Save ...
  • 实现 /users/1 查询功能
1
2
3
4
5
6
@RequestMapping(value = "/users/{id}", method = RequestMethod.DELETE)  
@ResponseBody
public String delete(@PathVariable Integer id){
System.out.println(">> delete " + id);
return "delete";
}
  • 完整 UserController.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
@Controller
public class UserController {
@RequestMapping(value = "/users",method = RequestMethod.POST)
@ResponseBody
public String save(){
System.out.println(">> Save ...");
return "save";
}

@RequestMapping(value = "/users/{id}",method = RequestMethod.GET)
@ResponseBody
public String query(@PathVariable Integer id){
System.out.println(">> query " + id);
return "query";
}

@RequestMapping(value = "/users",method = RequestMethod.GET)
@ResponseBody
public String query(){
System.out.println(">> query all ");
return "query";
}

@RequestMapping(value = "/users/{id}", method = RequestMethod.DELETE)
@ResponseBody
public String delete(@PathVariable Integer id){
System.out.println(">> delete " + id);
return "delete";
}

@RequestMapping(value = "/users/{id}",method = RequestMethod.PUT)
@ResponseBody
public String modify(@PathVariable Integer id){
System.out.println(">> modify " + id);
return "modify";
}
}
JAVA/attachments/Pasted image 20260125154148.png

Tips:
相同的路径可以写在最前面

1
2
3
4
@RequestMapping("/users")
// 下面带参数的路径只需要留下最后的即可
...
@RequestMapping(value = "/{id}",method = RequestMethod.GET)

因为所有方法中都带有 @ResponseBody , 所以可以和@Controller 一起省略成:

1
@RestController

方法前的注解也可以省略写

1
2
3
4
5
6
@RequestMapping(method = RequestMethod.POST)
// >>
@PostMapping

// 带参数的可以这样写:
@GetMapping("/{id}")

拦截器

拦截器和过滤器的区别
拦截器为SpringMVC技术,过滤器为Servlet技术
拦截器仅对SpringMVC访问进行增强,而过滤器是对所有访问加强

  • Example
    PorjectInterception.java , Location: com.xekoner.cotroller.Interception.PorjectInterception.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Component
public class PorjectInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle");
return true; // 是否放行【也就是是否执行下面代码】
}

@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
System.out.println("postHandle");
}

@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
System.out.println("afterCompletion");
}
}

同时修改配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
@Configuration  
@ComponentScan("com.xekoner.controller")
@EnableWebMvc
public class SpringMvcConfig implements WebMvcConfigurer { // 实现接口
@Autowired
private PorjectInterceptor porjectInterceptor; // 自动装载 PorjectInterception

@Override
public void addInterceptors(InterceptorRegistry registry) {
// 配置拦截规则【拦截路径】
registry.addInterceptor(porjectInterceptor).addPathPatterns("/users","/users/*");
}
}
JAVA/attachments/Pasted image 20260125163834.png
  • 拦截器执行顺序
1
2
3
Pre1 -> Pre2 -> Pre3 -> Controller
-> Post3 -> Post3 -> Post1
-> After3 -> After2 -> After1

SpringBoot

简化spring应用的搭建以及开发过程

Project Create
JAVA/attachments/Pasted image 20260125170637.png

Dependencies 选择 Web中的 Spring Web

检查pom是否有

1
2
3
4
<dependency>  
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
  • Demo
    BookController.java ; Location: main.java.com.xekoner.springboot.controller.BookController.java
1
2
3
4
5
6
7
8
9
10
@RestController  
@RequestMapping("/books")
public class BookController {

@GetMapping("/{id}")
public String getBooks(@PathVariable Integer id){
System.out.println(">>> Get Books: " + id);
return "hello , springboot!";
}
}

然后直接右键Application,Run即可。

JAVA/attachments/Pasted image 20260125172832.png
  • 打包操作JAVA/attachments/Pasted image 20260125173525.png

boot配置文件

Default Location : resources -> application.properties
或者 application.yml / application.yaml

  • Title: Java_SSM Learn
  • Author: xekOnerR
  • Created at : 2026-01-27 11:45:14
  • Updated at : 2026-01-29 18:23:51
  • Link: https://xekoner.xyz/2026/01/27/Java-ssm/
  • License: This work is licensed under CC BY-NC-SA 4.0.
On this page
Java_SSM Learn