## 一、JDBC应用 #### 1、导入`Maven依赖` `JDBC` Maven版本列表:[Maven Repository: com.mysql » mysql-connector-j](https://mvnrepository.com/artifact/com.mysql/mysql-connector-j) ```xml com.mysql mysql-connector-j 9.4.0 ``` #### 2、创建配置文件 在`rescources`资源目录下创建`db.properties` ```properties jdbc.mysql.driver=com.mysql.cj.jdbc.Driver jdbc.mysql.url=jdbc:mysql://[address]:3306/[database]?useUnicode=true&useSSL=false&serverTimezone=Asia/Shanghai&characterEncoding=utf8 jdbc.mysql.username=[username] jdbc.mysql.password=[password] ``` #### 3、新建工具包 在项目目录下新建`util`包 创建`DBUtil.java`类 ```java import java.io.IOException; import java.sql.*; import java.util.Properties; public class DBUtil { public static Connection getConnection() { Connection con = null; try { // 操作Properties的类 Properties properties = new Properties(); properties.load(DBUtil.class.getClassLoader().getResourceAsStream("db.properties")); Class.forName(properties.getProperty("jdbc.mysql.driver")); con = DriverManager.getConnection( properties.getProperty("jdbc.mysql.url"), properties.getProperty("jdbc.mysql.username"), properties.getProperty("jdbc.mysql.password")); } catch (ClassNotFoundException | SQLException e) { throw new RuntimeException(e); } catch (IOException e) { System.out.println("未找到db.properties"); throw new RuntimeException(e); } return con; } public static void closeConnection(Connection con, PreparedStatement pst, ResultSet rs) { try { if (rs != null) rs.close(); if (pst != null) pst.close(); if (con != null) con.close(); } catch (SQLException e) { throw new RuntimeException(e); } } } ``` 创建`CommonUtil.java`类 ```java import java.text.SimpleDateFormat; import java.util.Date; public class CommonUtil { // 获取系统日期 public static String getNewDate() { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); return sdf.format(new Date()); } } ``` #### 4、新建模型包 在项目目录下新建`po`包 包内包含数据库各表对应的对象类。 #### 5、新建数据层 在项目目录下新建`dao`包 包内包含查询数据库各表对应的数据增删改查的接口,以及`impl`包下的实现类。 **常用的语法**: ```java public List exampleMethod(Object obj, ...) { Connection con = DBUtil.getConnection(); PreparedStatement pst = null; ResultSet rs = null; List list = null; try { String sql = "SQL语句"; pst = con.prepareStatement(sql); rs = pst.executeQuery(); list = new ArrayList<>(); while (rs.next()) { list.add(fillObject(rs)); } } catch (SQLException e) { System.out.println(e.getMessage()); } finally { DBUtil.closeConnection(con, pst, rs); } return list; } private Object fillObject(ResultSet rs) throws SQLException { return new Objet(rs.getInt("字段"),...); } ``` #### 6、新建控制层 在项目目录下新建`controller`包 包内包含前端交互所需数据的获取接口,以及`impl`包下的实现类。 #### 7、新建前端 在项目目录下新建`view`包 包内包含前端各个部分,须配合控制层进行修改。 ## 二、MyBatis应用 #### 1、导入`Maven依赖` `MyBatis` Maven版本列表:[Maven Repository: org.mybatis » mybatis](https://mvnrepository.com/artifact/org.mybatis/mybatis) ```xml org.mybatis mybatis 3.5.19 ``` `JDBC` Maven版本列表:[Maven Repository: com.mysql » mysql-connector-j](https://mvnrepository.com/artifact/com.mysql/mysql-connector-j) ```xml com.mysql mysql-connector-j 9.4.0 ``` 如需日志则导入`log4j` Maven版本列表:[Maven Repository: log4j » log4j](https://mvnrepository.com/artifact/log4j/log4j) ```xml log4j log4j 1.2.17 ``` #### 2、创建配置文件 在项目`rescources`资源目录下创建`db.properties` ```properties jdbc.mysql.driver=com.mysql.cj.jdbc.Driver jdbc.mysql.url=jdbc:mysql://[address]:3306/[database]?useUnicode=true&useSSL=false&serverTimezone=Asia/Shanghai&characterEncoding=utf8 jdbc.mysql.username=[username] jdbc.mysql.password=[password] ``` 创建`SqlMapperConfig.xml` ```xml ``` 创建`log4j.properties` ```properties # 日志等级:OFF > FATAL > ERROR > WARN > INFO(默认) > DEBUG(调试用) > TRACE > ALL log4j.rootLogger=ERROR, stdout log4j.logger.org.mybatis.example.BlogMapper=TRACE log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n ``` #### 3、新建工具包 在项目目录下新建`util`包 包内创建`DBUtil.java` ```java import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import java.io.IOException; import java.io.InputStream; public class DBUtil { private static final SqlSessionFactory sqlSessionFactory; static { SqlSessionFactory sqlSessionFactory1; try { // 1、读取Mybatis配置文件 InputStream input = Resources.getResourceAsStream("SqlMapConfig.xml"); // 2、通过配置文件信息,创建SqlSessionFactory sqlSessionFactory1 = new SqlSessionFactoryBuilder().build(input); } catch (IOException e) { sqlSessionFactory1 = null; System.out.println(e.getMessage()); } sqlSessionFactory = sqlSessionFactory1; } public static SqlSessionFactory getSqlSessionFactory() { return sqlSessionFactory; } } ``` 创建`CommonUtil.java`类 ```java import java.text.SimpleDateFormat; import java.util.Date; public class CommonUtil { // 获取系统日期 public static String getNewDate() { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); return sdf.format(new Date()); } } ``` #### 4、新建模型包 在项目目录下新建`po`包 包内包含数据库各表对应的对象类。 #### 5、新建数据层 在项目目录下新建`mapper`、`sqlprovider`包 **常用的注解**: `@Select("SQL语句")` `@Update("SQL语句")` `@Insert("SQL语句")` `@Delete("SQL语句")` `@SelectProvider(type = SelectProvider.class, method = "methodName")` `@UpdateProvider(type = UpdateProvider.class, method = "methodName")` `@InsertProvider(type = InsertProvider.class, method = "methodName")` `@DeleteProvider(type = DeleteProvider.class, method = "methodName")` `*Provider.java`类的实现`动态SQL`常用结构 ```java import org.apache.ibatis.jdbc.SQL; public class XXXSqlProvider { public String updatePoById(PoObject o) { return new SQL() {{ UPDATE("[表名]"); if (o.getField() != null && !o.getFied().isEmpty()) SET("field=#{field}"); if (o.getNumField() != null && o.getNumField() > 0) SET("numField=#{numField}"); WHERE("keyField=#{keyField}"); }}.toString(); } } ``` `@Results`、`@Result`、`@One`多对一、`@Many`一对多 ```java @Results(id = "resultsId", value = { @Result(property = "keyField", column = "keyField", id = true), @Result(property = "field", column = "field"), @Result(property = "foreignKeyField", column = "foreignKeyField", javaType = otherTablePo.class, one = @One(select = "com.to.project.mapper.otherTableMapper.methodLazy")), @Result(property = "foreignKeyFieldList", column = "keyField", javaType = List.class, many = @Many(select = "com.to.project.mapper.otherTableMapper.methodLazy")) }) ``` **注意**:带`id`的`@Results`必须放在方法上声明且必须为该`mapper`中第一或位置较前的方法,否则会检测不到。 `@ResultMap("resultsId")` 获取自增主键,通常搭配`@Insert`、`@InsertProvider`使用 `@Options(useGeneratedKeys = true, keyProperty = "keyField", keyColumn = "keyField")` #### 6、新建控制层 在项目目录下新建`controller`包 包内包含前端交互所需数据的获取接口,以及`impl`包下的实现类。 #### 7、新建前端 在项目目录下新建`view`包 包内包含前端各个部分,须配合控制层进行修改。 ## 三、Spring集成MyBatis应用 #### 1、导入`Maven依赖` `properties` ```xml 7.0.0-M9 ``` `spring-context` Maven版本列表:[Maven Repository: org.springframework » spring-context](https://mvnrepository.com/artifact/org.springframework/spring-context) ```xml org.springframework spring-context ${spring.version} ``` `spring-jdbc` Maven版本列表:[Maven Repository: org.springframework » spring-jdbc](https://mvnrepository.com/artifact/org.springframework/spring-jdbc) ```xml org.springframework spring-jdbc ${spring.version} ``` `aspectjweaver` Maven版本列表:[Maven Repository: org.aspectj » aspectjweaver](https://mvnrepository.com/artifact/org.aspectj/aspectjweaver) ```xml org.aspectj aspectjweaver 1.9.24 ``` `mybatis` Maven版本列表: ```xml org.mybatis mybatis 3.5.19 ``` `mybatis-spring` Maven版本列表:[Maven Repository: org.mybatis » mybatis](https://mvnrepository.com/artifact/org.mybatis/mybatis) ```xml org.mybatis mybatis-spring 3.0.5 ``` `JDBC` Maven版本列表:[Maven Repository: com.mysql » mysql-connector-j ](https://mvnrepository.com/artifact/com.mysql/mysql-connector-j) ```xml com.mysql mysql-connector-j 9.4.0 ``` ##### 完整`dependencies` ```xml org.springframework spring-context ${spring.version} org.springframework spring-jdbc ${spring.version} org.aspectj aspectjweaver 1.9.24 org.mybatis mybatis 3.5.19 org.mybatis mybatis-spring 3.0.5 com.mysql mysql-connector-j 9.4.0 ``` #### 2、创建配置文件 在项目`rescources`资源目录下创建`db.properties` ```properties jdbc.mysql.driver=com.mysql.cj.jdbc.Driver jdbc.mysql.url=jdbc:mysql://[address]:3306/[database]?useUnicode=true&useSSL=false&serverTimezone=Asia/Shanghai&characterEncoding=utf8 jdbc.mysql.username=[username] jdbc.mysql.password=[password] ``` 创建`SpringConfig.xml` ```xml ``` #### 3、新建模型包 在项目目录下新建`po`包 包内包含数据库各表对应的对象类。 #### 4、新建数据层 在项目目录下新建`mapper`、`sqlprovider`包 ```java import org.apache.ibatis.annotations.Mapper; // 告诉Spring这是一个mapper接口,将数据源、SQLFactory全部注入到这个接口中 @Mapper public interface XXXMapper { // 数据查询方法 } ``` ##### 常用的注解 `@Mapper` `@Select("SQL语句")` `@Update("SQL语句")` `@Insert("SQL语句")` `@Delete("SQL语句")` `@SelectProvider(type = SelectProvider.class, method = "methodName")` `@UpdateProvider(type = UpdateProvider.class, method = "methodName")` `@InsertProvider(type = InsertProvider.class, method = "methodName")` `@DeleteProvider(type = DeleteProvider.class, method = "methodName")` `*Provider.java`类的实现`动态SQL`常用结构 ```java import org.apache.ibatis.jdbc.SQL; public class XXXSqlProvider { public String updatePoById(PoObject o) { return new SQL() {{ UPDATE("[表名]"); if (o.getField() != null && !o.getFied().isEmpty()) SET("field=#{field}"); if (o.getNumField() != null && o.getNumField() > 0) SET("numField=#{numField}"); WHERE("keyField=#{keyField}"); }}.toString(); } } ``` `@Results`、`@Result`、`@One`多对一、`@Many`一对多 ```java @Results(id = "resultsId", value = { @Result(property = "keyField", column = "keyField", id = true), @Result(property = "field", column = "field"), @Result(property = "foreignKeyField", column = "foreignKeyField", javaType = otherTablePo.class, one = @One(select = "com.to.project.mapper.otherTableMapper.methodLazy")), @Result(property = "foreignKeyFieldList", column = "keyField", javaType = List.class, many = @Many(select = "com.to.project.mapper.otherTableMapper.methodLazy")) }) ``` **注意**:带`id`的`@Results`必须放在方法上声明且必须为该`mapper`中第一或位置较前的方法,否则会检测不到。 `@ResultMap("resultsId")` 获取自增主键,通常搭配`@Insert`、`@InsertProvider`使用 `@Options(useGeneratedKeys = true, keyProperty = "keyField", keyColumn = "keyField")` #### 5、新建服务层 在项目目录下新建`service`包 包内包含前端交互所需数据的获取接口,以及`impl`包下的实现类。 ```java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; @Service("xxxService") public class XXXServiceImpl implements XXXService { private XXXMapper xxxMapper; public XXXServiceImpl() { } @Autowired public XXXServiceImpl(XXXMapper xxxMapper) { this.xxxMapper = xxxMapper; } @Override @Transactional(propagation = Propagation.SUPPORTS) public PoObject getPoById(int id) { // 非事务(SELECT)方法实现代码 if (no <= 0) return null; return xxxMapper.getPoById(id); } @Override @Transactional(propagation = Propagation.REQUIRED) public void txMethod(...) throws Exception { // 事务方法实现代码 } } ``` **注意**:需要事务管理的service,在方法上加`@Transactional`注解即可,必须为`public方法`才可以,不要捕获异常,要让异常自动抛出,否则不能进行事务回滚。 ##### 事务传播机制模式 `REQUIRED`(默认):如果当前存在事务,则加入该事务;否则创建新事务。 `SUPPORTS`:如果当前存在事务,则加入;否则以非事务方式执行。 `MANDATORY`:强制要求存在事务,否则抛`IllegalTransactionStateException`。 `REQUIRES_NEW`:无论当前是否有事务,都创建新事务。原事务暂停,新事务独立提交/回滚。 `NOT_SUPPORTED`:以非事务方式执行,挂起当前事务(如果存在)。 `NEVER`:禁止事务存在,否则抛异常。 `NESTED`:如果当前有事务,则在嵌套事务(子事务)中执行,子事务可单独回滚;否则行为同`REQUIRED`。 #### 6、新建前端 在项目目录下新建`view`包 包内包含前端各个部分,须配合服务层进行修改。 ## 四、SpringMVC #### 1、导入`Maven依赖` `properties` ```xml 7.0.0-M9 2.19.2 ``` `spring-context` Maven版本列表:[Maven Repository: org.springframework » spring-context](https://mvnrepository.com/artifact/org.springframework/spring-context) ```xml org.springframework spring-context ${spring.version} ``` `spring-webmvc` Maven版本列表:[Maven Repository: org.springframework » spring-webmvc](https://mvnrepository.com/artifact/org.springframework/spring-webmvc) ```xml org.springframework spring-webmvc ${spring.version} ``` `jakarta.servlet-api` Maven版本列表:[Maven Repository: jakarta.servlet » jakarta.servlet-api](https://mvnrepository.com/artifact/jakarta.servlet/jakarta.servlet-api) ```xml jakarta.servlet jakarta.servlet-api 6.2.0-M1 provided ``` `jackson-core` Maven版本列表:[Maven Repository: tools.jackson.core » jackson-core](https://mvnrepository.com/artifact/tools.jackson.core/jackson-core) ```xml com.fasterxml.jackson.core jackson-core ${jackson.version} ``` `jackson-databind` Maven版本列表:[Maven Repository: tools.jackson.core » jackson-databind](https://mvnrepository.com/artifact/tools.jackson.core/jackson-databind) ```xml com.fasterxml.jackson.core jackson-databind ${jackson.version} ``` `jackson-annotations` Maven版本列表:[Maven Repository: com.fasterxml.jackson.core » jackson-annotations](https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations) ```xml com.fasterxml.jackson.core jackson-annotations ${jackson.version} ``` `commons-fileupload2-jakarta-servlet6` Maven版本列表:[Maven Repository: org.apache.commons » commons-fileupload2-jakarta-servlet6](https://mvnrepository.com/artifact/org.apache.commons/commons-fileupload2-jakarta-servlet6) ```xml org.apache.commons commons-fileupload2-jakarta-servlet6 2.0.0-M4 ``` `commons-io` Maven版本列表:[Maven Repository: commons-io » commons-io](https://mvnrepository.com/artifact/commons-io/commons-io) ```xml commons-io commons-io 2.20.0 ``` ##### 完整`dependencies` ```xml org.springframework spring-context ${spring.version} org.springframework spring-webmvc ${spring.version} jakarta.servlet jakarta.servlet-api 6.2.0-M1 provided com.fasterxml.jackson.core jackson-core ${jackson.version} com.fasterxml.jackson.core jackson-databind ${jackson.version} com.fasterxml.jackson.core jackson-annotations ${jackson.version} org.apache.commons commons-fileupload2-jakarta-servlet6 2.0.0-M4 commons-io commons-io 2.20.0 ``` #### 2、创建配置文件 在项目`rescources`资源目录下创建 ##### `SpringConfig.xml` ```xml ``` 在项目`src/main/webapp/WEB-INF/`目录下修改 ##### `web.xml` ```xml char encoding filter encodingFilter org.springframework.web.filter.CharacterEncodingFilter encoding UTF-8 encodingFilter /* springMvc org.springframework.web.servlet.DispatcherServlet contextConfigLocation classpath*:SpringConfig.xml 1 10485760 10485760 0 springMvc / 30 ``` #### 3、新建模型包 在项目目录下新建`po`包 包内包含数据库各表对应的对象类。 #### 4、新建数据层(须集成MyBatis) 在项目目录下新建`mapper`、`sqlprovider`包 ```java import org.apache.ibatis.annotations.Mapper; // 告诉Spring这是一个mapper接口,将数据源、SQLFactory全部注入到这个接口中 @Mapper public interface XXXMapper { // 数据查询方法 } ``` **常用的注解**: `@Mapper` `@Select("SQL语句")` `@Update("SQL语句")` `@Insert("SQL语句")` `@Delete("SQL语句")` `@SelectProvider(type = SelectProvider.class, method = "methodName")` `@UpdateProvider(type = UpdateProvider.class, method = "methodName")` `@InsertProvider(type = InsertProvider.class, method = "methodName")` `@DeleteProvider(type = DeleteProvider.class, method = "methodName")` `*Provider.java`类的实现`动态SQL`常用结构 ```java import org.apache.ibatis.jdbc.SQL; public class XXXSqlProvider { public String updatePoById(PoObject o) { return new SQL() {{ UPDATE("[表名]"); if (o.getField() != null && !o.getFied().isEmpty()) SET("field=#{field}"); if (o.getNumField() != null && o.getNumField() > 0) SET("numField=#{numField}"); WHERE("keyField=#{keyField}"); }}.toString(); } } ``` `@Results`、`@Result`、`@One`多对一、`@Many`一对多 ```java @Results(id = "resultsId", value = { @Result(property = "keyField", column = "keyField", id = true), @Result(property = "field", column = "field"), @Result(property = "foreignKeyField", column = "foreignKeyField", javaType = otherTablePo.class, one = @One(select = "com.to.project.mapper.otherTableMapper.methodLazy")), @Result(property = "foreignKeyFieldList", column = "keyField", javaType = List.class, many = @Many(select = "com.to.project.mapper.otherTableMapper.methodLazy")) }) ``` **注意**:带`id`的`@Results`必须放在方法上声明且必须为该`mapper`中第一或位置较前的方法,否则会检测不到。 `@ResultMap("resultsId")` 获取自增主键,通常搭配`@Insert`、`@InsertProvider`使用 `@Options(useGeneratedKeys = true, keyProperty = "keyField", keyColumn = "keyField")` #### 5、新建控制层 在项目目录下创建`controller`包 ##### 常用注解 `@RequestMapping("/URL")`/`@GetMapping("/URL")`/`@PostMapping("/URL")`/`@PutMapping("/URL")`/`@PatchMapping("/URL")`/`@DeleteMapping("/URL")`:用于建立请求URL与处理请求方法之间的对应关系,同种类型的请求URL路径不能出现重复 `@ResponseBody`:将返回的数据以`response.getWriter()`的形式输出给客户端 `@RequestBody`:规定参数注入所需的值需要在RequestBody中寻找 `@RequestParam(name = "参数名",required = 是否必须)`:为进行访问时设置所需提交的参数设置别名映射,常用在参数类型前 `@RequestHeader('请求头key')`:获取请求头信息,通过在参数前面添加注解,请求头对应的`value`会自动注入到参数中 `@PathVariable("参数名")`:通过动态路径映射并注入参数值,通常用在RestFul风格`("/path/{参数}/...")`Get请求时获取参数 ##### 常用转跳方式 重定向:方法不能为响应体且返回类型为`String`,返回`"redirect:/URL"`支持RestFul动态入参 ```java @RequestMapping("/redirect") public String testRedirect(RedirectAttributes redirectAttributes){ redirectAttributes.addAttribute("name","张三"); redirectAttributes.addAttribute("age","18"); redirectAttributes.addAttribute("sex","男"); return "redirect:restful/{name}/{age}/{sex}"; } ``` 转发:方法不能为响应体且返回类型为`String`,返回`"forward:/URL"`不支持RestFul动态入参 ```java @RequestMapping("/forward") public String testForward(){ return "forward:restful/张三/18/男"; } ``` ##### 常用入参方式 ###### 普通参数 ```java @RequestMapping("/hello") @ResponseBody public String hello(@RequestParam(name = "age", required = false) Integer age, @RequestParam(name = "money", defaultValue = "0") double money, @RequestParam("name") String name) { return "get - age:" + age + ",money:" + money + ",name:" + name; } ``` **注意**:当`required = true`和`defaultValue = ..`时可以为空,前者必须使用引用数据类型为参数类型,否则会报赋值错误 ###### RestFul风格参数 ```java @RequestMapping("/restful/{name}/{age}/{sex}") @ResponseBody public User restful(@PathVariable("name") String name, @PathVariable("age") int age, @PathVariable("sex") String sex) { return new User("获取:"+name, age, sex); } ``` ###### 请求头参数 ```java @RequestMapping("/hello") @ResponseBody public String hello(@RequestHeader("Host") String host, @RequestHeader("Accept") String accept) { return "Host:" + host + "; Accept:" + accept; } // 使用HttpServletRequest对象获取 @RequestMapping("/hello") @ResponseBody public String hello(HttpServletRequest request) { return request.getHeader("host"); } ``` ###### 对象参数 ```java @GetMapping("/hello") @ResponseBody public String hello(User user) { return user; } @PostMapping(value = "/hello") @ResponseBody public User hello(@RequestBody User user) { return user; } ``` ###### 返回列表 ```java @RequestMapping("/list-get") @ResponseBody public List listGet() { List list = new ArrayList<>(); list.add(new User("张三", 18, "男")); list.add(new User("李四", 19, "男")); list.add(new User("王五", 20, "男")); list.add(new User("赵六", 21, "男")); return list; } ``` **注意**:直接返回对象时必须添加Jackson依赖才能顺利转换成Json格式,在Post方法中必须使用`@RequestBody`注解才能正常解析Json对象 ##### 常用会话追踪 ###### Cookie ```java @RequestMapping("/cookie-set") @ResponseBody public String cookieSet(HttpServletRequest request, HttpServletResponse response) { // 创建一个Cookie对象 Cookie cookie = new Cookie("test", "test"); // 设置Cookie有效期 一天 cookie.setMaxAge(60 * 60 * 24); // 响应添加Cookie response.addCookie(cookie); return "success"; } @RequestMapping("/cookie-get") @ResponseBody public String cookieGet(HttpServletRequest request, HttpServletResponse response) { // 设置页面可以显示中文 response.setContentType("text/html;charset=utf-8"); // 获取请求的Cookies Cookie[] cookies = request.getCookies(); if (cookies != null) { for (Cookie cookie : cookies) { // 通过Cookie名来对比 if (cookie.getName().equals("test")) return "Cookie测试"; // 通过Cookie值来对比 if (cookie.getValue().equals("test")) return "Cookie测试"; } } return "Not Found Cookie:test."; } ``` **注意**:Cookie在赋值时不可以赋值中文等非ASCII字符。 ###### Session ```java @RequestMapping("/session-set") @ResponseBody public String sessionSet(HttpSession session, HttpServletRequest request) { // 手动获取/创建Session // request.getSession(); User user = new User("张三", 18, "男"); // 设置Session内容 session.setAttribute("user", user); return session.getId(); } @RequestMapping("/session-get") @ResponseBody public User sessionGet(HttpSession session) { // 获取Session内容 return (User) session.getAttribute("user"); } ``` #### 6、新建拦截器 在项目目录下创建`interceptor`包 ```java import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.jspecify.annotations.Nullable; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; public class *Interceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("处理器处理前"); // 获取Session HttpSession session = request.getSession(); if (session.getAttribute("属性名") != null) return true; // URL重定向 response.sendRedirect("URL"); return false; // true为放行 } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception { System.out.println("处理器处理后"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception { System.out.println("视图渲染后"); } } ``` 记得去`SpringConfig.xml`文件中配置拦截器 #### 7、文件上传处理器 `FileController.java` ```java import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import java.io.File; import java.io.IOException; import java.util.UUID; @Controller @RequestMapping("/upload") public class FileController { @PostMapping("/file") @ResponseBody public String uploadFile(@RequestBody @RequestParam("file") MultipartFile file) { String path = "保存的路径"; String fileName = file.getOriginalFilename(); String newFileName; if (fileName != null) { // 重命名文件 newFileName = UUID.randomUUID() + fileName.substring(fileName.lastIndexOf(".")); File file1 = new File(path, newFileName); if (!file1.exists()){ // 创建保存路径的所有文件夹 file1.mkdirs(); } try { // 保存文件 file.transferTo(file1); } catch (IOException e) { throw new RuntimeException(e); } finally { // 输出文件所在位置 System.out.println(file1); } } return "ok"; } } ``` `` ```html ``` #### 8、新建前端 在项目目录下新建`view`包 包内包含前端各个部分,须配合服务层进行修改。 ``` Loading... ## 一、JDBC应用 #### 1、导入`Maven依赖` `JDBC` Maven版本列表:[Maven Repository: com.mysql » mysql-connector-j](https://mvnrepository.com/artifact/com.mysql/mysql-connector-j) ```xml <!-- https://mvnrepository.com/artifact/com.mysql/mysql-connector-j --> <dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <version>9.4.0</version> </dependency> ``` #### 2、创建配置文件 在`rescources`资源目录下创建`db.properties` ```properties jdbc.mysql.driver=com.mysql.cj.jdbc.Driver jdbc.mysql.url=jdbc:mysql://[address]:3306/[database]?useUnicode=true&useSSL=false&serverTimezone=Asia/Shanghai&characterEncoding=utf8 jdbc.mysql.username=[username] jdbc.mysql.password=[password] ``` #### 3、新建工具包 在项目目录下新建`util`包 创建`DBUtil.java`类 ```java import java.io.IOException; import java.sql.*; import java.util.Properties; public class DBUtil { public static Connection getConnection() { Connection con = null; try { // 操作Properties的类 Properties properties = new Properties(); properties.load(DBUtil.class.getClassLoader().getResourceAsStream("db.properties")); Class.forName(properties.getProperty("jdbc.mysql.driver")); con = DriverManager.getConnection( properties.getProperty("jdbc.mysql.url"), properties.getProperty("jdbc.mysql.username"), properties.getProperty("jdbc.mysql.password")); } catch (ClassNotFoundException | SQLException e) { throw new RuntimeException(e); } catch (IOException e) { System.out.println("未找到db.properties"); throw new RuntimeException(e); } return con; } public static void closeConnection(Connection con, PreparedStatement pst, ResultSet rs) { try { if (rs != null) rs.close(); if (pst != null) pst.close(); if (con != null) con.close(); } catch (SQLException e) { throw new RuntimeException(e); } } } ``` 创建`CommonUtil.java`类 ```java import java.text.SimpleDateFormat; import java.util.Date; public class CommonUtil { // 获取系统日期 public static String getNewDate() { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); return sdf.format(new Date()); } } ``` #### 4、新建模型包 在项目目录下新建`po`包 包内包含数据库各表对应的对象类。 #### 5、新建数据层 在项目目录下新建`dao`包 包内包含查询数据库各表对应的数据增删改查的接口,以及`impl`包下的实现类。 **常用的语法**: ```java public List<Object> exampleMethod(Object obj, ...) { Connection con = DBUtil.getConnection(); PreparedStatement pst = null; ResultSet rs = null; List<Object> list = null; try { String sql = "SQL语句"; pst = con.prepareStatement(sql); rs = pst.executeQuery(); list = new ArrayList<>(); while (rs.next()) { list.add(fillObject(rs)); } } catch (SQLException e) { System.out.println(e.getMessage()); } finally { DBUtil.closeConnection(con, pst, rs); } return list; } private Object fillObject(ResultSet rs) throws SQLException { return new Objet(rs.getInt("字段"),...); } ``` #### 6、新建控制层 在项目目录下新建`controller`包 包内包含前端交互所需数据的获取接口,以及`impl`包下的实现类。 #### 7、新建前端 在项目目录下新建`view`包 包内包含前端各个部分,须配合控制层进行修改。 ## 二、MyBatis应用 #### 1、导入`Maven依赖` `MyBatis` Maven版本列表:[Maven Repository: org.mybatis » mybatis](https://mvnrepository.com/artifact/org.mybatis/mybatis) ```xml <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.19</version> </dependency> ``` `JDBC` Maven版本列表:[Maven Repository: com.mysql » mysql-connector-j](https://mvnrepository.com/artifact/com.mysql/mysql-connector-j) ```xml <!-- https://mvnrepository.com/artifact/com.mysql/mysql-connector-j --> <dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <version>9.4.0</version> </dependency> ``` 如需日志则导入`log4j` Maven版本列表:[Maven Repository: log4j » log4j](https://mvnrepository.com/artifact/log4j/log4j) ```xml <!-- https://mvnrepository.com/artifact/log4j/log4j --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> ``` #### 2、创建配置文件 在项目`rescources`资源目录下创建`db.properties` ```properties jdbc.mysql.driver=com.mysql.cj.jdbc.Driver jdbc.mysql.url=jdbc:mysql://[address]:3306/[database]?useUnicode=true&useSSL=false&serverTimezone=Asia/Shanghai&characterEncoding=utf8 jdbc.mysql.username=[username] jdbc.mysql.password=[password] ``` 创建`SqlMapperConfig.xml` ```xml <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <!-- 加载其他配置文件 --> <properties resource="db.properties"/> <settings> <!-- 如果aggressiveLazyLoading为true,即使lazyLoadingEnable为true也没有效果 --> <setting name="lazyLoadingEnabled" value="true"/> <!-- 全局延迟加载开关 默认为false --> <setting name="aggressiveLazyLoading" value="false"/> <!-- 延迟加载整个对象 默认为true,false:表示对象的每个属性都延迟加载 --> </settings> <typeAliases> <package name="com.to.project.po"/> </typeAliases> <!-- 配置数据源 --> <environments default="development"> <environment id="development"> <!-- 数据源的事务管理 --> <transactionManager type="JDBC"/> <!-- 配置JDBC数据库信息 --> <dataSource type="POOLED"> <property name="driver" value="${jdbc.mysql.driver}"/> <property name="url" value="${jdbc.mysql.url}"/> <property name="username" value="${jdbc.mysql.username}"/> <property name="password" value="${jdbc.mysql.password}"/> </dataSource> </environment> </environments> <!-- 配置映射文件 --> <mappers> <package name="com.to.project.mapper"/> </mappers> </configuration> ``` 创建`log4j.properties` ```properties # 日志等级:OFF > FATAL > ERROR > WARN > INFO(默认) > DEBUG(调试用) > TRACE > ALL log4j.rootLogger=ERROR, stdout log4j.logger.org.mybatis.example.BlogMapper=TRACE log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n ``` #### 3、新建工具包 在项目目录下新建`util`包 包内创建`DBUtil.java` ```java import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import java.io.IOException; import java.io.InputStream; public class DBUtil { private static final SqlSessionFactory sqlSessionFactory; static { SqlSessionFactory sqlSessionFactory1; try { // 1、读取Mybatis配置文件 InputStream input = Resources.getResourceAsStream("SqlMapConfig.xml"); // 2、通过配置文件信息,创建SqlSessionFactory sqlSessionFactory1 = new SqlSessionFactoryBuilder().build(input); } catch (IOException e) { sqlSessionFactory1 = null; System.out.println(e.getMessage()); } sqlSessionFactory = sqlSessionFactory1; } public static SqlSessionFactory getSqlSessionFactory() { return sqlSessionFactory; } } ``` 创建`CommonUtil.java`类 ```java import java.text.SimpleDateFormat; import java.util.Date; public class CommonUtil { // 获取系统日期 public static String getNewDate() { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); return sdf.format(new Date()); } } ``` #### 4、新建模型包 在项目目录下新建`po`包 包内包含数据库各表对应的对象类。 #### 5、新建数据层 在项目目录下新建`mapper`、`sqlprovider`包 **常用的注解**: `@Select("SQL语句")` `@Update("SQL语句")` `@Insert("SQL语句")` `@Delete("SQL语句")` `@SelectProvider(type = SelectProvider.class, method = "methodName")` `@UpdateProvider(type = UpdateProvider.class, method = "methodName")` `@InsertProvider(type = InsertProvider.class, method = "methodName")` `@DeleteProvider(type = DeleteProvider.class, method = "methodName")` `*Provider.java`类的实现`动态SQL`常用结构 ```java import org.apache.ibatis.jdbc.SQL; public class XXXSqlProvider { public String updatePoById(PoObject o) { return new SQL() {{ UPDATE("[表名]"); if (o.getField() != null && !o.getFied().isEmpty()) SET("field=#{field}"); if (o.getNumField() != null && o.getNumField() > 0) SET("numField=#{numField}"); WHERE("keyField=#{keyField}"); }}.toString(); } } ``` `@Results`、`@Result`、`@One`多对一、`@Many`一对多 ```java @Results(id = "resultsId", value = { @Result(property = "keyField", column = "keyField", id = true), @Result(property = "field", column = "field"), @Result(property = "foreignKeyField", column = "foreignKeyField", javaType = otherTablePo.class, one = @One(select = "com.to.project.mapper.otherTableMapper.methodLazy")), @Result(property = "foreignKeyFieldList", column = "keyField", javaType = List.class, many = @Many(select = "com.to.project.mapper.otherTableMapper.methodLazy")) }) ``` **注意**:带`id`的`@Results`必须放在方法上声明且必须为该`mapper`中第一或位置较前的方法,否则会检测不到。 `@ResultMap("resultsId")` 获取自增主键,通常搭配`@Insert`、`@InsertProvider`使用 `@Options(useGeneratedKeys = true, keyProperty = "keyField", keyColumn = "keyField")` #### 6、新建控制层 在项目目录下新建`controller`包 包内包含前端交互所需数据的获取接口,以及`impl`包下的实现类。 #### 7、新建前端 在项目目录下新建`view`包 包内包含前端各个部分,须配合控制层进行修改。 ## 三、Spring集成MyBatis应用 #### 1、导入`Maven依赖` `properties` ```xml <properties> <spring.version>7.0.0-M9</spring.version> </properties> ``` `spring-context` Maven版本列表:[Maven Repository: org.springframework » spring-context](https://mvnrepository.com/artifact/org.springframework/spring-context) ```xml <!-- https://mvnrepository.com/artifact/org.springframework/spring-context --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> ``` `spring-jdbc` Maven版本列表:[Maven Repository: org.springframework » spring-jdbc](https://mvnrepository.com/artifact/org.springframework/spring-jdbc) ```xml <!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring.version}</version> </dependency> ``` `aspectjweaver` Maven版本列表:[Maven Repository: org.aspectj » aspectjweaver](https://mvnrepository.com/artifact/org.aspectj/aspectjweaver) ```xml <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.24</version> </dependency> ``` `mybatis` Maven版本列表: ```xml <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.19</version> </dependency> ``` `mybatis-spring` Maven版本列表:[Maven Repository: org.mybatis » mybatis](https://mvnrepository.com/artifact/org.mybatis/mybatis) ```xml <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>3.0.5</version> </dependency> ``` `JDBC` Maven版本列表:[Maven Repository: com.mysql » mysql-connector-j ](https://mvnrepository.com/artifact/com.mysql/mysql-connector-j) ```xml <!-- https://mvnrepository.com/artifact/com.mysql/mysql-connector-j --> <dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <version>9.4.0</version> </dependency> ``` ##### 完整`dependencies` ```xml <dependencies> <!-- Spring相关依赖 --> <!-- https://mvnrepository.com/artifact/org.springframework/spring-context --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring.version}</version> </dependency> <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.24</version> </dependency> <!-- MyBatis相关依赖 --> <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.19</version> </dependency> <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>3.0.5</version> </dependency> <!-- JDBC相关依赖 --> <!-- https://mvnrepository.com/artifact/com.mysql/mysql-connector-j --> <dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <version>9.4.0</version> </dependency> </dependencies> ``` #### 2、创建配置文件 在项目`rescources`资源目录下创建`db.properties` ```properties jdbc.mysql.driver=com.mysql.cj.jdbc.Driver jdbc.mysql.url=jdbc:mysql://[address]:3306/[database]?useUnicode=true&useSSL=false&serverTimezone=Asia/Shanghai&characterEncoding=utf8 jdbc.mysql.username=[username] jdbc.mysql.password=[password] ``` 创建`SpringConfig.xml` ```xml <?xml version="1.0" encoding="utf-8" ?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd"> <!-- 注解扫描 --> <context:component-scan base-package="cn.doooog.[project]"/> <!-- 引入DB配置文件 --> <context:property-placeholder location="classpath:db.properties"/> <!-- 配置数据源dataSource --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="${jdbc.mysql.driver}"/> <property name="url" value="${jdbc.mysql.url}"/> <property name="username" value="${jdbc.mysql.username}"/> <property name="password" value="${jdbc.mysql.password}"/> </bean> <!-- 创建SqlSessionFactory,并且扫描实体包创建别名 --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="typeAliasesPackage" value="cn.doooog.[project].po"/> </bean> <!-- 配置Mapper,自动扫描mapper接口,为mapper接口注入SqlSessionFactory --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/> <property name="basePackage" value="cn.doooog.[project].mapper"/> </bean> <!-- 配置Spring事务管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <!-- 开启注解事务 --> <tx:annotation-driven transaction-manager="transactionManager"/> <!-- 声明自动为spring容器中配置了aspectj切面的bean自动创建代理,织入通知 --> <aop:aspectj-autoproxy/> </beans> ``` #### 3、新建模型包 在项目目录下新建`po`包 包内包含数据库各表对应的对象类。 #### 4、新建数据层 在项目目录下新建`mapper`、`sqlprovider`包 ```java import org.apache.ibatis.annotations.Mapper; // 告诉Spring这是一个mapper接口,将数据源、SQLFactory全部注入到这个接口中 @Mapper public interface XXXMapper { // 数据查询方法 } ``` ##### 常用的注解 `@Mapper` `@Select("SQL语句")` `@Update("SQL语句")` `@Insert("SQL语句")` `@Delete("SQL语句")` `@SelectProvider(type = SelectProvider.class, method = "methodName")` `@UpdateProvider(type = UpdateProvider.class, method = "methodName")` `@InsertProvider(type = InsertProvider.class, method = "methodName")` `@DeleteProvider(type = DeleteProvider.class, method = "methodName")` `*Provider.java`类的实现`动态SQL`常用结构 ```java import org.apache.ibatis.jdbc.SQL; public class XXXSqlProvider { public String updatePoById(PoObject o) { return new SQL() {{ UPDATE("[表名]"); if (o.getField() != null && !o.getFied().isEmpty()) SET("field=#{field}"); if (o.getNumField() != null && o.getNumField() > 0) SET("numField=#{numField}"); WHERE("keyField=#{keyField}"); }}.toString(); } } ``` `@Results`、`@Result`、`@One`多对一、`@Many`一对多 ```java @Results(id = "resultsId", value = { @Result(property = "keyField", column = "keyField", id = true), @Result(property = "field", column = "field"), @Result(property = "foreignKeyField", column = "foreignKeyField", javaType = otherTablePo.class, one = @One(select = "com.to.project.mapper.otherTableMapper.methodLazy")), @Result(property = "foreignKeyFieldList", column = "keyField", javaType = List.class, many = @Many(select = "com.to.project.mapper.otherTableMapper.methodLazy")) }) ``` **注意**:带`id`的`@Results`必须放在方法上声明且必须为该`mapper`中第一或位置较前的方法,否则会检测不到。 `@ResultMap("resultsId")` 获取自增主键,通常搭配`@Insert`、`@InsertProvider`使用 `@Options(useGeneratedKeys = true, keyProperty = "keyField", keyColumn = "keyField")` #### 5、新建服务层 在项目目录下新建`service`包 包内包含前端交互所需数据的获取接口,以及`impl`包下的实现类。 ```java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; @Service("xxxService") public class XXXServiceImpl implements XXXService { private XXXMapper xxxMapper; public XXXServiceImpl() { } @Autowired public XXXServiceImpl(XXXMapper xxxMapper) { this.xxxMapper = xxxMapper; } @Override @Transactional(propagation = Propagation.SUPPORTS) public PoObject getPoById(int id) { // 非事务(SELECT)方法实现代码 if (no <= 0) return null; return xxxMapper.getPoById(id); } @Override @Transactional(propagation = Propagation.REQUIRED) public void txMethod(...) throws Exception { // 事务方法实现代码 } } ``` **注意**:需要事务管理的service,在方法上加`@Transactional`注解即可,必须为`public方法`才可以,不要捕获异常,要让异常自动抛出,否则不能进行事务回滚。 ##### 事务传播机制模式 `REQUIRED`(默认):如果当前存在事务,则加入该事务;否则创建新事务。 `SUPPORTS`:如果当前存在事务,则加入;否则以非事务方式执行。 `MANDATORY`:强制要求存在事务,否则抛`IllegalTransactionStateException`。 `REQUIRES_NEW`:无论当前是否有事务,都创建新事务。原事务暂停,新事务独立提交/回滚。 `NOT_SUPPORTED`:以非事务方式执行,挂起当前事务(如果存在)。 `NEVER`:禁止事务存在,否则抛异常。 `NESTED`:如果当前有事务,则在嵌套事务(子事务)中执行,子事务可单独回滚;否则行为同`REQUIRED`。 #### 6、新建前端 在项目目录下新建`view`包 包内包含前端各个部分,须配合服务层进行修改。 ## 四、SpringMVC #### 1、导入`Maven依赖` `properties` ```xml <properties> <spring.version>7.0.0-M9</spring.version> <jackson.version>2.19.2</jackson.version> </properties> ``` `spring-context` Maven版本列表:[Maven Repository: org.springframework » spring-context](https://mvnrepository.com/artifact/org.springframework/spring-context) ```xml <!-- https://mvnrepository.com/artifact/org.springframework/spring-context --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> ``` `spring-webmvc` Maven版本列表:[Maven Repository: org.springframework » spring-webmvc](https://mvnrepository.com/artifact/org.springframework/spring-webmvc) ```xml <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> ``` `jakarta.servlet-api` Maven版本列表:[Maven Repository: jakarta.servlet » jakarta.servlet-api](https://mvnrepository.com/artifact/jakarta.servlet/jakarta.servlet-api) ```xml <!-- https://mvnrepository.com/artifact/jakarta.servlet/jakarta.servlet-api --> <dependency> <groupId>jakarta.servlet</groupId> <artifactId>jakarta.servlet-api</artifactId> <version>6.2.0-M1</version> <scope>provided</scope> </dependency> ``` `jackson-core` Maven版本列表:[Maven Repository: tools.jackson.core » jackson-core](https://mvnrepository.com/artifact/tools.jackson.core/jackson-core) ```xml <!-- https://mvnrepository.com/artifact/tools.jackson.core/jackson-core --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>${jackson.version}</version> </dependency> ``` `jackson-databind` Maven版本列表:[Maven Repository: tools.jackson.core » jackson-databind](https://mvnrepository.com/artifact/tools.jackson.core/jackson-databind) ```xml <!-- https://mvnrepository.com/artifact/tools.jackson.core/jackson-databind --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>${jackson.version}</version> </dependency> ``` `jackson-annotations` Maven版本列表:[Maven Repository: com.fasterxml.jackson.core » jackson-annotations](https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations) ```xml <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>${jackson.version}</version> </dependency> ``` `commons-fileupload2-jakarta-servlet6` Maven版本列表:[Maven Repository: org.apache.commons » commons-fileupload2-jakarta-servlet6](https://mvnrepository.com/artifact/org.apache.commons/commons-fileupload2-jakarta-servlet6) ```xml <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-fileupload2-jakarta-servlet6 --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-fileupload2-jakarta-servlet6</artifactId> <version>2.0.0-M4</version> </dependency> ``` `commons-io` Maven版本列表:[Maven Repository: commons-io » commons-io](https://mvnrepository.com/artifact/commons-io/commons-io) ```xml <!-- https://mvnrepository.com/artifact/commons-io/commons-io --> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.20.0</version> </dependency> ``` ##### 完整`dependencies` ```xml <dependencies> <!-- Spring框架 --> <!-- https://mvnrepository.com/artifact/org.springframework/spring-context --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <!-- Servlet服务器 --> <!-- https://mvnrepository.com/artifact/jakarta.servlet/jakarta.servlet-api --> <dependency> <groupId>jakarta.servlet</groupId> <artifactId>jakarta.servlet-api</artifactId> <version>6.2.0-M1</version> <scope>provided</scope> </dependency> <!-- 对象<->Json转换器 --> <!-- https://mvnrepository.com/artifact/tools.jackson.core/jackson-core --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>${jackson.version}</version> </dependency> <!-- https://mvnrepository.com/artifact/tools.jackson.core/jackson-databind --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>${jackson.version}</version> </dependency> <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>${jackson.version}</version> </dependency> <!-- 文件上传 --> <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-fileupload2-jakarta-servlet6 --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-fileupload2-jakarta-servlet6</artifactId> <version>2.0.0-M4</version> </dependency> <!-- https://mvnrepository.com/artifact/commons-io/commons-io --> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.20.0</version> </dependency> </dependencies> ``` #### 2、创建配置文件 在项目`rescources`资源目录下创建 ##### `SpringConfig.xml` ```xml <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- 注解扫描 --> <context:component-scan base-package="cn.doooog.[project]"/> <mvc:annotation-driven/> <!-- 拦截器 --> <!-- 全部拦截 --> <mvc:interceptors> <bean class="cn.doooog.[project].interceptor.*Interceptor"/> </mvc:interceptors> <!-- 拦截部分且放行部分 --> <mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/拦截根路径/**代表该路径及其子路径"/> <mvc:exclude-mapping path="/不拦截的路径/*代表该路径不包含子路径"/> <bean class="cn.doooog.[project].interceptor.*Interceptor"/> </mvc:interceptor> <mvc:interceptor> <mvc:mapping path="/拦截根路径/**代表该路径及其子路径"/> <mvc:exclude-mapping path="/不拦截的路径/*代表该路径不包含子路径"/> <bean class="cn.doooog.[project].interceptor.*Interceptor"/> </mvc:interceptor> </mvc:interceptors> <!-- 上传文件解析器配置 --> <bean id="multipartResolver" class="org.springframework.web.multipart.support.StandardServletMultipartResolver"/> </beans> ``` 在项目`src/main/webapp/WEB-INF/`目录下修改 ##### `web.xml` ```xml <?xml version="1.0" encoding="UTF-8"?> <web-app id="WebApp_ID" version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> <!-- 编码过滤 utf-8 --> <filter> <description>char encoding filter</description> <filter-name>encodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <!-- 过滤路径, /* 代表所有请求包括静态资源请求--> <url-pattern>/*</url-pattern> </filter-mapping> <!-- servlet请求分发器 --> <servlet> <servlet-name>springMvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!--配置文件设置--> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath*:SpringConfig.xml</param-value> </init-param> <!-- 表示启动容器时初始化该Servlet --> <load-on-startup>1</load-on-startup> <!-- 文件上传配置 --> <multipart-config> <!-- 单个文件最大10MB --> <max-file-size>10485760</max-file-size> <!-- 请求总大小最大10MB --> <max-request-size>10485760</max-request-size> <file-size-threshold>0</file-size-threshold> </multipart-config> </servlet> <servlet-mapping> <servlet-name>springMvc</servlet-name> <!-- 拦截请求, /代表拦截所有请求不包括静态资源请求 --> <url-pattern>/</url-pattern> </servlet-mapping> <!-- 服务器Session配置 --> <session-config> <!-- session过期时间, 单位是分钟, 默认为30 --> <session-timeout>30</session-timeout> </session-config> </web-app> ``` #### 3、新建模型包 在项目目录下新建`po`包 包内包含数据库各表对应的对象类。 #### 4、新建数据层(须集成MyBatis) 在项目目录下新建`mapper`、`sqlprovider`包 ```java import org.apache.ibatis.annotations.Mapper; // 告诉Spring这是一个mapper接口,将数据源、SQLFactory全部注入到这个接口中 @Mapper public interface XXXMapper { // 数据查询方法 } ``` **常用的注解**: `@Mapper` `@Select("SQL语句")` `@Update("SQL语句")` `@Insert("SQL语句")` `@Delete("SQL语句")` `@SelectProvider(type = SelectProvider.class, method = "methodName")` `@UpdateProvider(type = UpdateProvider.class, method = "methodName")` `@InsertProvider(type = InsertProvider.class, method = "methodName")` `@DeleteProvider(type = DeleteProvider.class, method = "methodName")` `*Provider.java`类的实现`动态SQL`常用结构 ```java import org.apache.ibatis.jdbc.SQL; public class XXXSqlProvider { public String updatePoById(PoObject o) { return new SQL() {{ UPDATE("[表名]"); if (o.getField() != null && !o.getFied().isEmpty()) SET("field=#{field}"); if (o.getNumField() != null && o.getNumField() > 0) SET("numField=#{numField}"); WHERE("keyField=#{keyField}"); }}.toString(); } } ``` `@Results`、`@Result`、`@One`多对一、`@Many`一对多 ```java @Results(id = "resultsId", value = { @Result(property = "keyField", column = "keyField", id = true), @Result(property = "field", column = "field"), @Result(property = "foreignKeyField", column = "foreignKeyField", javaType = otherTablePo.class, one = @One(select = "com.to.project.mapper.otherTableMapper.methodLazy")), @Result(property = "foreignKeyFieldList", column = "keyField", javaType = List.class, many = @Many(select = "com.to.project.mapper.otherTableMapper.methodLazy")) }) ``` **注意**:带`id`的`@Results`必须放在方法上声明且必须为该`mapper`中第一或位置较前的方法,否则会检测不到。 `@ResultMap("resultsId")` 获取自增主键,通常搭配`@Insert`、`@InsertProvider`使用 `@Options(useGeneratedKeys = true, keyProperty = "keyField", keyColumn = "keyField")` #### 5、新建控制层 在项目目录下创建`controller`包 ##### 常用注解 `@RequestMapping("/URL")`/`@GetMapping("/URL")`/`@PostMapping("/URL")`/`@PutMapping("/URL")`/`@PatchMapping("/URL")`/`@DeleteMapping("/URL")`:用于建立请求URL与处理请求方法之间的对应关系,同种类型的请求URL路径不能出现重复 `@ResponseBody`:将返回的数据以`response.getWriter()`的形式输出给客户端 `@RequestBody`:规定参数注入所需的值需要在RequestBody中寻找 `@RequestParam(name = "参数名",required = 是否必须)`:为进行访问时设置所需提交的参数设置别名映射,常用在参数类型前 `@RequestHeader('请求头key')`:获取请求头信息,通过在参数前面添加注解,请求头对应的`value`会自动注入到参数中 `@PathVariable("参数名")`:通过动态路径映射并注入参数值,通常用在RestFul风格`("/path/{参数}/...")`Get请求时获取参数 ##### 常用转跳方式 重定向:方法不能为响应体且返回类型为`String`,返回`"redirect:/URL"`支持RestFul动态入参 ```java @RequestMapping("/redirect") public String testRedirect(RedirectAttributes redirectAttributes){ redirectAttributes.addAttribute("name","张三"); redirectAttributes.addAttribute("age","18"); redirectAttributes.addAttribute("sex","男"); return "redirect:restful/{name}/{age}/{sex}"; } ``` 转发:方法不能为响应体且返回类型为`String`,返回`"forward:/URL"`不支持RestFul动态入参 ```java @RequestMapping("/forward") public String testForward(){ return "forward:restful/张三/18/男"; } ``` ##### 常用入参方式 ###### 普通参数 ```java @RequestMapping("/hello") @ResponseBody public String hello(@RequestParam(name = "age", required = false) Integer age, @RequestParam(name = "money", defaultValue = "0") double money, @RequestParam("name") String name) { return "get - age:" + age + ",money:" + money + ",name:" + name; } ``` **注意**:当`required = true`和`defaultValue = ..`时可以为空,前者必须使用引用数据类型为参数类型,否则会报赋值错误 ###### RestFul风格参数 ```java @RequestMapping("/restful/{name}/{age}/{sex}") @ResponseBody public User restful(@PathVariable("name") String name, @PathVariable("age") int age, @PathVariable("sex") String sex) { return new User("获取:"+name, age, sex); } ``` ###### 请求头参数 ```java @RequestMapping("/hello") @ResponseBody public String hello(@RequestHeader("Host") String host, @RequestHeader("Accept") String accept) { return "Host:" + host + "; Accept:" + accept; } // 使用HttpServletRequest对象获取 @RequestMapping("/hello") @ResponseBody public String hello(HttpServletRequest request) { return request.getHeader("host"); } ``` ###### 对象参数 ```java @GetMapping("/hello") @ResponseBody public String hello(User user) { return user; } @PostMapping(value = "/hello") @ResponseBody public User hello(@RequestBody User user) { return user; } ``` ###### 返回列表 ```java @RequestMapping("/list-get") @ResponseBody public List<User> listGet() { List<User> list = new ArrayList<>(); list.add(new User("张三", 18, "男")); list.add(new User("李四", 19, "男")); list.add(new User("王五", 20, "男")); list.add(new User("赵六", 21, "男")); return list; } ``` **注意**:直接返回对象时必须添加Jackson依赖才能顺利转换成Json格式,在Post方法中必须使用`@RequestBody`注解才能正常解析Json对象 ##### 常用会话追踪 ###### Cookie ```java @RequestMapping("/cookie-set") @ResponseBody public String cookieSet(HttpServletRequest request, HttpServletResponse response) { // 创建一个Cookie对象 Cookie cookie = new Cookie("test", "test"); // 设置Cookie有效期 一天 cookie.setMaxAge(60 * 60 * 24); // 响应添加Cookie response.addCookie(cookie); return "success"; } @RequestMapping("/cookie-get") @ResponseBody public String cookieGet(HttpServletRequest request, HttpServletResponse response) { // 设置页面可以显示中文 response.setContentType("text/html;charset=utf-8"); // 获取请求的Cookies Cookie[] cookies = request.getCookies(); if (cookies != null) { for (Cookie cookie : cookies) { // 通过Cookie名来对比 if (cookie.getName().equals("test")) return "Cookie测试"; // 通过Cookie值来对比 if (cookie.getValue().equals("test")) return "Cookie测试"; } } return "Not Found Cookie:test."; } ``` **注意**:Cookie在赋值时不可以赋值中文等非ASCII字符。 ###### Session ```java @RequestMapping("/session-set") @ResponseBody public String sessionSet(HttpSession session, HttpServletRequest request) { // 手动获取/创建Session // request.getSession(); User user = new User("张三", 18, "男"); // 设置Session内容 session.setAttribute("user", user); return session.getId(); } @RequestMapping("/session-get") @ResponseBody public User sessionGet(HttpSession session) { // 获取Session内容 return (User) session.getAttribute("user"); } ``` #### 6、新建拦截器 在项目目录下创建`interceptor`包 ```java import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.jspecify.annotations.Nullable; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; public class *Interceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("处理器处理前"); // 获取Session HttpSession session = request.getSession(); if (session.getAttribute("属性名") != null) return true; // URL重定向 response.sendRedirect("URL"); return false; // true为放行 } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception { System.out.println("处理器处理后"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception { System.out.println("视图渲染后"); } } ``` 记得去`SpringConfig.xml`文件中配置拦截器 #### 7、文件上传处理器 `FileController.java` ```java import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import java.io.File; import java.io.IOException; import java.util.UUID; @Controller @RequestMapping("/upload") public class FileController { @PostMapping("/file") @ResponseBody public String uploadFile(@RequestBody @RequestParam("file") MultipartFile file) { String path = "保存的路径"; String fileName = file.getOriginalFilename(); String newFileName; if (fileName != null) { // 重命名文件 newFileName = UUID.randomUUID() + fileName.substring(fileName.lastIndexOf(".")); File file1 = new File(path, newFileName); if (!file1.exists()){ // 创建保存路径的所有文件夹 file1.mkdirs(); } try { // 保存文件 file.transferTo(file1); } catch (IOException e) { throw new RuntimeException(e); } finally { // 输出文件所在位置 System.out.println(file1); } } return "ok"; } } ``` `<form>` ```html <form action="./upload/file" method="post" enctype="multipart/form-data"> <input type="file" name="file"><br> <input type="submit" value="提交"> </form> ``` #### 8、新建前端 在项目目录下新建`view`包 包内包含前端各个部分,须配合服务层进行修改。 ``` 最后修改:2025 年 11 月 19 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 👆请简单粗暴地爱我。