Spring Boot整合Spring和Spring Boot都是用来构建项目的脚手架Spring和Spring Boot的区别Spring 需要手动进行组件的配置Spring Boot是自动进行组件的配置一、Spring Boot如何自动进行组件的配置1.1 自动装配引入了MyBatis的依赖项目启动时会自动加载MyBatis相关的组件DataSource 、sqlSessionFactory...当启动了Spring Boot时pom.xml中配置的所有框架的组件都会自动进行加载。比如pom.xml中引入了mybatis依赖不配置datasource启动就会报错。1.2 如何进行自动装配pom.xml文件中添加mybatis的依赖Spring Boot就会自动加载MyBatis需要的bean只需要在该类配置中将需要创建的对象进行配置即可Spring 框架就会读取配置类进而创建对象反射Spring Boot如何自动实现bean的创建通过配置类的方式引入MyBatis依赖之后依赖中会包含一个配置类的信息配置类中会标注要创建的beanSpring Boot启动之后会读取配置类信息从而获得MyBatis需要创建的bean然后进行创建Maven:org.mybatis.spring.boot:mybatis-spring-boot-autoconfigure:3.0.5/META-INF/spring.factories启动Spring Boot时会读取spring.factories文件通过key获取到两个配置类。二、MyBatis PlusMyBatis Plus基于MyBatisMyBatis需要开发者手动编写SQL语句MyBatis Plus不需要开发者手动编写。使用MyBatis Plus会减少代码量。dependency groupIdcom.baomidougroupId artifactIdmybatis-plus-boot-starter/artifactId version3.4.3.1/version /dependencyMyBatis Plus除了可以自动生成SQL外还可以自动生成代码Controller、Service、Mapper和Enity)2.1 MyBatis Plus逆向工程的依赖!--mybatis plus逆向工程的依赖 要跟starter的版本一致-- dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-generator/artifactId version3.5.7/version /dependency !--模板引擎-- dependency groupIdorg.apache.velocity/groupId artifactIdvelocity-engine-core/artifactId version2.3/version /dependency3.5.x 完全重构了生成器旧的AutoGenerator类虽然还在但构造器已私有化必须使用新的流式 API。建议使用3.3.2!--mybatis plus的依赖-- dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version3.3.2/version /dependency !--mybatis plus逆向工程的依赖 跟starter的版本一致-- dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-generator/artifactId version3.3.2/version /dependency !--模板引擎-- dependency groupIdorg.apache.velocity/groupId artifactIdvelocity/artifactId version1.7/version /dependency2.2 通过表逆向生成项目package com.dyz; import com.baomidou.mybatisplus.annotation.DbType; import com.baomidou.mybatisplus.generator.AutoGenerator; import com.baomidou.mybatisplus.generator.config.DataSourceConfig; import com.baomidou.mybatisplus.generator.config.GlobalConfig; import com.baomidou.mybatisplus.generator.config.PackageConfig; import com.baomidou.mybatisplus.generator.config.StrategyConfig; import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy; public class Main { public static void main(String[] args) { AutoGenerator autoGenerator new AutoGenerator(); //配置数据源 DataSourceConfig dataSourceConfig new DataSourceConfig(); dataSourceConfig.setDbType(DbType.MYSQL); dataSourceConfig.setDriverName(com.mysql.cj.jdbc.Driver); dataSourceConfig.setUrl(jdbc:mysql://localhost:3306/car_rental_separate?useUnicodetruecharacterEncodingUTF-8serverTimezoneAsia/ShanghaiuseSSLfalseallowPublicKeyRetrievaltrue); dataSourceConfig.setUsername(root); dataSourceConfig.setPassword(123456); autoGenerator.setDataSource(dataSourceConfig); //全局配置 GlobalConfig globalConfig new GlobalConfig(); globalConfig.setOpen(false); globalConfig.setOutputDir(System.getProperty(user.dir) (/src/main/java)); globalConfig.setServiceName(%sService); //%s替换符避免出现IService不规范的情况 autoGenerator.setGlobalConfig(globalConfig); //配置包 PackageConfig packageConfig new PackageConfig(); packageConfig.setParent(com.dyz); packageConfig.setEntity(entity); packageConfig.setController(controller); packageConfig.setMapper(mapper); packageConfig.setService(service); packageConfig.setServiceImpl(service.impl); autoGenerator.setPackageInfo(packageConfig); //生成策略 StrategyConfig strategyConfig new StrategyConfig(); strategyConfig.setEntityLombokModel(true); strategyConfig.setInclude(sys_news); strategyConfig.setNaming(NamingStrategy.underline_to_camel);//下划线转驼峰 SysNew不是Sys_news这样不规范 autoGenerator.setStrategy(strategyConfig); //启动 autoGenerator.execute(); } }生成器帮你写 Java 代码但 Spring Boot 的启动配置还得你自己配。就是说想要项目跑起来还得自己写appliation.yml配置package com.dyz.controller; import com.dyz.entity.SysNews; import com.dyz.service.SysNewsService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RestController; import java.util.List; //Controller RestController //返回json RequestMapping(/news) public class SysNewsController { Autowired private SysNewsService sysNewsService; GetMapping(/list) public ListSysNews list(){ return this.sysNewsService.list(); } GetMapping(/get/{id}) public SysNews getById(PathVariable(id) Integer id){ return this.sysNewsService.getById(id); } }package com.dyz; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; SpringBootApplication MapperScan(com.dyz.mapper) public class SpringbootMybatisPlusApplication { public static void main(String[] args) { SpringApplication.run(SpringbootMybatisPlusApplication.class, args); } }三、Spring Boot整合jdbcTemplatejdbcTemplate是一个轻量级的JDBC封装组件。jdbcTemplate是Spring自带的JDBC模板组件底层实现了对JDBC的封装需要开发者自定义SQL语句jdbcTemplate帮助完成数据库的连接SQL的执行结果集的封装。jdbcTemplate提供了通用的SQL操作方法execute、update、batchUpdate、queryjdbcTemplate和MyBatis的区别MyBatis的SQL定义在XML文件中jdbcTemplate的SQL定义在Java类中。3.1 pom.xml中添加依赖dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-jdbc/artifactId /dependency3.2 表创建实体类package com.dyz.entity; import lombok.Data; import java.util.Date; Data public class News { private int id; private String title; private String content; private Date createtime; private String opername; }3.3 创建Mapper接口定义JDBC方法浏览器一般只能测试查询方法postman一款接口测试工具package com.dyz.jdbcTemplate; import com.dyz.entity.News; import java.util.List; public interface NewsMapper { public ListNews list(); public News getById(Integer id); public void add(News news); public void update(News news); public void deleteById(Integer id); public void batchUpdate(); public void batchAdd(); public void batchDelete(); }package com.dyz.jdbcTemplate; import com.dyz.entity.News; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Repository; import java.util.ArrayList; import java.util.Date; import java.util.List; Repository public class NewsMapperImpl implements NewsMapper{ Autowired private JdbcTemplate jdbcTemplate; Override public ListNews list() { return this.jdbcTemplate.query(select * from sys_news,new BeanPropertyRowMapper(News.class)); } Override public News getById(Integer id) { return this.jdbcTemplate.queryForObject(select * from sys_news where id ?,new Object[]{id},new BeanPropertyRowMapper(News.class)); } Override public void add(News news) { this.jdbcTemplate.update(insert into sys_news(title,content,createtime,opername) values(?,?,?,?),news.getTitle(),news.getContent(),news.getCreatetime(),news.getOpername()); } Override public void update(News news) { this.jdbcTemplate.update(update sys_news set title ?,content ?,createtime ?,opername ? where id ?,news.getTitle(),news.getContent(),news.getCreatetime(),news.getOpername(),news.getId()); } Override public void deleteById(Integer id) { this.jdbcTemplate.update(delete from sys_news where id ?,id); } Override public void batchAdd() { ListObject[] args new ArrayList(); args.add(new Object[]{测试1,这是测试数据1,new Date(),admin}); args.add(new Object[]{测试2,这是测试数据2,new Date(),admin}); args.add(new Object[]{测试3,这是测试数据3,new Date(),admin}); args.add(new Object[]{测试4,这是测试数据4,new Date(),admin}); this.jdbcTemplate.batchUpdate(insert into sys_news(title,content,createtime,opername) values (?,?,?,?),args); } Override public void batchUpdate() { ListObject[] args new ArrayList(); args.add(new Object[]{测试12,这是测试数据1,new Date(),admin}); this.jdbcTemplate.batchUpdate(update sys_news set title ?,content ?,createtime?,opername?,args); } Override public void batchDelete() { ListObject[] args new ArrayList(); args.add(new Object[]{1}); args.add(new Object[]{5}); this.jdbcTemplate.batchUpdate(delete from sys_news where id ?,args); } }3.4 controller实现方法package com.dyz.controller; import com.dyz.entity.News; import com.dyz.jdbcTemplate.NewsMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import java.util.List; //Controller RestController public class NewsController { Autowired private NewsMapper newsMapper; GetMapping(/list) public ListNews list(){ return this.newsMapper.list(); } GetMapping(/getById/{id}) public News getById(PathVariable(id) Integer id){ News news null; try { news this.newsMapper.getById(id); } catch (Exception e) { return null; } return news; } PostMapping(/add) public void add(RequestBody News news){ this.newsMapper.add(news); } PutMapping(/update) public void update(RequestBody News news){ this.newsMapper.update(news); } DeleteMapping(/delete/{id}) public void deleteById(PathVariable(id) Integer id){ this.newsMapper.deleteById(id); } GetMapping(/batchAdd) public void batchAdd(){ this.newsMapper.batchAdd(); } GetMapping(/batchUpdate) public void batchUpdate(){ this.newsMapper.batchUpdate(); } GetMapping(/batchDelete) public void batchDelete(){ this.newsMapper.batchDelete(); } }四、Spring Boot整合Spring Data JPASpring Data JPA是Spring框架提供的持久层解决方案。4.1 pom.xml中引入依赖dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-data-jpa/artifactId /dependency4.2 创建数据表实体类package com.dyz.jpaentity; import jakarta.persistence.*; import lombok.Data; import java.util.Date; Data Entity(name sys_news) //表示关联到数据库 public class News { Id GeneratedValue(strategy GenerationType.IDENTITY) //自增 private Integer id; Column //普通字段 private String title; Column private String content; Column private Date createtime; Column private String opername; }4.3 创建接口package com.dyz.repository; import com.dyz.jpaentity.News; import org.springframework.data.jpa.repository.JpaRepository; public interface NewsRepository extends JpaRepositoryNews,Integer { }4.4 创建Controllerpackage com.dyz.controller; import com.dyz.jpaentity.News; import com.dyz.repository.NewsRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.List; import java.util.Optional; RestController RequestMapping(/jpa) public class JPANewsController { Autowired private NewsRepository newsRepository; GetMapping(/list) public ListNews list(){ return this.newsRepository.findAll(); } GetMapping(/getById/{id}) public News getById(PathVariable(id) Integer id){ OptionalNews optional this.newsRepository.findById(id); return optional.get(); } PostMapping(/add) public void add(RequestBody News news){ this.newsRepository.save(news); } PutMapping(/update) public void update(RequestBody News news){ this.newsRepository.save(news); } DeleteMapping(/deleteById/{id}) public void DeleteById(PathVariable(id) Integer id){ this.newsRepository.deleteById(id); } }五、Spring Boot整合Spring Security5.1 登录认证5.1.1 pom.xml中添加依赖相当于添加安全校验的框架会自动跳转到login页面进行校验dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-security/artifactId /dependency5.1.2 创建html页面!DOCTYPE html html langen head meta charsetUTF-8 titleTitle/title /head body h1Welcome/h1 /body /html5.1.3 创建controllerpackage com.dyz.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; Controller public class IndexController { GetMapping(/welcome) public String index(){ return welcome; } }5.1.4 控制台输出测试username:useryml文件中可自定义账号密码server: port: 8081 spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/car_rental_separate username: root password: 123456 security: user: name: dyz password: 123456除基本的登录认证还可以用来完成资源权限管理当请求某个资源时对角色进行认证如果该角色拥有访问权限则正常访问否则无法访问。5.2 权限管理admin:可以访问index和welcome页面user只能访问welcome页面WebSecurityConfigurerAdapter在Spring Security 5.7.0 / Spring Boot 2.7中已被弃用deprecated并在Spring Security 6.x / Spring Boot 3.x中完全移除。基于内存的用户认证In-Memory AuthenticationURL 路径拦截Filter Chain 授权5.2.1 新建页面index.html!DOCTYPE html html xmlns:thhttp://www.thymeleaf.org xmlns:sechttp://www.thymeleaf.org/extras/spring-security headtitle首页/title/head body h2 管理员专属页面 - Index/h2 p当前用户: span sec:authenticationname/span/p p角色: span sec:authenticationprincipal.authorities/span/p a th:href{/welcome}去Welcome页面/a | form th:action{/logout} methodpost styledisplay:inline; button typesubmit退出/button /form /body /htmlwelcome.html!DOCTYPE html html xmlns:thhttp://www.thymeleaf.org xmlns:sechttp://www.thymeleaf.org/extras/spring-security headtitle欢迎/title/head body h2欢迎页面 - Welcome/h2 p当前用户: span sec:authenticationname/span/p !-- 只有 ADMIN 能看到这个链接 -- div sec:authorizehasRole(ADMIN) a th:href{/index}去Index页面仅管理员/a /div !-- 只有 USER 能看到这个提示 -- div sec:authorizehasRole(USER) p您是普通用户无法访问 Index 页面/p /div form th:action{/logout} methodpost styledisplay:inline; button typesubmit退出/button /form /body /html5.2.2 创建controllerpackage com.dyz.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; Controller public class IndexController { GetMapping(/index) public String index() { return index; // admin专属页面 } GetMapping(/welcome) public String welcome() { return welcome; // 所有用户都能访问 } }5.2.3 安全配置类package com.dyz.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.provisioning.InMemoryUserDetailsManager; import org.springframework.security.web.SecurityFilterChain; Configuration EnableWebSecurity public class SecurityConfiguration { Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .csrf(csrf - csrf.disable()) .authorizeHttpRequests(auth - auth // 必须放行 Security 内置端点不写的话login会被拦截 .requestMatchers(/login, /logout, /error).permitAll() .requestMatchers(/index).hasRole(ADMIN) .requestMatchers(/welcome).hasAnyRole(ADMIN, USER) .anyRequest().authenticated() ) .formLogin(form - form.defaultSuccessUrl(/welcome)); return http.build(); } Bean public UserDetailsService userDetailsService() { UserDetails admin User.builder() .username(admin) .password(passwordEncoder().encode(123456)) .roles(ADMIN) .build(); UserDetails user User.builder() .username(user) .password(passwordEncoder().encode(123456)) .roles(USER) .build(); return new InMemoryUserDetailsManager(admin, user); } Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } }六、Spring Boot整合Shiro通过过滤器和拦截器去拦截用户的各种请求然后进行各种验证、登录、权限验证。6.1 Shiro核心组件Token存储用户登录信息用户在登录时创建Shiro通过Token来判断当前用户的身份和权限。Subject:存储当前用户信息当前用户用户/第三方进程/后台账户/其他正在交互的用户。SecurityManager:Shiro的核心用来管理内部的组件实例实现安全认证和授权。Realm:实现数据交互对用户执行认证和授权验证时Shiro从Realm中查找用户信息和权限信息。6.1.1 pom.xml添加依赖dependency groupIdcom.mysql/groupId artifactIdmysql-connector-j/artifactId scoperuntime/scope /dependency dependency groupIdorg.apache.shiro/groupId artifactIdshiro-spring/artifactId version1.8.0/version /dependency6.1.2 创建表mysql use sys; Database changed mysql create table account(id int primary key auto_increment,username varchar(11),password varchar(11),permits varchar(20),role varchar(20));6.1.3 创建实体类package com.dyz.entity; import lombok.Data; Data public class Account { private Integer id; private String username; private String password; private String permits; private String role; }6.1.4 创建控制器package com.dyz.controller; import com.dyz.entity.Account; import com.dyz.mapper.AccountMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.List; RestController RequestMapping(/account) public class AccountController { Autowired private AccountMapper accountMapper; GetMapping(/list) public ListAccount list(){ return this.accountMapper.selectList(null); } }6.1.5 创建mapperpackage com.dyz.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.dyz.entity.Account; public interface AccountMapper extends BaseMapperAccount { }6.1.6 创建service及其implpackage com.dyz.service; import com.dyz.entity.Account; public interface AccountService { public Account findByUsername(String username); }package com.dyz.service.impl; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.dyz.entity.Account; import com.dyz.mapper.AccountMapper; import com.dyz.service.AccountService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; Service public class AccountServiceImpl implements AccountService { Autowired private AccountMapper accountMapper; Override public Account findByUsername(String username) { QueryWrapper queryWrapper new QueryWrapper(); queryWrapper.eq(username,username); return this.accountMapper.selectOne(queryWrapper); } }6.1.7 创建Shiro过滤器package com.dyz.realm; import com.dyz.entity.Account; import com.dyz.service.AccountService; import org.apache.shiro.authc.*; import org.apache.shiro.realm.AuthenticatingRealm; import org.springframework.beans.factory.annotation.Autowired; //AuthenticatingRealm只支持认证不支持授权 // AuthorizingRealm 同时支持认证和授权 public class AccountRealm extends AuthorizingRealm { Autowired private AccountService accountService; /** * 认证 * param authenticationToken * return * throws AuthenticationException */ Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { UsernamePasswordToken token (UsernamePasswordToken) authenticationToken; Account account this.accountService.findByUsername(token.getUsername()); //验证密码 if (account ! null){ return new SimpleAuthenticationInfo(account, account.getPassword(), getName()); } return null; } }6.1.8 创建配置类package com.dyz.config; import com.dyz.realm.AccountRealm; import org.apache.shiro.spring.web.ShiroFilterFactoryBean; import org.apache.shiro.web.mgt.DefaultWebSecurityManager; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; Configuration public class ShiroConfiguration { Bean public ShiroFilterFactoryBean shiroFilterFactoryBean( Qualifier(securityManager)DefaultWebSecurityManager securityManager ){ ShiroFilterFactoryBean factoryBean new ShiroFilterFactoryBean(); factoryBean.setSecurityManager(securityManager); return factoryBean; } Bean public DefaultWebSecurityManager securityManager( Qualifier(accountRealm)AccountRealm accountRealm ){ DefaultWebSecurityManager securityManager new DefaultWebSecurityManager(); securityManager.setRealm(accountRealm); return securityManager; } Bean public AccountRealm accountRealm(){ return new AccountRealm(); } }6.2 Shiro 认证授权规则认证过滤器anon:无需认证就能访问authc:必须登录才能访问authBasic:需要通过httpBasic认证user不一定通过认证只要曾经被Shiro记录过登录状态的用户都可以正常发起请求授权过滤器perms:必须拥有权限才能访问roles:必须拥有角色才能访问port请求的端口必须为指定值才可访问res请求必须时基于RESTful的才能访问ssl必须是安全的URL请求协议为HTTPS6.2.1 创建页面/要求/完善配置类login.html、main.html、manage.html、administratoy.html登录状态才能访问main.html页面拥有manager权限的用户才能访问 manage.html拥有administrator角色才能访问administratoy.htmllogin.html!DOCTYPE html html langen head meta charsetUTF-8 titleTitle/title /head body form action/login methodpost table tr td用户名:/td td input typetext name username/ /td /tr tr td密码:/td td input typepassword namepassword/ /td /tr tr td input typesubmit value登录/ /td /tr /table /form /body /htmlShiroConfiguration.javaBean public ShiroFilterFactoryBean shiroFilterFactoryBean( Qualifier(securityManager)DefaultWebSecurityManager securityManager ){ ShiroFilterFactoryBean factoryBean new ShiroFilterFactoryBean(); factoryBean.setSecurityManager(securityManager); //权限设置 MapString,String map new HashMap(); map.put(/main,authc); map.put(/manage,perms[manager]); map.put(/administrator,roles[administrator]); factoryBean.setFilterChainDefinitionMap(map); //设置登陆页面 factoryBean.setLoginUrl(/login); //设置未授权页面 factoryBean.setUnauthorizedUrl(/unauth); return factoryBean; }6.2.2 controller实现登录PostMapping(/login) public String login(String username, String password, Model model){ Subject subject SecurityUtils.getSubject(); UsernamePasswordToken token new UsernamePasswordToken(username,password); try { subject.login(token); return main; }catch (UnknownAccountException e){ model.addAttribute(msg,用户名错误); return /login; } catch (IncorrectCredentialsException e){ model.addAttribute(msg,密码错误); return /login; } } RequestMapping(/unauth) ResponseBody public String unauth(){ return 未授权无法访问; }6.2.3 AccountRealm中实现授权方法//授权 protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection){ //获取当前登录对象 Subject subject SecurityUtils.getSubject(); Account account (Account) subject.getPrincipal(); //设置角色 SetString roles new HashSet(); roles.add(account.getRole()); SimpleAuthorizationInfo info new SimpleAuthorizationInfo(roles); //设置权限 info.addStringPermission(account.getPermits()); return info; }
回顾Java知识点,面试题汇总Day17(持续更新)
Spring Boot整合Spring和Spring Boot都是用来构建项目的脚手架Spring和Spring Boot的区别Spring 需要手动进行组件的配置Spring Boot是自动进行组件的配置一、Spring Boot如何自动进行组件的配置1.1 自动装配引入了MyBatis的依赖项目启动时会自动加载MyBatis相关的组件DataSource 、sqlSessionFactory...当启动了Spring Boot时pom.xml中配置的所有框架的组件都会自动进行加载。比如pom.xml中引入了mybatis依赖不配置datasource启动就会报错。1.2 如何进行自动装配pom.xml文件中添加mybatis的依赖Spring Boot就会自动加载MyBatis需要的bean只需要在该类配置中将需要创建的对象进行配置即可Spring 框架就会读取配置类进而创建对象反射Spring Boot如何自动实现bean的创建通过配置类的方式引入MyBatis依赖之后依赖中会包含一个配置类的信息配置类中会标注要创建的beanSpring Boot启动之后会读取配置类信息从而获得MyBatis需要创建的bean然后进行创建Maven:org.mybatis.spring.boot:mybatis-spring-boot-autoconfigure:3.0.5/META-INF/spring.factories启动Spring Boot时会读取spring.factories文件通过key获取到两个配置类。二、MyBatis PlusMyBatis Plus基于MyBatisMyBatis需要开发者手动编写SQL语句MyBatis Plus不需要开发者手动编写。使用MyBatis Plus会减少代码量。dependency groupIdcom.baomidougroupId artifactIdmybatis-plus-boot-starter/artifactId version3.4.3.1/version /dependencyMyBatis Plus除了可以自动生成SQL外还可以自动生成代码Controller、Service、Mapper和Enity)2.1 MyBatis Plus逆向工程的依赖!--mybatis plus逆向工程的依赖 要跟starter的版本一致-- dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-generator/artifactId version3.5.7/version /dependency !--模板引擎-- dependency groupIdorg.apache.velocity/groupId artifactIdvelocity-engine-core/artifactId version2.3/version /dependency3.5.x 完全重构了生成器旧的AutoGenerator类虽然还在但构造器已私有化必须使用新的流式 API。建议使用3.3.2!--mybatis plus的依赖-- dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version3.3.2/version /dependency !--mybatis plus逆向工程的依赖 跟starter的版本一致-- dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-generator/artifactId version3.3.2/version /dependency !--模板引擎-- dependency groupIdorg.apache.velocity/groupId artifactIdvelocity/artifactId version1.7/version /dependency2.2 通过表逆向生成项目package com.dyz; import com.baomidou.mybatisplus.annotation.DbType; import com.baomidou.mybatisplus.generator.AutoGenerator; import com.baomidou.mybatisplus.generator.config.DataSourceConfig; import com.baomidou.mybatisplus.generator.config.GlobalConfig; import com.baomidou.mybatisplus.generator.config.PackageConfig; import com.baomidou.mybatisplus.generator.config.StrategyConfig; import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy; public class Main { public static void main(String[] args) { AutoGenerator autoGenerator new AutoGenerator(); //配置数据源 DataSourceConfig dataSourceConfig new DataSourceConfig(); dataSourceConfig.setDbType(DbType.MYSQL); dataSourceConfig.setDriverName(com.mysql.cj.jdbc.Driver); dataSourceConfig.setUrl(jdbc:mysql://localhost:3306/car_rental_separate?useUnicodetruecharacterEncodingUTF-8serverTimezoneAsia/ShanghaiuseSSLfalseallowPublicKeyRetrievaltrue); dataSourceConfig.setUsername(root); dataSourceConfig.setPassword(123456); autoGenerator.setDataSource(dataSourceConfig); //全局配置 GlobalConfig globalConfig new GlobalConfig(); globalConfig.setOpen(false); globalConfig.setOutputDir(System.getProperty(user.dir) (/src/main/java)); globalConfig.setServiceName(%sService); //%s替换符避免出现IService不规范的情况 autoGenerator.setGlobalConfig(globalConfig); //配置包 PackageConfig packageConfig new PackageConfig(); packageConfig.setParent(com.dyz); packageConfig.setEntity(entity); packageConfig.setController(controller); packageConfig.setMapper(mapper); packageConfig.setService(service); packageConfig.setServiceImpl(service.impl); autoGenerator.setPackageInfo(packageConfig); //生成策略 StrategyConfig strategyConfig new StrategyConfig(); strategyConfig.setEntityLombokModel(true); strategyConfig.setInclude(sys_news); strategyConfig.setNaming(NamingStrategy.underline_to_camel);//下划线转驼峰 SysNew不是Sys_news这样不规范 autoGenerator.setStrategy(strategyConfig); //启动 autoGenerator.execute(); } }生成器帮你写 Java 代码但 Spring Boot 的启动配置还得你自己配。就是说想要项目跑起来还得自己写appliation.yml配置package com.dyz.controller; import com.dyz.entity.SysNews; import com.dyz.service.SysNewsService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RestController; import java.util.List; //Controller RestController //返回json RequestMapping(/news) public class SysNewsController { Autowired private SysNewsService sysNewsService; GetMapping(/list) public ListSysNews list(){ return this.sysNewsService.list(); } GetMapping(/get/{id}) public SysNews getById(PathVariable(id) Integer id){ return this.sysNewsService.getById(id); } }package com.dyz; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; SpringBootApplication MapperScan(com.dyz.mapper) public class SpringbootMybatisPlusApplication { public static void main(String[] args) { SpringApplication.run(SpringbootMybatisPlusApplication.class, args); } }三、Spring Boot整合jdbcTemplatejdbcTemplate是一个轻量级的JDBC封装组件。jdbcTemplate是Spring自带的JDBC模板组件底层实现了对JDBC的封装需要开发者自定义SQL语句jdbcTemplate帮助完成数据库的连接SQL的执行结果集的封装。jdbcTemplate提供了通用的SQL操作方法execute、update、batchUpdate、queryjdbcTemplate和MyBatis的区别MyBatis的SQL定义在XML文件中jdbcTemplate的SQL定义在Java类中。3.1 pom.xml中添加依赖dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-jdbc/artifactId /dependency3.2 表创建实体类package com.dyz.entity; import lombok.Data; import java.util.Date; Data public class News { private int id; private String title; private String content; private Date createtime; private String opername; }3.3 创建Mapper接口定义JDBC方法浏览器一般只能测试查询方法postman一款接口测试工具package com.dyz.jdbcTemplate; import com.dyz.entity.News; import java.util.List; public interface NewsMapper { public ListNews list(); public News getById(Integer id); public void add(News news); public void update(News news); public void deleteById(Integer id); public void batchUpdate(); public void batchAdd(); public void batchDelete(); }package com.dyz.jdbcTemplate; import com.dyz.entity.News; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Repository; import java.util.ArrayList; import java.util.Date; import java.util.List; Repository public class NewsMapperImpl implements NewsMapper{ Autowired private JdbcTemplate jdbcTemplate; Override public ListNews list() { return this.jdbcTemplate.query(select * from sys_news,new BeanPropertyRowMapper(News.class)); } Override public News getById(Integer id) { return this.jdbcTemplate.queryForObject(select * from sys_news where id ?,new Object[]{id},new BeanPropertyRowMapper(News.class)); } Override public void add(News news) { this.jdbcTemplate.update(insert into sys_news(title,content,createtime,opername) values(?,?,?,?),news.getTitle(),news.getContent(),news.getCreatetime(),news.getOpername()); } Override public void update(News news) { this.jdbcTemplate.update(update sys_news set title ?,content ?,createtime ?,opername ? where id ?,news.getTitle(),news.getContent(),news.getCreatetime(),news.getOpername(),news.getId()); } Override public void deleteById(Integer id) { this.jdbcTemplate.update(delete from sys_news where id ?,id); } Override public void batchAdd() { ListObject[] args new ArrayList(); args.add(new Object[]{测试1,这是测试数据1,new Date(),admin}); args.add(new Object[]{测试2,这是测试数据2,new Date(),admin}); args.add(new Object[]{测试3,这是测试数据3,new Date(),admin}); args.add(new Object[]{测试4,这是测试数据4,new Date(),admin}); this.jdbcTemplate.batchUpdate(insert into sys_news(title,content,createtime,opername) values (?,?,?,?),args); } Override public void batchUpdate() { ListObject[] args new ArrayList(); args.add(new Object[]{测试12,这是测试数据1,new Date(),admin}); this.jdbcTemplate.batchUpdate(update sys_news set title ?,content ?,createtime?,opername?,args); } Override public void batchDelete() { ListObject[] args new ArrayList(); args.add(new Object[]{1}); args.add(new Object[]{5}); this.jdbcTemplate.batchUpdate(delete from sys_news where id ?,args); } }3.4 controller实现方法package com.dyz.controller; import com.dyz.entity.News; import com.dyz.jdbcTemplate.NewsMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import java.util.List; //Controller RestController public class NewsController { Autowired private NewsMapper newsMapper; GetMapping(/list) public ListNews list(){ return this.newsMapper.list(); } GetMapping(/getById/{id}) public News getById(PathVariable(id) Integer id){ News news null; try { news this.newsMapper.getById(id); } catch (Exception e) { return null; } return news; } PostMapping(/add) public void add(RequestBody News news){ this.newsMapper.add(news); } PutMapping(/update) public void update(RequestBody News news){ this.newsMapper.update(news); } DeleteMapping(/delete/{id}) public void deleteById(PathVariable(id) Integer id){ this.newsMapper.deleteById(id); } GetMapping(/batchAdd) public void batchAdd(){ this.newsMapper.batchAdd(); } GetMapping(/batchUpdate) public void batchUpdate(){ this.newsMapper.batchUpdate(); } GetMapping(/batchDelete) public void batchDelete(){ this.newsMapper.batchDelete(); } }四、Spring Boot整合Spring Data JPASpring Data JPA是Spring框架提供的持久层解决方案。4.1 pom.xml中引入依赖dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-data-jpa/artifactId /dependency4.2 创建数据表实体类package com.dyz.jpaentity; import jakarta.persistence.*; import lombok.Data; import java.util.Date; Data Entity(name sys_news) //表示关联到数据库 public class News { Id GeneratedValue(strategy GenerationType.IDENTITY) //自增 private Integer id; Column //普通字段 private String title; Column private String content; Column private Date createtime; Column private String opername; }4.3 创建接口package com.dyz.repository; import com.dyz.jpaentity.News; import org.springframework.data.jpa.repository.JpaRepository; public interface NewsRepository extends JpaRepositoryNews,Integer { }4.4 创建Controllerpackage com.dyz.controller; import com.dyz.jpaentity.News; import com.dyz.repository.NewsRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.List; import java.util.Optional; RestController RequestMapping(/jpa) public class JPANewsController { Autowired private NewsRepository newsRepository; GetMapping(/list) public ListNews list(){ return this.newsRepository.findAll(); } GetMapping(/getById/{id}) public News getById(PathVariable(id) Integer id){ OptionalNews optional this.newsRepository.findById(id); return optional.get(); } PostMapping(/add) public void add(RequestBody News news){ this.newsRepository.save(news); } PutMapping(/update) public void update(RequestBody News news){ this.newsRepository.save(news); } DeleteMapping(/deleteById/{id}) public void DeleteById(PathVariable(id) Integer id){ this.newsRepository.deleteById(id); } }五、Spring Boot整合Spring Security5.1 登录认证5.1.1 pom.xml中添加依赖相当于添加安全校验的框架会自动跳转到login页面进行校验dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-security/artifactId /dependency5.1.2 创建html页面!DOCTYPE html html langen head meta charsetUTF-8 titleTitle/title /head body h1Welcome/h1 /body /html5.1.3 创建controllerpackage com.dyz.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; Controller public class IndexController { GetMapping(/welcome) public String index(){ return welcome; } }5.1.4 控制台输出测试username:useryml文件中可自定义账号密码server: port: 8081 spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/car_rental_separate username: root password: 123456 security: user: name: dyz password: 123456除基本的登录认证还可以用来完成资源权限管理当请求某个资源时对角色进行认证如果该角色拥有访问权限则正常访问否则无法访问。5.2 权限管理admin:可以访问index和welcome页面user只能访问welcome页面WebSecurityConfigurerAdapter在Spring Security 5.7.0 / Spring Boot 2.7中已被弃用deprecated并在Spring Security 6.x / Spring Boot 3.x中完全移除。基于内存的用户认证In-Memory AuthenticationURL 路径拦截Filter Chain 授权5.2.1 新建页面index.html!DOCTYPE html html xmlns:thhttp://www.thymeleaf.org xmlns:sechttp://www.thymeleaf.org/extras/spring-security headtitle首页/title/head body h2 管理员专属页面 - Index/h2 p当前用户: span sec:authenticationname/span/p p角色: span sec:authenticationprincipal.authorities/span/p a th:href{/welcome}去Welcome页面/a | form th:action{/logout} methodpost styledisplay:inline; button typesubmit退出/button /form /body /htmlwelcome.html!DOCTYPE html html xmlns:thhttp://www.thymeleaf.org xmlns:sechttp://www.thymeleaf.org/extras/spring-security headtitle欢迎/title/head body h2欢迎页面 - Welcome/h2 p当前用户: span sec:authenticationname/span/p !-- 只有 ADMIN 能看到这个链接 -- div sec:authorizehasRole(ADMIN) a th:href{/index}去Index页面仅管理员/a /div !-- 只有 USER 能看到这个提示 -- div sec:authorizehasRole(USER) p您是普通用户无法访问 Index 页面/p /div form th:action{/logout} methodpost styledisplay:inline; button typesubmit退出/button /form /body /html5.2.2 创建controllerpackage com.dyz.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; Controller public class IndexController { GetMapping(/index) public String index() { return index; // admin专属页面 } GetMapping(/welcome) public String welcome() { return welcome; // 所有用户都能访问 } }5.2.3 安全配置类package com.dyz.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.provisioning.InMemoryUserDetailsManager; import org.springframework.security.web.SecurityFilterChain; Configuration EnableWebSecurity public class SecurityConfiguration { Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .csrf(csrf - csrf.disable()) .authorizeHttpRequests(auth - auth // 必须放行 Security 内置端点不写的话login会被拦截 .requestMatchers(/login, /logout, /error).permitAll() .requestMatchers(/index).hasRole(ADMIN) .requestMatchers(/welcome).hasAnyRole(ADMIN, USER) .anyRequest().authenticated() ) .formLogin(form - form.defaultSuccessUrl(/welcome)); return http.build(); } Bean public UserDetailsService userDetailsService() { UserDetails admin User.builder() .username(admin) .password(passwordEncoder().encode(123456)) .roles(ADMIN) .build(); UserDetails user User.builder() .username(user) .password(passwordEncoder().encode(123456)) .roles(USER) .build(); return new InMemoryUserDetailsManager(admin, user); } Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } }六、Spring Boot整合Shiro通过过滤器和拦截器去拦截用户的各种请求然后进行各种验证、登录、权限验证。6.1 Shiro核心组件Token存储用户登录信息用户在登录时创建Shiro通过Token来判断当前用户的身份和权限。Subject:存储当前用户信息当前用户用户/第三方进程/后台账户/其他正在交互的用户。SecurityManager:Shiro的核心用来管理内部的组件实例实现安全认证和授权。Realm:实现数据交互对用户执行认证和授权验证时Shiro从Realm中查找用户信息和权限信息。6.1.1 pom.xml添加依赖dependency groupIdcom.mysql/groupId artifactIdmysql-connector-j/artifactId scoperuntime/scope /dependency dependency groupIdorg.apache.shiro/groupId artifactIdshiro-spring/artifactId version1.8.0/version /dependency6.1.2 创建表mysql use sys; Database changed mysql create table account(id int primary key auto_increment,username varchar(11),password varchar(11),permits varchar(20),role varchar(20));6.1.3 创建实体类package com.dyz.entity; import lombok.Data; Data public class Account { private Integer id; private String username; private String password; private String permits; private String role; }6.1.4 创建控制器package com.dyz.controller; import com.dyz.entity.Account; import com.dyz.mapper.AccountMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.List; RestController RequestMapping(/account) public class AccountController { Autowired private AccountMapper accountMapper; GetMapping(/list) public ListAccount list(){ return this.accountMapper.selectList(null); } }6.1.5 创建mapperpackage com.dyz.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.dyz.entity.Account; public interface AccountMapper extends BaseMapperAccount { }6.1.6 创建service及其implpackage com.dyz.service; import com.dyz.entity.Account; public interface AccountService { public Account findByUsername(String username); }package com.dyz.service.impl; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.dyz.entity.Account; import com.dyz.mapper.AccountMapper; import com.dyz.service.AccountService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; Service public class AccountServiceImpl implements AccountService { Autowired private AccountMapper accountMapper; Override public Account findByUsername(String username) { QueryWrapper queryWrapper new QueryWrapper(); queryWrapper.eq(username,username); return this.accountMapper.selectOne(queryWrapper); } }6.1.7 创建Shiro过滤器package com.dyz.realm; import com.dyz.entity.Account; import com.dyz.service.AccountService; import org.apache.shiro.authc.*; import org.apache.shiro.realm.AuthenticatingRealm; import org.springframework.beans.factory.annotation.Autowired; //AuthenticatingRealm只支持认证不支持授权 // AuthorizingRealm 同时支持认证和授权 public class AccountRealm extends AuthorizingRealm { Autowired private AccountService accountService; /** * 认证 * param authenticationToken * return * throws AuthenticationException */ Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { UsernamePasswordToken token (UsernamePasswordToken) authenticationToken; Account account this.accountService.findByUsername(token.getUsername()); //验证密码 if (account ! null){ return new SimpleAuthenticationInfo(account, account.getPassword(), getName()); } return null; } }6.1.8 创建配置类package com.dyz.config; import com.dyz.realm.AccountRealm; import org.apache.shiro.spring.web.ShiroFilterFactoryBean; import org.apache.shiro.web.mgt.DefaultWebSecurityManager; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; Configuration public class ShiroConfiguration { Bean public ShiroFilterFactoryBean shiroFilterFactoryBean( Qualifier(securityManager)DefaultWebSecurityManager securityManager ){ ShiroFilterFactoryBean factoryBean new ShiroFilterFactoryBean(); factoryBean.setSecurityManager(securityManager); return factoryBean; } Bean public DefaultWebSecurityManager securityManager( Qualifier(accountRealm)AccountRealm accountRealm ){ DefaultWebSecurityManager securityManager new DefaultWebSecurityManager(); securityManager.setRealm(accountRealm); return securityManager; } Bean public AccountRealm accountRealm(){ return new AccountRealm(); } }6.2 Shiro 认证授权规则认证过滤器anon:无需认证就能访问authc:必须登录才能访问authBasic:需要通过httpBasic认证user不一定通过认证只要曾经被Shiro记录过登录状态的用户都可以正常发起请求授权过滤器perms:必须拥有权限才能访问roles:必须拥有角色才能访问port请求的端口必须为指定值才可访问res请求必须时基于RESTful的才能访问ssl必须是安全的URL请求协议为HTTPS6.2.1 创建页面/要求/完善配置类login.html、main.html、manage.html、administratoy.html登录状态才能访问main.html页面拥有manager权限的用户才能访问 manage.html拥有administrator角色才能访问administratoy.htmllogin.html!DOCTYPE html html langen head meta charsetUTF-8 titleTitle/title /head body form action/login methodpost table tr td用户名:/td td input typetext name username/ /td /tr tr td密码:/td td input typepassword namepassword/ /td /tr tr td input typesubmit value登录/ /td /tr /table /form /body /htmlShiroConfiguration.javaBean public ShiroFilterFactoryBean shiroFilterFactoryBean( Qualifier(securityManager)DefaultWebSecurityManager securityManager ){ ShiroFilterFactoryBean factoryBean new ShiroFilterFactoryBean(); factoryBean.setSecurityManager(securityManager); //权限设置 MapString,String map new HashMap(); map.put(/main,authc); map.put(/manage,perms[manager]); map.put(/administrator,roles[administrator]); factoryBean.setFilterChainDefinitionMap(map); //设置登陆页面 factoryBean.setLoginUrl(/login); //设置未授权页面 factoryBean.setUnauthorizedUrl(/unauth); return factoryBean; }6.2.2 controller实现登录PostMapping(/login) public String login(String username, String password, Model model){ Subject subject SecurityUtils.getSubject(); UsernamePasswordToken token new UsernamePasswordToken(username,password); try { subject.login(token); return main; }catch (UnknownAccountException e){ model.addAttribute(msg,用户名错误); return /login; } catch (IncorrectCredentialsException e){ model.addAttribute(msg,密码错误); return /login; } } RequestMapping(/unauth) ResponseBody public String unauth(){ return 未授权无法访问; }6.2.3 AccountRealm中实现授权方法//授权 protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection){ //获取当前登录对象 Subject subject SecurityUtils.getSubject(); Account account (Account) subject.getPrincipal(); //设置角色 SetString roles new HashSet(); roles.add(account.getRole()); SimpleAuthorizationInfo info new SimpleAuthorizationInfo(roles); //设置权限 info.addStringPermission(account.getPermits()); return info; }