https://github.com/mxg133/learnforSpringBoot
注解 | 解释 |
---|---|
@SpringBootApplication | 来标注一个主程序类,说明这是一个springboot应用。 |
@RequestMapping(“/hello”) | 接收来自于浏览器的hello请求,给出外界访问方法的路径,或者说触发路径 ,触发条件。 |
@RequestBody | @RequestBody除了把return的结果变成JSON对象返回,还可以把前端传输过来的json数据自动装配成后端可操作的map对象或自定义对象。 |
@ResponseBody | 用@ResponseBody标记Controller类中的方法。把return的结果变成JSON对象返回,把类的方法返回的数据写给浏览器。(如果没有这个注解,这个方法只能返回要跳转的路径即跳转的html/JSP页面。有这个注解,可以不跳转页面,只返回JSON数据)。 |
@Controller | @Controller标识的类,该类代表控制器类(控制层/表现层)。 |
@RestController | 是==@Controller和@ResponseBody==的结合。 |
@Repository | 作用于数据访问层。 |
@Service | 作用于业务逻辑层。 |
@SpringBootConfiguration | SpringBoot的配置类,标注在某个类上,表明这是一个SpringBoot的配置类。 |
@EnableAutoConfiguration | 开启自动配置。 |
@AutoConfigurationPackage | 自动配置包,将主配置类(@SpringBootApplication标注的类)的所在包及所有子包里的所有组件扫描到spring容器里。 |
@Import() | 给容器导入组件。 |
@ConfigurationProperties(prefix=“person”) | 将配置文件中配置的每一个属性,映射到这个组件中,告诉springboot将本类中的所有属性和配置文件中相关的配置进行绑定;prefix前缀,将配置文件中的"person"下的属性映射进来。 |
@Component | 把该组件注入springboot容器。作用于实体类或者工具类。 |
@PropertySource({“classpath:xxx.properties”}) | 加载指定的properties配置文件。 |
@Configuration | 指明当前类是一个配置类,就是用来替代之前的spring配置文件,可以和@Bean搭配使用。 |
@EnableWebMvc | 加上这个注解,将使所有SpringMVC的自动配置失效,使用自己的配置。 |
@Async | 告诉Spring这是一个异步方法 |
@RequestMapping | @RequestMapping可以指定GET、POST请求方式 |
@GetMapping | @GetMapping等价于@RequestMapping的GET请求方式 |
@ImportResource | springboot默认使用Java配置,但也可以使用xml配置,只需通过该注解引入一个xml配置。 |
@PathVariable
@PathVariable绑定URI模板变量值
@PathVariable是用来获得请求url中的动态参数的
@PathVariable用于将请求URL中的模板变量映射到功能处理方法的参数上。//配置url和方法的一个关系
@RequestMapping(“item/{itemId}”)
@RequestMapping 来映射请求,也就是通过它来指定控制器可以处理哪些URL请求,类似于struts的action请求。
@responsebody 表示该方法的返回结果直接写入HTTP responseBody中一般在异步获取数据时使用,在使用@RequestMapping后,返回值通常解析为跳转路径,加上@responsebody后返回结果不会被解析为跳转路径,而是直接写入HTTP responseBody中。比如异步获取json数据,加上@responsebody后,会直接返回json数据。
@Pathvariable 注解绑定它传过来的值到方法的参数上用于将请求URL中的模板变量映射到功能处理方法的参数上,即取出uri模板中的变量作为参数
@RequestMapping("/zyh/{type}")
public String zyh(@PathVariable(value = "type") int type) throws UnsupportedEncodingException {
String url = "http://wx.diyfintech.com/zyhMain/" + type;
if (type != 1 && type != 2) {
throw new IllegalArgumentException("参数错误");
}
String encodeUrl = URLEncoder.encode(url, "utf-8");
String redirectUrl = MessageFormat.format(OAUTH_URL, WxConfig.zyhAppId, encodeUrl, "snsapi_userinfo", UUID.randomUUID().toString().replace("-", ""));
return "redirect:" + redirectUrl;m
}
在SpringMVC后台控制层获取参数的方式主要有两种:
一种是request.getParameter(“name”),另外一种是用注解@RequestParam直接获取
这里主要讲这个注解 @RequestParam
value:参数名字,即入参的请求参数名字,如username表示请求的参数区中的名字为username的参数的值将传入;
required:是否必须,默认是true,表示请求中一定要有相应的参数,否则将报404错误码;
defaultValue:默认值,表示如果请求中没有同名参数时的默认值,例如:
public List getItemTreeNode(@RequestParam(value=”id”,defaultValue=”0”)long parentId)
@Controller
@RequestMapping("/wx")
public class WxController {
@Autowired
private WxService wxService;
private static final Log log= LogFactory.getLog(WxController.class);
@RequestMapping(value = "/service",method = RequestMethod.GET)
public void acceptWxValid(@RequestParam String signature, @RequestParam String timestamp, @RequestParam String nonce,
@RequestParam String echostr, HttpServletResponse response) throws IOException {
PrintWriter out = response.getWriter();
if (SignUtil.checkSignature(signature, timestamp, nonce)) {
out.print(echostr);
}else
out.print("fail");
out.flush();
out.close();
}
@ConfigurationProperties | @Value() | |
---|---|---|
功能 | 批量注入配置文件中的属性 | 一个个指定 |
@RequestParam
(1)不加@RequestParam前端的参数名需要和后端控制器的变量名保持一致才能生效
(2)不加@RequestParam参数为非必传,加@RequestParam写法参数为必传。但@RequestParam可以通过@RequestParam(required = false)设置为非必传。
(3)@RequestParam可以通过@RequestParam(“userId”)或者@RequestParam(value = “userId”)指定传入的参数名。
(4)@RequestParam可以通过@RequestParam(defaultValue = “0”)指定参数默认值
(5)如果接口除了前端调用还有后端RPC调用,则不能省略@RequestParam,否则RPC会找不到参数报错
(6)Get请求访问时:
Mysql数据库连接配置:
数据库连接application.properties:
spring.datasource.username=root spring.datasource.password=123456 spring.datasource.url=jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
数据库连接application.yml:
spring: datasource: url: jdbc:mysql://localhost:3306/rate?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8 username: root password: 123456 driver-class-name: com.mysql.jdbc.Driver jpa: # 显示sql语句 show-sql: true properties: hibernate: # 格式化sql语句 format_sql: true server: port: 8080
官方文档
依赖:
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-thymeleafartifactId>
dependency>
thymeleaf 命名空间:
xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/extras/spring-security"
xmlns:shiro="http://www.pollix.at/thymeleaf/shiro"
<html lang="en" xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/extras/spring-security"
xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
${...}:获取变量值;
th:object="${}" 来获取对象信息
*{...}:选择变量表达式,在功能上和${...}是一样的;
补充:配合${...}使用,用*{}代替${}获取的对象
示例:
<div th:object="${session.user}"> #获取对象user
<p>Name: <span th:text="*{firstName}">Sebastian</span>.</p> #通过*{}获取对象user的firstName
<p>Surname: <span th:text="*{lastName}">Pepper</span>.</p>
<p>Nationality: <span th:text="*{nationality}">Saturn</span>.</p>
</div>
#{...}:获取国际化内容(中英文切换)
@{...}:定义URL链接表达式
访问这个链接时:<!-- Will produce 'http://localhost:8080/gtvg/order/details?orderId=3' (plus rewriting) -->
通过:<a href="details.html" th:href="@{http://localhost:8080/gtvg/order/details(orderId=${o.id})}">view</a>
~{...}:片段引用表达式
#表单里面可以有三种方式来获取对象属性
使用 th:value="*{属性名}"
使用 th:value="${对象.属性名}",对象指的是上面使用 th:object 获取的对象
使用 th:value="${对象.get方法}",对象指的是上面使用 th:object 获取的对象
常用的标签操作
标签 | 功能 | 例子 |
---|---|---|
th:value |
给属性赋值 | |
th:style |
设置样式 | |
th:onclick |
点击事件 | th:onclick="'getInfo()'" |
th:if |
条件判断 | th:if="${not #strings.isEmpty(msg)}" |
th:href |
超链接 | th:href="@{/index.html(l=zh_CN)}" |
th:unless |
条件判断和th:if 相反 |
|
th:switch |
配合th:case |
|
th:case |
配合th:switch |
|
th:src |
地址引入 | th:src="@{/img/bootstrap-solid.svg}" |
th:action |
表单提交的地址 | th:action="@{/user/login}" |
jdbc增删改查
JdbcController:
@RestController
public class JdbcController {
@Autowired
JdbcTemplate jdbcTemplate;
//查询数据库的所有信息 万能Map
@GetMapping("/userList")
public List<Map<String,Object>> userList(){
String sql="select * from user";
List<Map<String, Object>> List_maps = jdbcTemplate.queryForList(sql);
return List_maps;
}
@GetMapping("/addUser")
public String addUser(){
String sql="insert into mybatis.user(id,name,pwd) value (1,'小龙','345678')";
jdbcTemplate.update(sql);
return "update-ok";
}
@GetMapping("/updateUser/{id}")
public String updateUser(@PathVariable("id") int id){
String sql="update mybatis.user set name=?,pwd=? where id="+id;
//封装
Object[] objects = new Object[2];
objects[0]="anny";
objects[1]="121212";
jdbcTemplate.update(sql,objects);
return "update-ok";
}
@GetMapping("/deletUser/{id}")
public String deletUser(@PathVariable("id")int id){
String sql="delete from mybatis.user where id=?";
jdbcTemplate.update(sql,id);
return "deletUser-ok";
}
application.yml:
Spring:
datasource:
username: root
password: 123456
url: jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
driver-calss-name: com.mysql.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
是阿里巴巴开源平台上的一个数据库连接池实现,结合了C3p0、DBCP、PROXOOL等DB池的优点,同时加入了日志监控。
Druid依赖<1.2.8>:
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druidartifactId>
<version>1.2.8version>
dependency>
log4j依赖:
<dependency>
<groupId>log4jgroupId>
<artifactId>log4jartifactId>
<version>1.2.17version>
dependency>
application.yml:
#SpringBoot默认是不注入这些的,需要自己绑定
#druid数据源专有配置
Spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource #选择数据源
initialSize: 5
minIdle: 5
maxActive: 20
maxWait: 60000
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
#配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入
#如果允许报错,java.lang.ClassNotFoundException: org.apache.Log4j.Properity
#则导入log4j 依赖就行
filters: stat,wall,log4j
maxPoolPreparedStatementPerConnectionSize: 20
useGlobalDataSourceStat: true
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
DruidConfig:
@Configuration
public class DruidConfig {
@ConfigurationProperties(prefix = "spring.datasource")//绑定application.yml中的Spring: datasource:
@Bean
public DataSource druidDataSource() {
return new DruidDataSource();
}
//后台监控
@Bean
public ServletRegistrationBean StatViewServlet() {
ServletRegistrationBean<StatViewServlet> bean = new ServletRegistrationBean<>(new StatViewServlet(), "/druid/*");
//后台需要有人登录,账号密码配置
HashMap<String, String> initParameters = new HashMap<>();
//增加配置
initParameters.put("loginUsername", "admin");//登录key 是固定的loginUsername loginPassword
initParameters.put("loginPassword", "123456");
//允许谁可以访问
initParameters.put("allow", "");//所有人可访问
//initParameters.put("allow", "localhost");//本机可访问
//禁止谁能访问 initParameters.put("mest","192.168.11.123");
bean.setInitParameters(initParameters);//设置初始化参数
return bean;
}
//filter过滤
@Bean
public FilterRegistrationBean webStatFilter() {
FilterRegistrationBean bean = new FilterRegistrationBean();
bean.setFilter(new WebStatFilter());
//可以过滤哪些请求
Map<String, String> initParameters = new HashMap<>();
//这些东西不进行统计
initParameters.put("exclusions", "*.js,*.css,/druid/*");
bean.setInitParameters(initParameters);
return bean;
}
}
启动项目后访问http://localhost:8080/druid
:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-APwqOhWj-1673610088513)(…/springboot随堂笔记/assets/image-20220822201855299.png)]
service层主要做的是业务逻辑处理的工作,dao层里面做的是和数据库连接的工作。
service层调用dao层的功能,也就是将dao层的类作为service层类的私有成员变量。
mybatis依赖包:
<dependency>
<groupId>org.mybatis.spring.bootgroupId>
<artifactId>mybatis-spring-boot-starterartifactId>
<version>2.2.2version>
dependency>
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#整合mybatis
mybatis.type-aliases-package=com.mest.pojo
mybatis.mapper-locations=classpath:mybatis/mapper/*.xml
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mest.mapper.UserMapper">
<select id="queryUserList" resultType="User">
select * from user
select>
<select id="queryUserByid" resultType="User">
select * from user where id=#{id}
select>
<insert id="addUser" parameterType="User">
insert into user (id,name ,pwd) values (#{id},#{name},#{pwd})
insert>
<update id="updateUser" parameterType="User">
update user set name =#{name},pwd=#{pwd} where id=#{id}
update>
<delete id="deleteUser" parameterType="int">
delete from user where id=#{id}
delete>
mapper>
Service调用dao层
Controller调用service层
web开发中常用的安全功能,过滤器,拦截器
SpringSecurity主要目标是认证和授权(访问控制)
security依赖:
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-securityartifactId>
<version>2.6.8version>
dependency>
securityConfig配置:
@EnableWebSecurity
public class securityConfig extends WebSecurityConfigurerAdapter {
//授权
@Override
protected void configure(HttpSecurity http) throws Exception {
//首页所有人可以访问,功能页只有有权限的人才能访问
//请求授权的规则
http.authorizeRequests().antMatchers("/").permitAll()
.antMatchers("/level1/**").hasRole("vip1")
.antMatchers("/level2/**").hasRole("vip2")
.antMatchers("/level3/**").hasRole("vip3");
//没有权限跳到登录页,需要开启登录的页面
//定制登录页面
http.formLogin().loginPage("/toLogin").loginProcessingUrl("/login");
//http.formLogin().loginPage("/toLogin");
//注销
//防止网站攻击
http.csrf().disable();//关闭csrf功能
http.logout().logoutSuccessUrl("/");
//开启记住我功能 cookie 默认保存两周,自定义接收前端的参数
http.rememberMe().rememberMeParameter("remember");
}
//认证
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//这些数据正常应该从数据库中读
//密码编码错误:There was an unexpected error (type=Internal Server Error, status=500).
auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
.withUser("mest").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1","vip2")
.and().withUser("saisai").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1","vip2","vip3")
.and().withUser("honey").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1");
}
有哪些功能:
Authentication:身份验证、登录、验证用户是否拥有相应的身份。
Authorization:授权,即权限验证。判断用户能进行什么操作。
Session Manager:会话管理,即用户登录就是第一次会话,在没有退出之前,所有信息都保存在会话中。
Remember me:记住我。
…
整合shiro:
项目结构:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uooB0RF6-1673610088515)(assets/image-20220824103551304.png)]
pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.6.4version>
<relativePath/>
parent>
<groupId>com.mestgroupId>
<artifactId>shiroartifactId>
<version>0.0.1-SNAPSHOTversion>
<name>shironame>
<description>Demo project for Spring Bootdescription>
<properties>
<java.version>1.8java.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
dependency>
<dependency>
<groupId>log4jgroupId>
<artifactId>log4jartifactId>
<version>1.2.17version>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druidartifactId>
<version>1.1.12version>
dependency>
<dependency>
<groupId>org.mybatis.spring.bootgroupId>
<artifactId>mybatis-spring-boot-starterartifactId>
<version>2.1.0version>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<version>1.16.10version>
dependency>
<dependency>
<groupId>com.github.theborakompanionigroupId>
<artifactId>thymeleaf-extras-shiroartifactId>
<version>2.0.0version>
dependency>
<dependency>
<groupId>org.apache.shirogroupId>
<artifactId>shiro-springartifactId>
<version>1.4.1version>
dependency>
<dependency>
<groupId>org.thymeleafgroupId>
<artifactId>thymeleaf-spring5artifactId>
dependency>
<dependency>
<groupId>org.thymeleaf.extrasgroupId>
<artifactId>thymeleaf-extras-java8timeartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
plugins>
build>
project>
ShiroConfiger配置类:
@Configuration
public class ShiroConfiger {
//ShiroFilterFactoryBean
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("getDefaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager) {
//设置安全管理器
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
bean.setSecurityManager(defaultWebSecurityManager);
//添加shiro的内置过滤器
/*
* anon:无需认证就可以访问
* authc:必须认证了才能访问
* user:必须拥有记住我功能才能使用
* perms:拥有对某个资源的权限才能访问
* role:拥有某个角色的权限才能访问
* */
// 拦截
Map<String, String> filterMap = new LinkedHashMap<>();
//授权 正常情况下没有授权会跳转到未授权页面下
filterMap.put("/user/add", "perms[user:add]");
filterMap.put("/user/update", "perms[user:update]");
// filterMap.put("/user/add","authc");
// filterMap.put("/user/update","authc");
filterMap.put("/user/*", "authc");
bean.setFilterChainDefinitionMap(filterMap);
//设置登录的请求
bean.setLoginUrl("/toLogin");
//未授权页面
bean.setUnauthorizedUrl("/noauth");
return bean;
}
//DefaultWebSecurityManager
@Bean
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//关联UserRealm
securityManager.setRealm(userRealm);
return securityManager;
}
//创建realm对象,需要自定义类
@Bean
public UserRealm userRealm() {
return new UserRealm();
}
@Bean
//整合shiroDialect: 用来整合shiro和thymeleaf
public ShiroDialect getShiroDialect() {
return new ShiroDialect();
}
}
//自定义realm
public class UserRealm extends AuthorizingRealm {
@Autowired
UserService userService;
// 授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
// info.addStringPermission("user:add");默认会走,开启后全部授权,
//当拿到当前登录的这个对象
Subject subject= SecurityUtils.getSubject();
User currentUser = (User) subject.getPrincipal();//拿到user对象
//设置当前用户的权限
info.addStringPermission(currentUser.getPerms());
return info;
}
// 认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
// //用户名,密码
// String username="root";
// String password="123456";
//连接真实数据库
UsernamePasswordToken userToken = (UsernamePasswordToken) authenticationToken;
// if(!userToken.getUsername().equals(username)){
// return null;//抛出异常
// }
User user = userService.queryUserByName(userToken.getUsername());
if(user==null){//没有这个人
return null;
}
Subject currentSubject = SecurityUtils.getSubject();
Session session = currentSubject.getSession();
session.setAttribute("loginUser",user);
return new SimpleAuthenticationInfo(user,user.getPwd(),"");//把user对象放入
}
}
@Controller
public class MyController {
@GetMapping({"/", "/index"})
public String toIndex(Model model) {
model.addAttribute("msg", "hello,shiro");
return "index";
}
@RequestMapping("/user/add")
public String add() {
return "user/add";
}
@RequestMapping("/user/update")
public String update() {
return "user/update";
}
@RequestMapping("/toLogin")
public String toLogin() {
return "login";
}
@RequestMapping("/login")
public String login(String username, String password, Model model) {
//获取当前对象
Subject subject = SecurityUtils.getSubject();
//封装用户数据
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
try {
subject.login(token);//执行登录的方法 如果没有异常就ok
return "index";
} catch (UnknownAccountException e) {
model.addAttribute("msg", "用户名错误");
return "login";
} catch (IncorrectCredentialsException e) {
model.addAttribute("msg", "密码错误");
return "login";
}
}
@RequestMapping("/noauth")
@ResponseBody
public String unauthroized() {
return "未授权页面";
}
}
mapper层:
@Repository
@Mapper
public interface UserMapper {
public User queryUserByName(String name);
}
实体类pojo:
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private int id;
private String name;
private String pwd;
private String perms;//权限
}
server层:
//UserService
public interface UserService {
public User queryUserByName(String name);
}
UserServiceImpl实现类:
@Service
public class UserServiceImpl implements UserService{
@Autowired
UserMapper userMapper;
@Override
public User queryUserByName(String name) {
return userMapper.queryUserByName(name);
}
}
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mest.mapper.UserMapper">
<select id="queryUserByName" parameterType="String" resultType="User">
select * from mybatis.user where name = #{name}
select>
mapper>
spring:
datasource:
username: root
password: 123456
url: jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
#SpringBoot默认是不注入这些的,需要自己绑定
#druid数据源专有配置
initialSize: 5
minIdle: 5
maxActive: 20
maxWait: 60000
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
#配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入
#如果允许报错,java.lang.ClassNotFoundException: org.apache.Log4j.Properity
#则导入log4j 依赖就行
filters: stat,wall,log4j
maxPoolPreparedStatementPerConnectionSize: 20
useGlobalDataSourceStat: true
connectionoProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
mybatis.type-aliases-package=com.mest.pojo
mybatis.mapper-locations=classpath:mapper/*.xml
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-mailartifactId>
dependency>
<dependency>
<groupId>com.sun.mailgroupId>
<artifactId>jakarta.mailartifactId>
<version>1.6.5version>
dependency>
[email protected]
spring.mail.password=wvwidyvmstzadhah # qq邮箱pop3令牌
spring.mail.host=smtp.qq.com
#开启加密验证
spring.mail.properties.mail.smtp.ssl.enabled=true
@SpringBootTest
class TaskApplicationTests {
@Autowired
JavaMailSenderImpl mailSender;
@Test
void contextLoads() {
//简单的邮件
SimpleMailMessage simpleMailMessage = new SimpleMailMessage();
simpleMailMessage.setSubject("通知");//主题
simpleMailMessage.setText("关于延期开学通知");//文本
simpleMailMessage.setFrom("[email protected]");
simpleMailMessage.setTo("[email protected]");
mailSender.send(simpleMailMessage);
}
//复杂的邮件
@Test
void contextLoads2() throws MessagingException {
MimeMessage mimeMessage = mailSender.createMimeMessage();
//组装
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage,true);
//正文
helper.setSubject("网易夏日摸鱼");
helper.setText("网易邮箱摸鱼大片爆笑热映,加班?大饼?\n 漏漏漏!只要我摸得够多,内卷就追不上我!
",true);
//附件
helper.addAttachment("1.jpg",new File("C:\\Users\\缪晟\\Desktop\\1.jpg"));
helper.setFrom("[email protected]");
helper.setTo("[email protected]");
mailSender.send(mimeMessage);
}
//封装发送邮件的方法
/*
tf:true or false
subject:主题
text:正文
* */
public void sendMail(Boolean tf,String subject,String text) throws MessagingException {
MimeMessage mimeMessage = mailSender.createMimeMessage();
//组装
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage,tf);
//正文
helper.setSubject(subject);
helper.setText(""
+text+"",tf);
//附件
helper.addAttachment("1.jpg",new File("C:\\Users\\缪晟\\Desktop\\1.jpg"));
helper.setFrom("[email protected]");
helper.setTo("[email protected]");
mailSender.send(mimeMessage);
}
}
https://www.bejson.com/ 网络,前端,后端,加解密,转换,数据处理,表达式网站
@Service
public class ScheduledService {
//在一个特定的时间执行
//cron()表达式
/*
//秒 分 时 日 月 星期
30 15 10 * * ? 每天的10点15分30秒执行
0 0/5 10,18 * * ? 每天的10点和18点,每隔5分钟执行执行一次
0 15 10 ? * 1-6 每个月的星期1-6 的10点15分执行一次
0 15 10 L * ? 每个月的最后一天的10点15分执行一次
0/2 * * * * ? 每隔两秒执行一次
* */
//秒 分 时 日 月 星期
@Scheduled(cron = "0/2 * * * * ?")
public void hello(){
System.out.println("hello,你被执行了");
}
}
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-redisartifactId>
dependency>
#SpringBoot所有的配置类,都有一个自动配置类RedisAutoConfig
#自动配置类都会绑定一个properties 配置文件 RedisProperties
spring.redis.host=127.0.0.1
spring.redis.port=6379
@Component
@Data
@AllArgsConstructor
@NoArgsConstructor
//implements Serializable实现序列化
public class User implements Serializable {
private String username;
private Integer age;
}
@SpringBootTest
class SpringbootRedisApplicationTests {
//引入RedisTemplate模板
@Autowired
@Qualifier("redisTemplate")
private RedisTemplate redisTemplate;
@Test
void contextLoads() {
//redisTemplate 操作不同的数据类型 api和我们的指令命令是一致的
//opsForValue 操作字符串 类似String
//opsForList 操作List 类似List
//opsForSet
//opsForHash
//opsForGeo
//除了基本的操作 我们常用的方法也可以通过redisTemplate来操作 比如事务 和CRUD
//获取redis的连接对象
// RedisConnection connection= redisTemplate.getConnectionFactory().getConnection();
// connection.flushAll();
// connection.flushDb();
redisTemplate.opsForValue().set("mykey", "hellomest");
System.err.println(redisTemplate.opsForValue().get("mykey"));
}
//测试存放user对象(User对象未实例化)
@Test
public void testRedis() throws JsonProcessingException {
User user = new User("redis_zhangsan", 12);
String jsonUser = new ObjectMapper().writeValueAsString(user);
redisTemplate.opsForValue().set("user", jsonUser);//key,value
System.err.println(redisTemplate.opsForValue().get("user"));
}
//测试存放user对象(User对象被实例化)
@Test
public void testRedis2() throws JsonProcessingException {
User user = new User("redis_lisi", 11);
redisTemplate.opsForValue().set("user", user);//key,value
System.err.println(redisTemplate.opsForValue().get("user"));
}
//使用RedisUtils工具类
@Autowired
private RedisUtil redisUtil;
@Test
public void testRedisUtil() {
redisUtil.set("username","hello");
System.out.println(redisUtil.get("username"));
}
}
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/**
* 定义RedisTemplate模板
*/
@Configuration
public class RedisConfig {
@Bean
@SuppressWarnings("all")
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
// 连接工厂
redisTemplate.setConnectionFactory(redisConnectionFactory);
// Json序列化配置
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
// String序列化配置
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
// key采用String的序列化方式
redisTemplate.setKeySerializer(stringRedisSerializer);
// hash的key也采用String的序列化方式
redisTemplate.setHashKeySerializer(stringRedisSerializer);
// value序列化方式采用jackson
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
// hash的value序列化方式采用jackson
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
}
在SpringbootRedisApplicationTests中使用RedisTemplate模板:
@Autowired
@Qualifier("redisTemplate")
private RedisTemplate redisTemplate;
@Test
public void testRedis2() throws JsonProcessingException {
User user = new User("redis_lisi", 11);
redisTemplate.opsForValue().set("user", user);//key,value
System.err.println(redisTemplate.opsForValue().get("user"));
}
封装RedisUtils工具类,避免使用原生api的方式编写代码,直接使用:
package com.mest.utils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@Component
public final class RedisUtil {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
// =============================common============================
/**
* 指定缓存失效时间
* @param key 键
* @param time 时间(秒)
*/
public boolean expire(String key, long time) {
try {
if (time > 0) {
redisTemplate.expire(key, time, TimeUnit.SECONDS);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 根据key 获取过期时间
* @param key 键 不能为null
* @return 时间(秒) 返回0代表为永久有效
*/
public long getExpire(String key) {
return redisTemplate.getExpire(key, TimeUnit.SECONDS);
}
/**
* 判断key是否存在
* @param key 键
* @return true 存在 false不存在
*/
public boolean hasKey(String key) {
try {
return redisTemplate.hasKey(key);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 删除缓存
* @param key 可以传一个值 或多个
*/
@SuppressWarnings("unchecked")
public void del(String... key) {
if (key != null && key.length > 0) {
if (key.length == 1) {
redisTemplate.delete(key[0]);
} else {
redisTemplate.delete(CollectionUtils.arrayToList(key));
}
}
}
// ============================String=============================
/**
* 普通缓存获取
* @param key 键
* @return 值
*/
public Object get(String key) {
return key == null ? null : redisTemplate.opsForValue().get(key);
}
/**
* 普通缓存放入
* @param key 键
* @param value 值
* @return true成功 false失败
*/
public boolean set(String key, Object value) {
try {
redisTemplate.opsForValue().set(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 普通缓存放入并设置时间
* @param key 键
* @param value 值
* @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期
* @return true成功 false 失败
*/
public boolean set(String key, Object value, long time) {
try {
if (time > 0) {
redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
} else {
set(key, value);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 递增
* @param key 键
* @param delta 要增加几(大于0)
*/
public long incr(String key, long delta) {
if (delta < 0) {
throw new RuntimeException("递增因子必须大于0");
}
return redisTemplate.opsForValue().increment(key, delta);
}
/**
* 递减
* @param key 键
* @param delta 要减少几(小于0)
*/
public long decr(String key, long delta) {
if (delta < 0) {
throw new RuntimeException("递减因子必须大于0");
}
return redisTemplate.opsForValue().increment(key, -delta);
}
// ================================Map=================================
/**
* HashGet
* @param key 键 不能为null
* @param item 项 不能为null
*/
public Object hget(String key, String item) {
return redisTemplate.opsForHash().get(key, item);
}
/**
* 获取hashKey对应的所有键值
* @param key 键
* @return 对应的多个键值
*/
public Map<Object, Object> hmget(String key) {
return redisTemplate.opsForHash().entries(key);
}
/**
* HashSet
* @param key 键
* @param map 对应多个键值
*/
public boolean hmset(String key, Map<String, Object> map) {
try {
redisTemplate.opsForHash().putAll(key, map);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* HashSet 并设置时间
* @param key 键
* @param map 对应多个键值
* @param time 时间(秒)
* @return true成功 false失败
*/
public boolean hmset(String key, Map<String, Object> map, long time) {
try {
redisTemplate.opsForHash().putAll(key, map);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 向一张hash表中放入数据,如果不存在将创建
*
* @param key 键
* @param item 项
* @param value 值
* @return true 成功 false失败
*/
public boolean hset(String key, String item, Object value) {
try {
redisTemplate.opsForHash().put(key, item, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 向一张hash表中放入数据,如果不存在将创建
*
* @param key 键
* @param item 项
* @param value 值
* @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间
* @return true 成功 false失败
*/
public boolean hset(String key, String item, Object value, long time) {
try {
redisTemplate.opsForHash().put(key, item, value);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 删除hash表中的值
*
* @param key 键 不能为null
* @param item 项 可以使多个 不能为null
*/
public void hdel(String key, Object... item) {
redisTemplate.opsForHash().delete(key, item);
}
/**
* 判断hash表中是否有该项的值
*
* @param key 键 不能为null
* @param item 项 不能为null
* @return true 存在 false不存在
*/
public boolean hHasKey(String key, String item) {
return redisTemplate.opsForHash().hasKey(key, item);
}
/**
* hash递增 如果不存在,就会创建一个 并把新增后的值返回
*
* @param key 键
* @param item 项
* @param by 要增加几(大于0)
*/
public double hincr(String key, String item, double by) {
return redisTemplate.opsForHash().increment(key, item, by);
}
/**
* hash递减
*
* @param key 键
* @param item 项
* @param by 要减少记(小于0)
*/
public double hdecr(String key, String item, double by) {
return redisTemplate.opsForHash().increment(key, item, -by);
}
// ============================set=============================
/**
* 根据key获取Set中的所有值
* @param key 键
*/
public Set<Object> sGet(String key) {
try {
return redisTemplate.opsForSet().members(key);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 根据value从一个set中查询,是否存在
*
* @param key 键
* @param value 值
* @return true 存在 false不存在
*/
public boolean sHasKey(String key, Object value) {
try {
return redisTemplate.opsForSet().isMember(key, value);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 将数据放入set缓存
*
* @param key 键
* @param values 值 可以是多个
* @return 成功个数
*/
public long sSet(String key, Object... values) {
try {
return redisTemplate.opsForSet().add(key, values);
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* 将set数据放入缓存
*
* @param key 键
* @param time 时间(秒)
* @param values 值 可以是多个
* @return 成功个数
*/
public long sSetAndTime(String key, long time, Object... values) {
try {
Long count = redisTemplate.opsForSet().add(key, values);
if (time > 0)
expire(key, time);
return count;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* 获取set缓存的长度
*
* @param key 键
*/
public long sGetSetSize(String key) {
try {
return redisTemplate.opsForSet().size(key);
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* 移除值为value的
*
* @param key 键
* @param values 值 可以是多个
* @return 移除的个数
*/
public long setRemove(String key, Object... values) {
try {
Long count = redisTemplate.opsForSet().remove(key, values);
return count;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
// ===============================list=================================
/**
* 获取list缓存的内容
*
* @param key 键
* @param start 开始
* @param end 结束 0 到 -1代表所有值
*/
public List<Object> lGet(String key, long start, long end) {
try {
return redisTemplate.opsForList().range(key, start, end);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 获取list缓存的长度
*
* @param key 键
*/
public long lGetListSize(String key) {
try {
return redisTemplate.opsForList().size(key);
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* 通过索引 获取list中的值
*
* @param key 键
* @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推
*/
public Object lGetIndex(String key, long index) {
try {
return redisTemplate.opsForList().index(key, index);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 将list放入缓存
*
* @param key 键
* @param value 值
*/
public boolean lSet(String key, Object value) {
try {
redisTemplate.opsForList().rightPush(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 将list放入缓存
* @param key 键
* @param value 值
* @param time 时间(秒)
*/
public boolean lSet(String key, Object value, long time) {
try {
redisTemplate.opsForList().rightPush(key, value);
if (time > 0)
expire(key, time);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 将list放入缓存
*
* @param key 键
* @param value 值
* @return
*/
public boolean lSet(String key, List<Object> value) {
try {
redisTemplate.opsForList().rightPushAll(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 将list放入缓存
*
* @param key 键
* @param value 值
* @param time 时间(秒)
* @return
*/
public boolean lSet(String key, List<Object> value, long time) {
try {
redisTemplate.opsForList().rightPushAll(key, value);
if (time > 0)
expire(key, time);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 根据索引修改list中的某条数据
*
* @param key 键
* @param index 索引
* @param value 值
* @return
*/
public boolean lUpdateIndex(String key, long index, Object value) {
try {
redisTemplate.opsForList().set(key, index, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 移除N个值为value
*
* @param key 键
* @param count 移除多少个
* @param value 值
* @return 移除的个数
*/
public long lRemove(String key, long count, Object value) {
try {
Long remove = redisTemplate.opsForList().remove(key, count, value);
return remove;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
}
在SpringbootRedisApplicationTests中使用RedisUtils工具类:
@Autowired
private RedisUtil redisUtil;
@Test
public void testRedisUtil() {
redisUtil.set("username","hello");
System.out.println(redisUtil.get("username"));
}