SpringBoot 整合JDBC
application.yml
spring: datasource: username: root password: 123456 #加入时区报错就增加一个时区配置 serverTimezone=UTC url: jdbc:mysql://localhost:3306/mybats?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8 driver-class-name: com.mysql.jdbc.Driver
JDBCController
@RestController//返回字符串而不是页面 public class JDBCController { @Autowired JdbcTemplate jdbcTemplate; //查询数据库的所有信息并显示在网页上 //没有实体类,数据库中的东西,怎么获取 ? Map @GetMapping("/userList") public List<Map<String,Object>> userList(){ String sql="select * from users"; List<Map<String, Object>> maps = jdbcTemplate.queryForList(sql); return maps; } @GetMapping("/addUser") public String addUesr(){ String sql="insert into mybats.users(id,username) values (9,'longping5666')"; jdbcTemplate.update(sql); return "addUser OK"; } @GetMapping("/updateUser/{id}") public String updateUesr(@PathVariable("id") int id){ String sql="update mybats.users(id,username) set username=? where id="+id; //封装 Object[] objects = new Object[1]; objects[0]="longpingerzi"; jdbcTemplate.update(sql,objects); return "update OK"; } @GetMapping("/deleteUser/{id}") public String deleteUesr(@PathVariable("id") int id){ String sql="delete from mybats.users where id=? "; jdbcTemplate.update(sql,id); return "delete OK"; } }
SpringBoot 整合 Druid
自定义数据源DruidDataSource:
Druid是阿里巴巴开源平台上一个数据库连接池实现,结合了C3PO、DBCP、PROXOOL等DB池的优点,同时加入了日志监控。
Druid可以很好的监控DB池连接和SQL的执行情况,天生就是针对监控而生的DB 连接池。
Spring Boot 2.0以上默认使用Hikari数据源,可以说Hikari与 Driud都是当前Java Web上最优秀的
数据源,我们来重点介绍Spring Boot如何集成Druid数据源,如何实现数据库监控。
HikariDataSource号称Java WEB当前速度最快的数据源,相比于传统的C3PO、DBCP、Tomcat
jdbc等连接池更加优秀;
application.yml
spring: datasource: username: root password: 123456 #时区报错就增加一个时区配置 serverTimezone=UTC url: jdbc:mysql://localhost:3306/mybats?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8 driver-class-name: com.mysql.cj.jdbc.Driver type: com.alibaba.druid.pool.DruidDataSource #修改默认hikari配置源 #Spring Boot默认是不注入这些属性值的,需要自己绑定 #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.Priority #则导入 Log4j依赖即可,Maven地址: https://mvnrepository.com/artifact/Log4j/Log4j filters: stat,wall,log4j maxPoolPreparedstatementPerconnectionSize: 20 useGlobalDatasourcestat: true connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
com.decade.config.DruidConfig
@Configuration//对应bean.xml public class DruidConfig { @ConfigurationProperties(prefix = "spring.datasource")//将自定义的Druid加入到spring容器中 @Bean public DataSource druidDataSource(){ return new DruidDataSource(); } //后台监控功能 :web.xml //因为SpringBoot 内置了 servlet容器,所以没有web.xml,替代方法:ServletRegistrationBean @Bean public ServletRegistrationBean statViewServlet(){ ServletRegistrationBean<StatViewServlet> bean = new ServletRegistrationBean<>(new StatViewServlet(), "/druid/*"); //后台需要有人登陆,账号密码配置 HashMap<String, String> initParameters = new HashMap<>(); //增加配置 initParameters.put("loginUsername","admin");//登陆的key是固定的 initParameters.put("loginPassword","123456"); //允许谁可以访问 initParameters.put("allow","");//都可以访问 //禁止谁能访问 //initParameters.put("kuangshen","192.168.1.0"); bean.setInitParameters(initParameters);//设置初始化参数 return bean; } //filter @Bean public FilterRegistrationBean WebStatFilter(){ FilterRegistrationBean<Filter> bean = new FilterRegistrationBean<>(); bean.setFilter(new WebStatFilter()); //可以过滤哪些请求 Map<String,String> initParameters=new HashMap<>(); //这些东西不进行统计 initParameters.put("exclusions","*.js,*.css,/druid/*"); bean.setInitParameters(initParameters); return bean; } }
SpringBoot整合Mybatis
整合包
mybatis-spring-boot-starter
pojo/User
package com.kuang.pojo; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data @AllArgsConstructor @NoArgsConstructor public class User { private int id; private String username; private String password; }
mapper/UserMapper(Interface)
package com.kuang.mapper; import com.kuang.pojo.User; import org.apache.ibatis.annotations.Mapper; import org.springframework.stereotype.Repository; import java.util.List; @Mapper//表示这是一个mybatis的mapper类 @Repository//被spring整合并且是一个mapper类 public interface UserMapper { List<User> queryUserList(); User queryUserById(int id); int addUser(User user); int updateUser(User user); int deleteUser(int id); }
application.properties
spring.datasource.username=root spring.datasource.password=123456 spring.datasource.url=jdbc:mysql://localhost:3306/mybats?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver #整合mybatis mybatis.type-aliases-package=com.kuang.pojo mybatis.mapper-locations=classpath:mybatis/mapper/*.xml
resources/mybatis/mapper/UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.kuang.mapper.UserMapper"> <select id="queryUserList" resultType="User"> select * from users </select> <select id="queryUserById" resultType="User" > select * from users where id = #{id} </select> <insert id="addUser" parameterType="User"> insert into users (id,username,password) values (#{id},#{username},#{password}) </insert> <update id="updateUser" parameterType="User" > update users set username={username} ,password=#{password} where id = #{id} </update> <delete id="deleteUser" parameterType="int"> delete from user where id = #{id} </delete> </mapper>
com/wzd/controller/UserController
@RestController public class UserController { @Autowired private UserMapper userMapper; //查询 @GetMapping("/queryUserList") public List<User> queryUserList(){ List<User> userList = userMapper.queryUserList(); for (User user : userList) { System.out.println(user); } return userList; } //添加 @GetMapping("/addUser") public String addUser(){ userMapper.addUser(new User(30,"curry","123546")); return "addOK"; } //修改 @GetMapping("/updateUser") public String updateUser(){ userMapper.updateUser(new User(3,"longer","66666")); return "updateOk"; } //删除 @GetMapping("/deleteUser") public String deleteUser(){ userMapper.deleteUser(2); return "deleteOk"; } }
SpringSecurity(安全)
web开发中,安全第一位 过滤器,拦截器
功能性需求:否 非功能性需求:是
做网站:设计之初考虑安全
比如:shiro、springsecurity:很像,认证、授权
- 功能权限
- 访问权限
- 菜单权限
- 。。。拦截器、过滤器:大量的原生代码~冗余
简介
Spring Security是针对Spring项目的安全框架,也是Spring Boot底层安全模块默认的技术选型,他可以实现强大
的Web安全控制,对于安全控制,我们仅需要引入spring-boot-starter-security模块,进行少量的配置,即可实
现强大的安全管理!
记住几个类:
- WebSecurityConfigurerAdapter:自定义Security策略
- AuthenticationManagerBuilder:自定义认证策略
- @EnableWebSecurity:开启WebSecurity模式
Spring Security的两个主要目标是“认证”和“授权”(访问控制)。
“认证”(Authentication)
“授权”(Authorization)
这个概念是通用的,而不是只在Spring Security中存在。
com/kuang/config/SecurityConfig
//AOP @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") .usernameParameter("user")//默认是username(可自定义和前端用户名的name属性值对应) .passwordParameter("pwd");//默认password(可自定义和前端密码的name属性值对应) //防止网站工具:get post http.csrf().disable();//关闭csrf功能 //注销 跳转到首页 http.logout().logoutSuccessUrl("/"); //开启记住我功能 http.rememberMe().rememberMeParameter("remember");//cookie默认保存两周14天,自定义接收前端的参数 //注销并删除cookie和session //http.logout().deleteCookies("remove").invalidateHttpSession(true); } //认证 springboot 2.1.x 可以直接使用 //密码编码:passwordEncoder //在spring security5.0+中新增了很多加密方法 @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { //正常应该从数据库中读 auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder()) .withUser("kuangshen").password(new BCryptPasswordEncoder().encode("123456")).roles("vip2","vip3") .and() .withUser("root").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1","vip2","vip3") .and() .withUser("guest").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1"); } /*从数据库中导入*/ /* @Autowired private DataSource dataSource; @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { UserBuilder users = User.withDefaultPasswordEncoder(); auth .jdbcAuthentication() .dataSource(dataSource) .withDefaultSchema() .withUser(users.username( "user").password("password").roles("USER")) .withUser(users.username("admin").password("password").roles("USER","ADMIN"));*/ }
前端login.html
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"> <title>登录</title> <!--semantic-ui--> <link href="https://cdn.bootcss.com/semantic-ui/2.4.1/semantic.min.css" rel="stylesheet"> </head> <body> <!--主容器--> <div class="ui container"> <div class="ui segment"> <div style="text-align: center"> <h1 class="header">登录</h1> </div> <div class="ui placeholder segment"> <div class="ui column very relaxed stackable grid"> <div class="column"> <div class="ui form"> <form th:action="@{/login}" method="post"> <div class="field"> <label>Username</label> <div class="ui left icon input"> <input type="text" placeholder="Username" name="user"> <i class="user icon"></i> </div> </div> <div class="field"> <label>Password</label> <div class="ui left icon input"> <input type="password" name="pwd"> <i class="lock icon"></i> </div> </div> <div class="field"> <input type="checkbox" name="remember">记住我 </div> <input type="submit" class="ui blue submit button"/> </form> </div> </div> </div> </div> <div style="text-align: center"> <div class="ui label"> </i>注册 </div> <br><br> <small>blog.kuangstudy.com</small> </div> <div class="ui segment" style="text-align: center"> <h3>Spring Security Study by 秦疆</h3> </div> </div> </div> <script th:src="@{/qinjiang/js/jquery-3.1.1.min.js}"></script> <script th:src="@{/qinjiang/js/semantic.min.js}"></script> </body> </html>
首页 index.html
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"> <title>首页</title> <!--semantic-ui--> <link href="https://cdn.bootcss.com/semantic-ui/2.4.1/semantic.min.css" rel="stylesheet"> <link th:href="@{/qinjiang/css/qinstyle.css}" rel="stylesheet"> </head> <body> <!--主容器--> <div class="ui container"> <div class="ui segment" id="index-header-nav" th:fragment="nav-menu"> <div class="ui secondary menu"> <a class="item" th:href="@{/index}">首页</a> <!--登录注销--> <div class="right menu"> <!--如果未登陆 显示登录按钮--> <div sec:authorize="!isAuthenticated()"> <a class="item" th:href="@{/toLogin}"> <i class="address card icon"></i> 登录 </a> </div> <!--如果已登陆 在首页显示用户名 注销--> <div sec:authorize="isAuthenticated()"><!-- 是否已经登录--> <a class="item"> 用户名:<span sec:authentication="name"></span><!--获得用户名字--> </a> </div> <div sec:authorize="isAuthenticated()"> <a class="item" th:href="@{/logout}"> <i class="sign-out icon"></i> 注销 </a> </div> </div> </div> </div> <div class="ui segment" style="text-align: center"> <h3>Spring Security Study by 秦疆</h3> </div> <div> <br> <div class="ui three column stackable grid"> <!--根据用户的权限动态的显示菜单--> <div class="column" sec:authorize="hasRole('vip1')"> <div class="ui raised segment"> <div class="ui"> <div class="content"> <h5 class="content">Level 1</h5> <hr> <div><a th:href="@{/level1/1}"><i class="bullhorn icon"></i> Level-1-1</a></div> <div><a th:href="@{/level1/2}"><i class="bullhorn icon"></i> Level-1-2</a></div> <div><a th:href="@{/level1/3}"><i class="bullhorn icon"></i> Level-1-3</a></div> </div> </div> </div> </div> <div class="column" sec:authorize="hasRole('vip2')"> <div class="ui raised segment"> <div class="ui"> <div class="content"> <h5 class="content">Level 2</h5> <hr> <div><a th:href="@{/level2/1}"><i class="bullhorn icon"></i> Level-2-1</a></div> <div><a th:href="@{/level2/2}"><i class="bullhorn icon"></i> Level-2-2</a></div> <div><a th:href="@{/level2/3}"><i class="bullhorn icon"></i> Level-2-3</a></div> </div> </div> </div> </div> <div class="column" sec:authorize="hasRole('vip3')"> <div class="ui raised segment"> <div class="ui"> <div class="content"> <h5 class="content">Level 3</h5> <hr> <div><a th:href="@{/level3/1}"><i class="bullhorn icon"></i> Level-3-1</a></div> <div><a th:href="@{/level3/2}"><i class="bullhorn icon"></i> Level-3-2</a></div> <div><a th:href="@{/level3/3}"><i class="bullhorn icon"></i> Level-3-3</a></div> </div> </div> </div> </div> </div> </div> </div> <script th:src="@{/qinjiang/js/jquery-3.1.1.min.js}"></script> <script th:src="@{/qinjiang/js/semantic.min.js}"></script> </body> </html>