快速体验 导入依赖
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 38 39 <properties > <spring.version > 6.0.6</spring.version > <servlet.api > 9.1.0</servlet.api > <maven.compiler.source > 17</maven.compiler.source > <maven.compiler.target > 17</maven.compiler.target > <project.build.sourceEncoding > UTF-8</project.build.sourceEncoding > </properties > <dependencies > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-context</artifactId > <version > ${spring.version}</version > </dependency > <dependency > <groupId > jakarta.platform</groupId > <artifactId > jakarta.jakartaee-web-api</artifactId > <version > ${servlet.api}</version > <scope > provided</scope > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-webmvc</artifactId > <version > ${spring.version}</version > </dependency > </dependencies > **Controller声明**
Controller
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @Controller public class HelloController { @RequestMapping("/springmvc/hello") @ResponseBody public String hello () { System.out.println("HelloController.hello" ); return "hello springmvc!!" ; } }
Spring MVC 核心组件配置类
声明 springmvc 涉及组件信息的配置类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 @EnableWebMvc @Configuration @ComponentScan(basePackages = "com.atguigu.controller") public class SpringMvcConfig implements WebMvcConfigurer { @Bean public HandlerMapping handlerMapping () { return new RequestMappingHandlerMapping (); } @Bean public HandlerAdapter handlerAdapter () { return new RequestMappingHandlerAdapter (); } }
SpringMVC 环境搭建
对于使用基于 Java 的 Spring 配置的应用程序,建议这样做,如以下示例所示:
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 public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class<?>[] getRootConfigClasses() { return null ; } @Override protected Class<?>[] getServletConfigClasses() { return new Class <?>[] { SpringMvcConfig.class }; } @Override protected String[] getServletMappings() { return new String [] { "/" }; } }
接收数据 访问路径设置 精准路径匹配
1 2 3 4 5 6 7 8 9 10 11 12 @Controller public class UserController { /** * 精准设置访问地址 /user/login */ @RequestMapping(value = {"/user/login"}) @ResponseBody public String login(){ System.out.println("UserController.login"); return "login success!!"; } }
模糊路径匹配
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 @Controller public class ProductController { /** * 路径设置为 /product/* * /* 为单层任意字符串 /product/a /product/aaa 可以访问此handler * /product/a/a 不可以 * 路径设置为 /product/** * /** 为任意层任意字符串 /product/a /product/aaa 可以访问此handler * /product/a/a 也可以访问 */ @RequestMapping("/product/*") @ResponseBody public String show(){ System.out.println("ProductController.show"); return "product show!"; } }
类和方法级别区别
@RequestMapping
注解可以用于类级别和方法级别,它们之间的区别如下:
设置到类级别:@RequestMapping
注解可以设置在控制器类上,用于映射整个控制器的通用请求路径。这样,如果控制器中的多个方法都需要映射同一请求路径,就不需要在每个方法上都添加映射路径。
设置到方法级别:@RequestMapping
注解也可以单独设置在控制器方法上,用于更细粒度地映射请求路径和处理方法。当多个方法处理同一个路径的不同操作时,可以使用方法级别的 @RequestMapping
注解进行更精细的映射。
1 2 3 4 5 6 7 8 9 10 11 12 13 @RequestMapping("/user/login") @RequestMapping("/user/register") @RequestMapping("/user/logout") @RequestMapping("/user") @RequestMapping("/login") @RequestMapping("/register") @RequestMapping("/logout")
附带请求方式限制
默认情况下:@RequestMapping(“/logout”) 任何请求方式都可以访问!
如果需要特定指定:
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 @Controller public class UserController { @RequestMapping(value = {"/user/login"} , method = RequestMethod.POST) @ResponseBody public String login () { System.out.println("UserController.login" ); return "login success!!" ; } @RequestMapping(value = {"/user/register"},method = {RequestMethod.POST,RequestMethod.GET}) @ResponseBody public String register () { System.out.println("UserController.register" ); return "register success!!" ; } }
注意:违背请求方式,会出现 405 异常!!!
进阶注解
还有 @RequestMapping
的 HTTP 方法特定快捷方式变体:
@GetMapping
@PostMapping
@PutMapping
@DeleteMapping
@PatchMapping
1 2 3 @RequestMapping(value="/login",method=RequestMethod.GET) || @GetMapping(value="/login")
注意:进阶注解只能添加到 handler 方法上,无法添加到类上!
接收 param 参数 直接接值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 @Controller @RequestMapping("param") public class ParamController { /** * 前端请求: http://localhost:8080/param/value?name=xx&age=18 * * 可以利用形参列表,直接接收前端传递的param参数! * 要求: 参数名 = 形参名 * 类型相同 * 出现乱码正常,json接收具体解决!! * @return 返回前端数据 */ @GetMapping(value="/value") @ResponseBody public String setupForm(String name,int age){ System.out.println("name = " + name + ", age = " + age); return name + age; } }
@RequestParam 注解
@RequestParam
使用场景:
指定绑定的请求参数名
要求请求参数必须传递
为请求参数提供默认值
1 2 3 4 5 6 7 @GetMapping(value="/data") @ResponseBody public Object paramForm(@RequestParam("name") String name, @RequestParam(value = "stuAge",required = false,defaultValue = "18") int age){ System.out.println("name = " + name + ", age = " + age); return name+age; }
接收相同值
多选框,提交的数据的时候一个 key 对应多个值,我们可以使用集合进行接收!
1 2 3 4 5 6 7 8 9 10 11 /** * 前端请求: http://localhost:8080/param/mul?hbs=吃&hbs=喝 * * 一名多值,可以使用集合接收即可!但是需要使用@RequestParam注解指定 */ @GetMapping(value="/mul") @ResponseBody public Object mulForm(@RequestParam List<String> hbs){ System.out.println("hbs = " + hbs); return hbs; }
实体接收
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public class User { private String name; private int age = 18; // getter 和 setter 略 } @Controller @RequestMapping("param") public class ParamController { // 将请求参数name和age映射到实体类属性上!要求属性名必须等于参数名!否则无法映射! @RequestMapping(value = "/user", method = RequestMethod.POST) @ResponseBody public String addUser(User user) { // 在这里可以使用 user 对象的属性来接收请求参数 System.out.println("user = " + user); return "success"; } }
接收 query 参数 路径传递参数是一种在 URL 路径中传递参数的方式。在 RESTful 的 Web 应用程序中,经常使用路径传递参数来表示资源的唯一标识符或更复杂的表示方式。而 Spring MVC 框架提供了 @PathVariable
注解来处理路径传递参数。
@PathVariable
注解允许将 URL 中的占位符映射到控制器方法中的参数。
例如,如果我们想将 /user/{id}
路径下的 {id}
映射到控制器方法的一个参数中,则可以使用 @PathVariable
注解来实现。
下面是一个使用 @PathVariable
注解处理路径传递参数的示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 /** * 动态路径设计: /user/{动态部分}/{动态部分} 动态部分使用{}包含即可! {}内部动态标识! * 形参列表取值: @PathVariable Long id 如果形参名 = {动态标识} 自动赋值! * @PathVariable("动态标识") Long id 如果形参名 != {动态标识} 可以通过指定动态标识赋值! * * 访问测试: /param/user/1/root -> id = 1 uname = root */ @GetMapping("/user/{id}/{name}") @ResponseBody public String getUser(@PathVariable Long id, @PathVariable("name") String uname) { System.out.println("id = " + id + ", uname = " + uname); return "user_detail"; }
接收 JSON 参数 前端传递 JSON 数据时,Spring MVC 框架可以使用 @RequestBody
注解来将 JSON 数据转换为 Java 对象。@RequestBody
注解表示当前方法参数的值应该从请求体中获取,并且需要指定 value 属性来指示请求体应该映射到哪个参数上。其使用方式和示例代码如下:
定义一个用于接收 JSON 数据的 Java 类,例如:
1 2 3 4 5 6 public class Person { private String name; private int age; private String gender; }
在控制器中,使用 @RequestBody
注解来接收 JSON 数据,并将其转换为 Java 对象,例如:
1 2 3 4 5 6 7 @PostMapping("/person") @ResponseBody public String addPerson (@RequestBody Person person) { return "success" ; }
springmvc handlerAdpater 配置 json 转化器,配置类需要明确:
1 2 3 4 5 6 @EnableWebMvc @Configuration @ComponentScan(basePackages = "com.atguigu.controller") public class SpringMvcConfig implements WebMvcConfigurer {
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.15.0</version>
</dependency>
接收 Cookie 数据 可以使用 @CookieValue
注释将 HTTP Cookie 的值绑定到控制器中的方法参数。
考虑使用以下 cookie 的请求:
1 JSESSIONID=415A4AC178C59DACE0B2C9CA727CDD84
下面的示例演示如何获取 cookie 值:
1 2 3 4 @GetMapping("/demo") public void handle (@CookieValue("JSESSIONID") String cookie) { }
接收请求头数据 可以使用 @RequestHeader
批注将请求标头绑定到控制器中的方法参数。
请考虑以下带有标头的请求:
1 2 3 4 5 6 Host localhost:8080 Accept text/html,application/xhtml+xml,application/xml;q=0.9 Accept-Language fr,en-gb;q=0.7 ,en;q=0.3 Accept-Encoding gzip,deflate Accept-Charset ISO-8859 -1 ,utf-8 ;q=0.7 ,*;q=0.7 Keep-Alive 300
下面的示例获取 Accept-Encoding
和 Keep-Alive
标头的值:
1 2 3 4 5 6 @GetMapping("/demo") public void handle ( @RequestHeader("Accept-Encoding") String encoding, @RequestHeader("Keep-Alive") long keepAlive) { }
返回 JSON 数据 1 2 3 4 5 6 7 8 9 10 @RequestMapping(value = "/user/detail", method = RequestMethod.POST) @ResponseBody public User getUser(@RequestBody User userParam) { System.out.println("userParam = " + userParam); User user = new User(); user.setAge(18); user.setName("John"); //返回的对象,会使用jackson的序列化工具,转成json返回给前端! return user; }
全局异常处理 异常处理控制类,统一定义异常处理 handler 方法!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @RestControllerAdvice public class GlobalExceptionHandler {}声明异常处理hander方法
异常处理 handler 方法和普通的 handler 方法参数接收和响应都一致!
只不过异常处理 handler 方法要映射异常,发生对应的异常会调用!
普通的 handler 方法要使用@RequestMapping 注解映射路径,发生对应的路径调用!
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 38 39 @ExceptionHandler(HttpMessageNotReadableException.class) public Object handlerJsonDateException (HttpMessageNotReadableException e) { return null ; } @ExceptionHandler(NullPointerException.class) public Object handlerNullException (NullPointerException e) { return null ; } @ExceptionHandler(Exception.class) public Object handlerException (Exception e) { return null ; }
SSM 整合 依赖整合和添加 依赖导入
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 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.cgdcge.cc</groupId> <artifactId>ssm-part</artifactId> <version>1.0-SNAPSHOT</version> <packaging>pom</packaging> <modules> <module>smm-demo</module> </modules> <properties> <spring.version>6.0.6</spring.version> <jakarta.annotation-api.version>2.1.1</jakarta.annotation-api.version> <jakarta.jakartaee-web-api.version>9.1.0</jakarta.jakartaee-web-api.version> <jackson-databind.version>2.15.0</jackson-databind.version> <hibernate-validator.version>8.0.0.Final</hibernate-validator.version> <mybatis.version>3.5.11</mybatis.version> <mysql.version>8.0.25</mysql.version> <pagehelper.version>5.1.11</pagehelper.version> <druid.version>1.2.8</druid.version> <mybatis-spring.version>3.0.2</mybatis-spring.version> <jakarta.servlet.jsp.jstl-api.version>3.0.0</jakarta.servlet.jsp.jstl-api.version> <logback.version>1.2.3</logback.version> <lombok.version>1.18.26</lombok.version> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <!--spring pom.xml依赖--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>jakarta.annotation</groupId> <artifactId>jakarta.annotation-api</artifactId> <version>${jakarta.annotation-api.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>jakarta.platform</groupId> <artifactId>jakarta.jakartaee-web-api</artifactId> <version>${jakarta.jakartaee-web-api.version}</version> <scope>provided</scope> </dependency> <!-- jsp需要依赖! jstl--> <dependency> <groupId>jakarta.servlet.jsp.jstl</groupId> <artifactId>jakarta.servlet.jsp.jstl-api</artifactId> <version>${jakarta.servlet.jsp.jstl-api.version}</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>${jackson-databind.version}</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>${mybatis.version}</version> </dependency> <!-- MySQL驱动 mybatis底层依赖jdbc驱动实现,本次不需要导入连接池,mybatis自带! --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql.version}</version> </dependency> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>${pagehelper.version}</version> </dependency> <!-- 整合第三方特殊依赖 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>${mybatis-spring.version}</version> </dependency> <!-- 日志 , 会自动传递slf4j门面--> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>${logback.version}</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>${lombok.version}</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>${druid.version}</version> </dependency> </dependencies> </project>
logback 配置
位置:resources/logback.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 <?xml version="1.0" encoding="UTF-8" ?> <configuration debug ="true" > <appender name ="STDOUT" class ="ch.qos.logback.core.ConsoleAppender" > <encoder > <pattern > [%d{HH:mm:ss.SSS}] [%-5level] [%thread] [%logger] [%msg]%n</pattern > <charset > UTF-8</charset > </encoder > </appender > <root level ="DEBUG" > <appender-ref ref ="STDOUT" /> </root > <logger name ="com.cgdcgd.cc.mybatis" level ="DEBUG" /> </configuration >
控制层配置(SpringMVC 整合) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 位置:config/WebJavaConfig.java(命名随意) /** * * * 1.实现Springmvc组件声明标准化接口WebMvcConfigurer 提供了各种组件对应的方法 * 2.添加配置类注解@Configuration * 3.添加mvc复合功能开关@EnableWebMvc * 4.添加controller层扫描注解 * 5.开启默认处理器,支持静态资源处理 */ @Configuration @EnableWebMvc @ComponentScan("com.cgdcgd.cc.controller") public class WebJavaConfig implements WebMvcConfigurer { //开启静态资源 @Override public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { configurer.enable(); } }
业务层配置编写(AOP/TX 整合) 位置:config/ServiceJavaConfig.java(命名随意)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 @EnableTransactionManagement @EnableAspectJAutoProxy @Configuration @ComponentScan("com.cgdcgd.cc.service") public class ServiceJavaConfig { @Bean public DataSourceTransactionManager transactionManager (DataSource dataSource) { DataSourceTransactionManager transactionManager = new DataSourceTransactionManager (); transactionManager.setDataSource(dataSource); return transactionManager; } }
持久层配置编写(MyBatis 整合) 位置:config/MapperConfig
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 38 39 40 41 42 43 44 45 46 47 48 @Configuration public class MapperConfig { /** * 配置SqlSessionFactoryBean,指定连接池对象和外部配置文件即可 * @param dataSource 需要注入连接池对象 * @return 工厂Bean */ @Bean public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource){ //实例化SqlSessionFactory工厂 SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); //设置连接池 sqlSessionFactoryBean.setDataSource(dataSource); //settings [包裹到一个configuration对象] org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration(); configuration.setMapUnderscoreToCamelCase(true); configuration.setLogImpl(Slf4jImpl.class); configuration.setAutoMappingBehavior(AutoMappingBehavior.FULL); sqlSessionFactoryBean.setConfiguration(configuration); //typeAliases sqlSessionFactoryBean.setTypeAliasesPackage("com.atguigu.pojo"); //分页插件配置 PageInterceptor pageInterceptor = new PageInterceptor(); Properties properties = new Properties(); properties.setProperty("helperDialect","mysql"); pageInterceptor.setProperties(properties); sqlSessionFactoryBean.addPlugins(pageInterceptor); return sqlSessionFactoryBean; } /** * 配置Mapper实例扫描工厂,配置 <mapper <package 对应接口和mapperxml文件所在的包 * @return */ @Bean public MapperScannerConfigurer mapperScannerConfigurer(){ MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer(); //设置mapper接口和xml文件所在的共同包 mapperScannerConfigurer.setBasePackage("com.cgdcgd.cc.mapper"); return mapperScannerConfigurer; } }
位置:resources/jdbc.properties
1 2 3 4 jdbc.user=root jdbc.password=xxbsxy jdbc.url=jdbc:mysql:///mybatis-example jdbc.driver=com.mysql.cj.jdbc.Driver
位置:config/DataSouceConfig
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 @Configuration @PropertySource("classpath:jdbc.properties") public class DataSouceConfig { @Value("root") private String user; @Value("${jdbc.password}") private String password; @Value("${jdbc.url}") private String url; @Value("${jdbc.driver}") private String driver; //数据库连接池配置 @Bean public DataSource dataSource(){ DruidDataSource dataSource = new DruidDataSource(); dataSource.setUsername(user); dataSource.setPassword(password); dataSource.setUrl(url); dataSource.setDriverClassName(driver); return dataSource; } }
容器初始化配置类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public class Config extends AbstractAnnotationConfigDispatcherServletInitializer { //指定root容器对应的配置类 @Override protected Class<?>[] getRootConfigClasses() { return new Class<?>[] {MapperConfig.class, ServiceMvcConfig.class, DataSouceConfig.class }; } //指定web容器对应的配置类 @Override protected Class<?>[] getServletConfigClasses() { return new Class<?>[] { WebMvcConfig.class }; } //指定dispatcherServlet处理路径,通常为 / @Override protected String[] getServletMappings() { return new String[] { "/" }; } }
整合测试
需求
查询所有员工信息,返回对应 json 数据!
controller
1 2 3 4 5 6 7 8 9 10 11 12 13 @Slf4j @RestController @RequestMapping("/emp") public class EmployeeController { @Autowired private EmployeeService employeeService; @GetMapping("find") public List<Employee> find () { List<Employee> all = employeeService.findAll(); return all; } }
service
1 2 3 4 5 6 7 8 9 10 public class EmployeeImpl implements EmployeeService { @Autowired(required = false) private EmployeeMapper employeeMapper; @Override public List<Employee> findAll () { List<Employee> e = employeeMapper.queryList(); return e; } }
mapper
mapper 接口 包:com.cgdcgd.cc.mapper
1 2 3 public interface EmployeeMapper { List<Employee> queryList () ; }
mapper XML 文件位置: resources/com.cgdcgd.cc.mapper
注意新建文件要 com/cgdcgd/cc/mapper
1 2 3 4 5 6 7 8 9 10 11 12 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "https://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper namespace ="com.cgdcgd.cc.mapper.EmployeeMapper" > <select id ="queryList" resultType ="employee" > select * from t_emp </select > </mapper >