个人博客
http://www.milovetingting.cn
第一个SpringBoot程序
1、创建项目
选择Spring Initializr
,点击Next
2、设置项目
3、选择依赖
4、填写项目信息
5、创建controller
FooController
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| package com.wangyz.springboot.controller;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;
@RestController @RequestMapping("/foo") public class FooController { @RequestMapping("/hello") public String hello(){ return "hello"; } }
|
6、运行项目
7、在浏览器查看
修改默认启动banner
在Resources
目录下新建banner.txt
文件,内容随意,如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| //////////////////////////////////////////////////////////////////// // _ooOoo_ // // o8888888o // // 88" . "88 // // (| ^_^ |) // // O\ = /O // // ____/`---'\____ // // .' \\| |// `. // // / \\||| : |||// \ // // / _||||| -:- |||||- \ // // | | \\\ - /// | | // // | \_| ''\---/'' | | // // \ .-\__ `-` ___/-. / // // ___`. .' /--.--\ `. . ___ // // ."" '< `.___\_<|>_/___.' >'"". // // | | : `- \`.;`\ _ /`;.`/ - ` : | | // // \ \ `-. \_ __\ /__ _/ .-` / / // // ========`-.____`-.___\_____/___.-`____.-'======== // // `=---=' // // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // // 佛祖保佑 永不宕机 永无BUG // ////////////////////////////////////////////////////////////////////
|
启动后,可以看到已经修改
YAML
基本数据类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| name: zs
person: name: zs age: 18
student: {name: zs,age: 18}
aninals: - dog - cat
pets: [dog,cat]
|
相对于properties
只能保存key-value
,yaml
可以保存更多的数据类型
在properties
和yaml
中同时配置,properties
的优先级要高。
给实体赋值
1、使用默认的配置文件:application.properties
、application.yaml
1 2 3
| person: name: ls age: 18
|
1 2
| person.name=zs person.age=18
|
person.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| package com.wangyz.springboot.pojo;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component;
@Component @ConfigurationProperties(prefix = "person") public class Person { private String name; private int age;
public Person() { }
public Person(String name, int age) { this.name = name; this.age = age; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
@Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
|
SpringbootApplicationTests.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| package com.wangyz.springboot;
import com.wangyz.springboot.pojo.Person; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest class SpringbootApplicationTests {
@Autowired private Person person;
@Test void contextLoads() { System.out.println(person); }
}
|
2、自定义配置文件
person.properties
1 2
| person.name=ww person.age=18
|
person.java
1 2 3 4 5 6 7 8
| @Component
@PropertySource(value = "classpath:person.properties") public class Person { @Value("${person.name}") private String name; private int age; }
|
JSR303校验
1、依赖引入
1 2 3 4 5 6 7 8 9 10 11
| <dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator</artifactId> <version>7.0.1.Final</version> </dependency>
<dependency> <groupId>jakarta.validation</groupId> <artifactId>jakarta.validation-api</artifactId> <version>3.0.0</version> </dependency>
|
2、增加注解
Person.java
1 2 3 4 5 6
| @Validated public class Person { @Email(message = "邮箱格式不正确") @Value("${person.email}") private String email; }
|
多环境配置
优先级
1、项目根目录下的config文件夹下的配置文件
2、项目根目录下的配置文件
3、Resource目录下的config文件夹下的配置文件
4、Resource目录下的配置文件
多环境
1、通过properties
设置
application-dev.properties
application-test.properties
application.properties
选择环境
1
| spring.profiles.active=test
|
2、通过yaml
设置
application.yaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| server: port: 8084 spring: profiles: active: test
--- server: port: 8085 spring: profiles: dev
--- server: port: 8086 spring: profiles: test
|
静态资源配置
优先级
resources
>static
>public
自定义资源路径
1 2
| spring.mvc.static-path-pattern=/foo/** spring.web.resources.static-locations=classpath:/foo
|
自定义首页
index.html
可以放在resources
目录下的public
,resources
,static
目录下
Thymeleaf
1、导入依赖
1 2 3 4 5 6 7 8 9
| <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>
<dependency> <groupId>nz.net.ultraq.thymeleaf</groupId> <artifactId>thymeleaf-layout-dialect</artifactId> </dependency>
|
2、配置
1 2 3 4 5 6 7 8 9
| spring.thymeleaf.cache = false
spring.thymeleaf.encoding=UTF-8 spring.thymeleaf.mode=HTML5
spring.thymeleaf.suffix=.html
spring.thymeleaf.prefix=classpath:/templates/
|
自定义视图解析器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| package com.wangyz.springboot.config;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.View; import org.springframework.web.servlet.ViewResolver; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.Locale;
@Configuration public class MyMvcConfig implements WebMvcConfigurer {
@Bean public ViewResolver myViewResolver() { return new MyViewResolver(); }
public static class MyViewResolver implements ViewResolver {
@Override public View resolveViewName(String viewName, Locale locale) throws Exception { return null; } } }
|
视图控制器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| package com.wangyz.springboot.config;
import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration public class MyMvcConfig implements WebMvcConfigurer {
@Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/thymeleaf/hello").setViewName("index"); } }
|
JDBC
1、依赖
1 2 3 4 5 6 7 8 9 10
| <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency>
<dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <scope>runtime</scope> </dependency>
|
2、配置
application.yml
1 2 3 4 5 6
| spring: datasource: username: root password: root url: jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf-8 driver-class-name: com.mysql.cj.jdbc.Driver
|
3、使用
JDBCController
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| package com.wangyz.demo.controller;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController;
import java.util.List; import java.util.Map;
@RestController public class JDBCController { @Autowired(required = false) JdbcTemplate template;
@GetMapping("/addUser") public String addUser() { String sql = "insert into mybatis.user(id,name,pwd) values(5,'hello','123456')"; template.update(sql); return "add success!"; }
@GetMapping("/deleteUser/{id}") public String deleteUser(@PathVariable("id") int id) { String sql = "delete from mybatis.user where id=?"; Object[] params = new Object[1]; params[0] = id; template.update(sql, params); return "delete success!"; }
@GetMapping("/updateUser/{id}") public String updateUser(@PathVariable("id") int id) { String sql = "update mybatis.user set name=?,pwd=? where id=?"; Object[] params = new Object[3]; params[0] = "小明"; params[1] = "123456"; params[2] = id; template.update(sql, params); return "update success!"; }
@GetMapping("/userList") public List<Map<String, Object>> getUserList() { String sql = "select * from mybatis.user"; List<Map<String, Object>> list = template.queryForList(sql); return list; } }
|
Druid
1、依赖
1 2 3 4 5
| <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.2.15</version> </dependency>
|
2、配置YAML
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| spring: datasource: username: root password: root url: jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf-8 driver-class-name: com.mysql.cj.jdbc.Driver 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 maxPoolPreparedStatementPerConnectionSize: 20 useGlobalDataSourceStat: true connectionoProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
|
3、Config
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| package com.wangyz.demo.config;
import com.alibaba.druid.pool.DruidDataSource; import com.alibaba.druid.support.http.StatViewServlet; import com.alibaba.druid.support.http.WebStatFilter; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource; import java.util.HashMap; import java.util.Map;
@Configuration public class DruidConfig {
@ConfigurationProperties(prefix = "spring.datasource") @Bean public DataSource druidDataSource(){ return new DruidDataSource(); }
@Bean public ServletRegistrationBean statViewServlet(){ ServletRegistrationBean<StatViewServlet> bean = new ServletRegistrationBean<>(new StatViewServlet(), "/druid/*"); HashMap<String,String> initParam = new HashMap<>(); initParam.put("loginUsername","admin"); initParam.put("loginPassword","123456"); initParam.put("allow","");
bean.setInitParameters(initParam); return bean; }
@Bean public FilterRegistrationBean webStatFilter(){ FilterRegistrationBean bean = new FilterRegistrationBean(); bean.setFilter(new WebStatFilter()); Map<String,String> initParam = new HashMap<>(); initParam.put("exclusions","*.js,*.css,/druid/*"); bean.setInitParameters(initParam); return bean; } }
|
4、访问
http://localhost:8080/druid/index.html
MyBatis
1、依赖
1 2 3 4 5 6 7 8 9
| <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.2.2</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency>
|
2、pojo
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| package com.wangyz.demo.pojo;
import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor;
@Data @AllArgsConstructor @NoArgsConstructor public class User { private int id; private String name; private String pwd; }
|
3、mapper
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| package com.wangyz.demo.mapper;
import com.wangyz.demo.pojo.User; import org.apache.ibatis.annotations.Mapper; import org.springframework.stereotype.Repository;
import java.util.List;
@Mapper @Repository public interface UserMapper {
int addUser(User user);
int deleteUser(int id);
int updateUser(User user);
User getUserById(int id);
List<User> getUserList();
}
|
4、mapper.xml
resource/mybatis/mapper/UserMapper.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "https://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.wangyz.demo.mapper.UserMapper">
<insert id="addUser" parameterType="User"> insert into mybatis.user (id,name,pwd) values(#{id},#{name},#{pwd}) </insert>
<delete id="deleteUser" parameterType="int"> delete from mybatis.user where id = #{id} </delete>
<update id="updateUser" parameterType="User"> update mybatis.user set name=#{name},pwd=#{pwd} where id = #{id} </update>
<select id="getUserById" resultType="User"> select * from mybatis.user where id = #{id} </select>
<select id="getUserList" resultType="User"> select * from mybatis.user </select> </mapper>
|
5、配置
application.properties
1 2
| mybatis.type-aliases-package=com.wangyz.demo.pojo mybatis.mapper-locations=classpath:mybatis/mapper/*.xml
|
Spring Security
1、依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>
<dependency> <groupId>org.thymeleaf.extras</groupId> <artifactId>thymeleaf-extras-springsecurity5</artifactId> <version>3.0.5.RELEASE</version> </dependency>
|
2、controller
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| package com.wangyz.demo.controller;
import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping;
@Controller public class SecurityController {
@RequestMapping("/") public String index() { return "index.html"; }
@RequestMapping("/l1") public String l1() { return "/l1/index.html"; }
@RequestMapping("/l2") public String l2() { return "/l2/index.html"; }
@RequestMapping("/l3") public String l3() { return "/l3/index.html"; }
@RequestMapping("/toLogin") public String login(){ return "login.html"; }
@RequestMapping("/toLogout") public String logout(){ return "logout.html"; } }
|
3、config
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| package com.wangyz.demo.config;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.core.userdetails.User; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
@EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests() .antMatchers("/").permitAll() .antMatchers("/l1/**").hasRole("v1") .antMatchers("/l2/**").hasRole("v2") .antMatchers("/l3/**").hasRole("v3");
http.formLogin() .loginPage("/toLogin") .loginProcessingUrl("/login") .usernameParameter("username") .passwordParameter("password");
http.logout().logoutSuccessUrl("/");
http.rememberMe().rememberMeParameter("remember"); }
@Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder()) .withUser("admin").password(new BCryptPasswordEncoder().encode("123456")).roles("v1", "v2", "v3") .and() .withUser("u1").password(new BCryptPasswordEncoder().encode("123456")).roles("v1") .and() .withUser("u2").password(new BCryptPasswordEncoder().encode("123456")).roles("v2") .and() .withUser("u3").password(new BCryptPasswordEncoder().encode("123456")).roles("v3") ;
} }
|
4、index.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| <!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"> <title>index</title> </head> <body>
<div sec:authorize="isAuthenticated()"> <label sec:authentication="name"></label> <label sec:authentication="principal.authorities"></label> <a th:href="@{/toLogout}">退出</a> </div>
<div sec:authorize="!isAuthenticated()"> <a th:href="@{/toLogin}">登录</a> </div>
<a th:href="@{/l1}">l1</a><br/> <a th:href="@{/l2}">l2</a><br/> <a th:href="@{/l3}">l3</a><br/> </body> </html>
|
5、login.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| <!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"> <title>Login</title> <link th:href="@{/css/bootstrap.min.css}" rel="stylesheet"> <link th:href="@{/css/signin.css}" rel="stylesheet"> </head> <body class="text-center">
<main class="form-signin w-100 m-auto"> <form th:action="@{/login}" method="post"> <img class="mb-4" th:src="@{/img/bootstrap-logo.svg}" alt="" width="72" height="57"> <h1 class="h3 mb-3 fw-normal" text="请登录"></h1>
<div class="form-floating"> <input type="text" class="form-control" id="floatingInput" th:placeholder="用户名" name="username"> <label for="floatingInput" th:text="用户名"></label> </div> <div class="form-floating"> <input type="password" class="form-control" id="floatingPassword" th:placeholder="密码" name="password"> <label for="floatingPassword" th:text="密码"></label> </div>
<div class="checkbox mb-3"> <label> <input type="checkbox" value="remember-me" th:text="记住我" name="remember"> </label> </div> <button class="w-100 btn btn-lg btn-primary" type="submit" th:text="登录"></button> <p class="mt-5 mb-3 text-muted">© 2017–2022</p> </form> </main>
</body> </html>
|
6、logout.html
1 2 3 4 5 6 7 8 9 10 11 12
| <!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Logout</title> </head> <body> <form th:action="@{/logout}" method="post"> <input type="submit" value="退出"> </form> </body> </html>
|
Shiro
1、配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.8.0</version> </dependency>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency>
<dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <scope>runtime</scope> </dependency>
<dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.2.15</version> </dependency>
<dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.2.2</version> </dependency>
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency>
<dependency> <groupId>com.github.theborakompanioni</groupId> <artifactId>thymeleaf-extras-shiro</artifactId> <version>2.1.0</version> </dependency>
|
2、Config
UserRealm.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| package com.wangyz.demo.config;
import com.wangyz.demo.pojo.User; import com.wangyz.demo.service.UserService; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.*; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.authz.SimpleAuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; import org.apache.shiro.subject.Subject; import org.springframework.beans.factory.annotation.Autowired;
public class UserRealm extends AuthorizingRealm {
@Autowired UserService service;
@Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { System.out.println("执行=>doGetAuthorizationInfo");
Subject subject = SecurityUtils.getSubject(); User user = (User) subject.getPrincipal();
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); info.addStringPermission(user.getPerm());
return info; }
@Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { System.out.println("执行=>doGetAuthenticationInfo");
UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
User user = service.getUserByName(token.getUsername());
if (user == null) { return null; }
return new SimpleAuthenticationInfo(user, user.getPwd(), ""); } }
|
ShiroConfig.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
| package com.wangyz.demo.config;
import at.pollux.thymeleaf.shiro.dialect.ShiroDialect; 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;
import java.util.LinkedHashMap; import java.util.Map;
@Configuration public class ShiroConfig {
@Bean public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("getWebSecurityManager") DefaultWebSecurityManager securityManager) { ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
bean.setSecurityManager(securityManager);
Map<String,String> map = new LinkedHashMap<>();
map.put("/user/add","perms[user:add]"); map.put("/user/update","perms[user:update]");
bean.setFilterChainDefinitionMap(map);
bean.setLoginUrl("/user/login");
bean.setUnauthorizedUrl("/user/unauthorized");
return bean; }
@Bean public DefaultWebSecurityManager getWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(userRealm);
return securityManager; }
@Bean public UserRealm userRealm() { return new UserRealm(); }
@Bean public ShiroDialect getShiroDialect(){ return new ShiroDialect(); } }
|
3、Controller
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| package com.wangyz.demo.controller;
import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.IncorrectCredentialsException; import org.apache.shiro.authc.UnknownAccountException; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.subject.Subject; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.*;
@Controller public class WebController {
@RequestMapping("/") public String index(Model model) { model.addAttribute("msg", "hello,shiro"); return "index.html"; }
@RequestMapping("/user/add") public String add() { return "/user/add.html"; }
@RequestMapping("/user/update") public String update() { return "/user/update.html"; }
@GetMapping("/user/login") public String login() { return "login.html"; }
@PostMapping("/user/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 "index.html"; } catch (UnknownAccountException e) { model.addAttribute("msg", "用户名错误"); return "login.html"; } catch (IncorrectCredentialsException e) { model.addAttribute("msg", "密码错误"); return "login.html"; } }
@RequestMapping("/user/unauthorized") @ResponseBody public String unauthorized() { return "未授权,无法访问"; } }
|
其它mybatis相关配置略过。
Swagger
1、依赖
1 2 3 4 5 6 7 8 9 10 11
| <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version> </dependency>
<dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.9.2</version> </dependency>
|
高版本的springboot会报错,因此降级到2.5.2
2、config
1 2 3 4 5 6 7 8 9 10 11
| package com.wangyz.demo.config;
import org.springframework.context.annotation.Configuration; import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration @EnableSwagger2 public class SwaggerConfig {
}
|
3、controller
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| package com.wangyz.demo.controller;
import com.wangyz.demo.pojo.User; import io.swagger.annotations.ApiOperation; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;
@RestController @RequestMapping("/hello") public class HelloController {
@GetMapping("/hello") public String hello(){ return "hello"; }
@ApiOperation("返回用户信息") @PostMapping("/user") public User user(User user){ return user; }
}
|
4、运行
运行后,在浏览器地址栏输入:http://localhost:8080/swagger-ui.html
5、具体配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| package com.wangyz.demo.config;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.env.Environment; import org.springframework.core.env.Profiles; import springfox.documentation.builders.PathSelectors; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.service.ApiInfo; import springfox.documentation.service.Contact; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.util.ArrayList;
@Configuration @EnableSwagger2 public class SwaggerConfig {
@Bean public Docket docket(@Qualifier("apiInfo") ApiInfo apiInfo, Environment environment) { Profiles profiles = Profiles.of("dev"); boolean flag = environment.acceptsProfiles(profiles); return new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo) .enable(flag) .groupName("hello") .select() .apis(RequestHandlerSelectors.basePackage("com.wangyz.demo.controller")) .paths(PathSelectors.ant("/hello/**")) .build(); }
@Bean public Docket docketFoo(@Qualifier("apiInfo") ApiInfo apiInfo, Environment environment) { Profiles profiles = Profiles.of("dev"); boolean flag = environment.acceptsProfiles(profiles); return new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo) .enable(flag) .groupName("foo") .select() .apis(RequestHandlerSelectors.basePackage("com.wangyz.demo.controller")) .paths(PathSelectors.ant("/foo/**")) .build(); }
@Bean public ApiInfo apiInfo() { Contact contact = new Contact("milovetingting", "https://www.milovetingting.cn", "milovetingting@gmail.com"); return new ApiInfo("Api Document", "Api Document description", "v1.0", "https://www.milovetingting.cn", contact, "lisense", "licenseUrl", new ArrayList<>()); } }
|
异步任务
增加EnableAsync
注解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| package com.wangyz.demo;
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.scheduling.annotation.EnableAsync;
@SpringBootApplication @EnableAsync public class DemoApplication {
public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); }
}
|
增加Async
注解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| package com.wangyz.demo.service;
import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service;
@Service public class AsyncService {
@Async public void hello(){ try { Thread.sleep(3000); } catch (Exception e){
} System.out.println("loading"); } }
|
定时任务
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| package com.wangyz.demo;
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication @EnableScheduling public class DemoApplication {
public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); }
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| package com.wangyz.demo.service;
import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service;
@Service public class ScheduleService {
@Scheduled(cron = "0 * * * * 0-7") public void hello(){ System.out.println("hello"); }
}
|
Dubbo-ZooKeeper
配置ZooKeeper
https://www.apache.org/dyn/closer.lua/zookeeper/zookeeper-3.7.1/apache-zookeeper-3.7.1-bin.tar.gz
下载完成后解压到相应的目录下
在解压后的bin目录下,zkServer.cmd
用于启动服务端,zkCli.cmd
用于启动客户端,双击可运行。
配置Dubbo
1、下载源码
https://github.com/apache/dubbo-admin/tree/master
通过git clone
或者通过下载压缩包
2、编译
进行dubbo目录,执行
1
| mvn clean package -Dmaven.test.skip=true
|
执行时,会下载需要的依赖,这个过程需要花费一些时间。
执行完成后,会生成target目录
3、运行
1
| java -jar dubbo-admin-server-0.5.0.jar
|
可能出现的错误:8080端口已被占用
解决方案:
zookeeper 3.5.5版本中包含一个AdminServer默认的端口是8080,所以导致占用。
解决办法:修改zookeeper默认配置
访问http://localhost:8080/
,默认用户名密码都是root
Provider
1、依赖
pom.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-bom</artifactId> <version>3.2.0-beta.4</version> <type>pom</type> <scope>import</scope> </dependency>
<dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-dependencies-zookeeper-curator5</artifactId> <version>3.2.0-beta.4</version> <type>pom</type> </dependency>
<dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-spring-boot-starter</artifactId> <version>3.0.0</version> </dependency>
<dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-dependencies-zookeeper-curator5</artifactId> <version>3.2.0-beta.4</version> <type>pom</type> <exclusions> <exclusion> <artifactId>slf4j-reload4j</artifactId> <groupId>org.slf4j</groupId> </exclusion> </exclusions> </dependency>
|
2、配置
application.properties
1 2 3 4 5 6 7 8
| server.port=8001
dubbo.application.name=provider
dubbo.registry.address=zookeeper://127.0.0.1:2181
dubbo.scan.base-packages=com.wangyz.provider.service
|
3、Service
TicketService.java
1 2 3 4 5 6
| package com.wangyz.provider.service;
public interface TicketService { public String getTicket(); }
|
TicketServiceImpl.java
1 2 3 4 5 6 7 8 9 10 11 12
| package com.wangyz.provider.service;
import org.apache.dubbo.config.annotation.DubboService;
@DubboService public class TicketServiceImpl implements TicketService { @Override public String getTicket() { return "a ticket from provider!"; } }
|
Consumer
1、依赖
pom.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-bom</artifactId> <version>3.2.0-beta.4</version> <type>pom</type> <scope>import</scope> </dependency>
<dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-dependencies-zookeeper-curator5</artifactId> <version>3.2.0-beta.4</version> <type>pom</type> </dependency>
<dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-spring-boot-starter</artifactId> <version>3.0.0</version> </dependency>
<dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-dependencies-zookeeper-curator5</artifactId> <version>3.2.0-beta.4</version> <type>pom</type> <exclusions> <exclusion> <artifactId>slf4j-reload4j</artifactId> <groupId>org.slf4j</groupId> </exclusion> </exclusions> </dependency>
|
2、配置
application.properties
1 2 3 4 5 6
| server.port=8002
dubbo.application.name=consumer
dubbo.registry.address=zookeeper://127.0.0.1:2181
|
3、Service
将之前Provider端的TicketService.java
接口定义复制过来,保证包名和类名路径一致。
UserService.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| package com.wangyz.consumer.service;
import com.wangyz.provider.service.TicketService; import org.apache.dubbo.config.annotation.DubboReference; import org.springframework.stereotype.Service;
@Service public class UserService {
@DubboReference TicketService ticketService;
public String getTicket(){ return ticketService.getTicket(); } }
|
测试
ConsumerApplicationTests.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| package com.wangyz.consumer;
import com.wangyz.consumer.service.UserService; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest class ConsumerApplicationTests {
@Autowired UserService service;
@Test void contextLoads() { System.out.println(service.getTicket()); }
}
|
1、启动Zookeeper
2、启动Provider
3、测试