Введение в Spring Boot
Spring Boot — это новая платформа, предоставленная командой Pivotal, предназначенная для упрощения первоначальной настройки и разработки новых приложений Spring. Фреймворк использует особый способ настройки, поэтому разработчикам больше не нужно определять шаблонную конфигурацию.
Особенности весенней загрузки
-
Создайте отдельное приложение Spring
-
Встроенный Tomcat без развертывания файлов WAR
-
Упрощенная конфигурация Maven
-
Автоматически настроить Spring
-
Предоставляет готовые к работе функции, такие как метрики, проверки работоспособности и внешняя конфигурация.
-
Полное отсутствие генерации кода и требований к конфигурации для XML.
Быстрый старт
1. Посетите http://start.spring.io/, чтобы построить проект, или создайте следующую картинку в идее:
2. Springboot по умолчанию генерирует три файла
2.1 pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Акцент делается на один гав: spring-boot-starter-web, другие можно удалять.
2.2 application.properties
По умолчанию файл пуст, а номер порта запуска Springboot по умолчанию: 8080, который можно изменить в файле. Рекомендуется использовать формат yml
server:
port: 8080
2.3 Файл класса запуска
public class JxcApplication {
public static void main(String[] args) {
SpringApplication.run(JxcApplication.class, args);
}
}
2.4 Проверка весенней загрузки
Создайте контроллер в пути к пакету проекта и напишитеHelloController
@Controller
public class HelloController {
@RequestMapping("/")
@ResponseBody
public String getHello() {
return "hello";
}
}
Эффект просмотра в браузере
Завершить проект
полный каталог проекта
1. Зависимости проекта
- web
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.0</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectjweaver.version}</version>
</dependency>
- mysql
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
- ломбок (по желанию)
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
- помощник страницы (необязательно)
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>${pagehelper.version}</version>
</dependency>
- JWT (необязательно)
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>${jwt.version}</version>
</dependency>
- mybatis
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.2</version>
</dependency>
- shiro
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.0</version>
</dependency>
- хутул (по желанию)
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.0.7</version>
</dependency>
- druid
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
- jdbc
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
- fastjson
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
- tomcat
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
</dependency>
Прикрепить свойства
<properties>
<project.version>1.0</project.version>
<java.version>1.8</java.version>
<mysql.version>5.1.25</mysql.version>
<pagehelper.version>1.2.12</pagehelper.version>
<jwt.version>0.9.1</jwt.version>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<commons.lang.version>3.9</commons.lang.version>
<aspectjweaver.version>1.9.4</aspectjweaver.version>
<fastjson.version>1.2.62</fastjson.version>
</properties>
2. Файл конфигурации
2.1 Модификацияapplication.properties
дляapplication.yml
Порт конфигурации, корневой путь проекта, конфигурация spring, конфигурация mybatis, конфигурация плагина подкачки
server:
port: 8100
servlet:
context-path: /api
spring:
profiles:
active: dev
http:
encoding:
charset: UTF-8
force: true
enabled: true
mybatis:
mapper-locations: classpath:/mapper/*.xml
type-aliases-package: com.example.jxc.domain.entity.*
configuration:
cache-enabled: true
lazy-loading-enabled: true
multiple-result-sets-enabled: true
use-column-label: true
call-setters-on-nulls: true
local-cache-scope: session
map-underscore-to-camel-case: true
default-executor-type: BATCH
auto-mapping-behavior: PARTIAL
pagehelper:
helperDialect: mysql
reasonable: true
supportMethodsArguments: true
params: count=countSql
Конфигурация конфигурации в mybatis, которая является чрезвычайно важным параметром настройки в MyBatis, изменит поведение MyBatis во время выполнения. В следующей таблице описаны назначение, значения по умолчанию и т. д. элементов в настройках.
Найти имя | описывать | действительное значение | По умолчанию |
---|---|---|---|
cacheEnabled | Глобально включает или выключает любые кэши, настроенные всеми картографами в файле конфигурации. | true false | true |
lazyLoadingEnabled | Глобальный переключатель для отложенной загрузки. Когда включено, все связанные объекты загружаются лениво. Состояние переключения элемента можно переопределить, установив свойство fetchType в определенном отношении. | true false | false |
aggressiveLazyLoading | Когда включено, любой вызов метода загрузит все свойства объекта. В противном случае каждое свойство загружается по требованию (см. lazyLoadTriggerMethods). | true false | false (по умолчанию true в 3.4.1 и более ранних версиях) |
multipleResultSetsEnabled | Разрешить ли одному оператору возвращать несколько наборов результатов (требуется поддержка драйвера). | true false | true |
useColumnLabel | Используйте метки столбцов вместо имен столбцов. Разные драйверы имеют разную производительность в этом отношении.Подробности см. в соответствующей документации драйвера или наблюдайте за результатами используемых драйверов при тестировании этих двух разных режимов. | true false | true |
useGeneratedKeys | Чтобы поддержка JDBC могла автоматически генерировать первичные ключи, требуется поддержка драйвера. Если установлено значение true, этот параметр принудительно использует автоматически сгенерированные первичные ключи, что прекрасно работает, даже если некоторые драйверы не поддерживают его (например, Derby). | true false | false |
autoMappingBehavior | Указывает, как MyBatis должен автоматически сопоставлять столбцы с полями или свойствами. NONE означает отмену автоматического сопоставления; PARTIAL автоматически сопоставляет наборы результатов, для которых не определены вложенные сопоставления наборов результатов. FULL автоматически отображает произвольно сложные наборы результатов (вложенные или нет). | NONE, PARTIAL, FULL | PARTIAL |
autoMappingUnknownColumnBehavior | Задает поведение при обнаружении неизвестного столбца (или неизвестного типа свойства) целевого объекта автоматического сопоставления. НЕТ: ничего не делать, ПРЕДУПРЕЖДЕНИЕ: вывод журнала напоминаний (уровень журнала «org.apache.ibatis.session.AutoMappingUnknownColumnBehavior» должен быть установлен на ПРЕДУПРЕЖДЕНИЕ), ОШИБКА: сопоставление не удалось (выдает SqlSessionException) | NONE, WARNING, FAILING | NONE |
defaultExecutorType | Настройте исполнителя по умолчанию. SIMPLE — это обычный исполнитель; исполнитель REUSE будет повторно использовать подготовленные операторы; исполнитель BATCH будет повторно использовать операторы и выполнять пакетные обновления. | SIMPLE REUSE BATCH | SIMPLE |
defaultStatementTimeout | Установите TimeOut, что определяет количество секунд, которые драйвер ждет ответа от базы данных. | любое положительное целое число | не установлен (нулевой) |
defaultFetchSize | Задает значение подсказки для размера выборки результирующего набора драйвера (fetchSize). Этот параметр можно переопределить только в настройках запроса. | любое положительное целое число | не установлен (нулевой) |
defaultResultSetType | Specifies a scroll strategy when omit it per statement settings. (Since: 3.5.2) | FORWARD_ONLY SCROLL_SENSITIVE SCROLL_INSENSITIVE DEFAULT(same behavior with 'Not Set') | Not Set (null) |
safeRowBoundsEnabled | Позволяет использовать пейджинг (RowBounds) во вложенных операторах. Установите значение false, если использование разрешено. | true false | false |
safeResultHandlerEnabled | Tab позволяет использовать (обработчик результатов) во вложенных операторах. Установите значение false, если использование разрешено. | true false | false |
mapUnderscoreToCamelCase | Следует ли автоматически открывать сопоставление соглашения об именах (верблюжий случай), которое сопоставляет имена столбцов A_COLUMN аналогично классическому имени свойства Java aColumn из классической базы данных. | true false | false |
localCacheScope | MyBatis использует механизм локального кэша (Local Cache) для предотвращения циклических ссылок и ускорения повторяющихся вложенных запросов. По умолчанию используется SESSION, и в этом случае все запросы, выполненные в сеансе, кэшируются. Если значение параметра — STATEMENT, локальный сеанс используется только для выполнения инструкции, а разные вызовы одного и того же SqlSession не будут совместно использовать данные. | SESSION STATEMENT | SESSION |
jdbcTypeForNull | Укажите тип JDBC для нулевого значения, если для параметра не указан конкретный тип JDBC. Некоторым драйверам необходимо указать тип столбца JDBC.В большинстве случаев можно напрямую использовать общий тип, например NULL, VARCHAR или OTHER. | Константа JdbcType, общие значения: NULL, VARCHAR или OTHER. | OTHER |
lazyLoadTriggerMethods | Указывает, какой метод объекта запускает ленивую загрузку. | список методов через запятую | equals,clone,hashCode,toString |
defaultScriptingLanguage | Указывает язык по умолчанию для динамического создания SQL. | псевдоним типа или полное имя класса | org.apache.ibatis.scripting.xmltags.XMLLanguageDriver |
defaultEnumTypeHandler | Задает TypeHandler по умолчанию, используемый Enum. (Добавлено в 3.4.5) | псевдоним типа или полное имя класса | org.apache.ibatis.type.EnumTypeHandler |
callSettersOnNulls | Указывает, следует ли вызывать метод setter (put) объекта карты, когда значение в результирующем наборе равно null, что полезно при использовании Map.keySet() или инициализации нулевого значения. Обратите внимание, что примитивные типы (int, boolean и т. д.) не могут иметь значение null. | true false | false |
returnInstanceForEmptyRow | MyBatis возвращает null по умолчанию, когда все столбцы возвращаемой строки пусты. Когда этот параметр включен, MyBatis будет возвращать пустой экземпляр. Обратите внимание, что он также работает с вложенными наборами результатов (такими как коллекции или ассоциации). (Добавлено в 3.4.2) | true false | false |
logPrefix | Указывает префикс, который MyBatis добавляет к именам журналов. | любая строка | не установлен |
logImpl | Укажите MyBatis Укажите конкретную реализацию журнала, используемого MyBatis.Если он не указан, будет выполняться автоматический поиск. | SLF4J,LOG4J,LOG4J2,JDK_LOGGING,COMMONS_LOGGING,STDOUT_LOGGING,NO_LOGGING | не установлен |
proxyFactory | Указывает прокси-инструмент, который Mybatis использует для создания объектов с возможностью отложенной загрузки. | CGLIB ,JAVASSIST | AVASSIST (MyBatis 3.3 и выше) |
vfsImpl | Определяет реализацию VFS | Полные имена классов реализации пользовательской VFS, разделенные запятыми. | не установлен |
useActualParamName | Позволяет использовать имена в сигнатурах методов в качестве имен параметров оператора. Чтобы использовать эту функцию, ваш проект должен быть скомпилирован с помощью Java 8 с параметром -parameters. (Добавлено в 3.4.1) | true false | true |
configurationFactory | Задает класс, предоставляющий экземпляр Configuration. Возвращенный экземпляр Configuration используется для загрузки отложенных значений свойств десериализованного объекта. Этот класс должен содержать метод со статической сигнатурой Configuration getConfiguration(). (Добавлено в 3.2.3) | Введите псевдоним или полное имя класса. | не установлен |
2.2 Новыйapplication-dev.yml
Настройте информацию базы данных черезapplication.yml
активен, чтобы включить профиль разработчика
spring:
profiles:
active: dev
application-dev.yml
Полная конфигурация
spring:
datasource:
# 数据源基本配置
username: root
password:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/fhshgl
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,去掉后监控界面sql无法统计,'wall'用于防火墙
filters: stat,wall
maxPoolPreparedStatementPerConnectionSize: 20
useGlobalDataSourceStat: true
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
3. Пул соединений с базой данных
@Configuration
public class DruidConfig {
@ConfigurationProperties(prefix = "spring.datasource")
@Bean
public DataSource druid(){
return new DruidDataSource();
}
/**
* 配置Druid的监控
* @return
*/
@Bean
public ServletRegistrationBean statViewServlet(){
ServletRegistrationBean bean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
Map<String,String> initParams = new HashMap<>();
initParams.put("loginUsername","admin");
initParams.put("loginPassword","123456");
//默认就是允许所有访问
initParams.put("allow","");
initParams.put("deny","192.168.15.21");
bean.setInitParameters(initParams);
return bean;
}
/**
* 配置一个web监控的filter
* @return
*/
@Bean
public FilterRegistrationBean webStatFilter(){
FilterRegistrationBean bean = new FilterRegistrationBean();
bean.setFilter(new WebStatFilter());
Map<String,String> initParams = new HashMap<>();
initParams.put("exclusions","*.js,*.css,/druid/*");
bean.setInitParameters(initParams);
bean.setUrlPatterns(Arrays.asList("/*"));
return bean;
}
}
4. Широ
4.1 Пользовательский мир
код показывает, как показано ниже:
public class MyRealm extends AuthorizingRealm{
@Autowired
private UserService userService;
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//拿到封装好账户密码的token
UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
String userName = token.getUsername();
//用户校验
User user = this.userService.getUser(userName);
if (user == null) {
throw new AuthenticationException("用户名或密码错误!");
}
//加盐 计算盐值 保证每个加密后的 MD5 不一样
ByteSource credentialsSalt = ByteSource.Util.bytes(user.getUsername());
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, user.getPassword(), credentialsSalt,
this.getName());
return info;
}
}
4.2конфигурация Широ
@Configuration
public class ShiroConfig {
/**
* 主要配置一些相应的URL的规则和访问权限
*/
@Bean
public ShiroFilterFactoryBean shiroFilter() {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager());
//拦截器.
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
//配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了
filterChainDefinitionMap.put("/system/logout", "anon");
//过滤链定义,从上向下顺序执行,一般将/**放在最为下边
//authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问
// filterChainDefinitionMap.put("/static/**", "anon");
shiroFilterFactoryBean.setLoginUrl("/system/login");
filterChainDefinitionMap.put("/**", "authc");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
/**
* 注入 securityManager
*/
@Bean
public DefaultWebSecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
// 设置realm.
securityManager.setRealm(customRealm());
return securityManager;
}
/**
* 自定义身份认证 realm;
* <p>
* 必须写这个类,并加上 @Bean 注解,目的是注入 MyRealm,
* 否则会影响 MyRealm 中其他类的依赖注入
*/
@Bean
public MyRealm customRealm() {
return new MyRealm();
}
/**
* 开启Shiro的注解(如@RequiresRoles,@RequiresPermissions),需借助SpringAOP扫描使用Shiro注解的类,并在必要时进行安全逻辑验证
* 配置以下两个bean(DefaultAdvisorAutoProxyCreator(可选)和AuthorizationAttributeSourceAdvisor)即可实现此功能
*
* @return
*/
@Bean
@DependsOn({"lifecycleBeanPostProcessor"})
public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
advisorAutoProxyCreator.setProxyTargetClass(true);
return advisorAutoProxyCreator;
}
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager());
return authorizationAttributeSourceAdvisor;
}
/**
* Shiro生命周期处理器 ---可以自定的来调用配置在 Spring IOC 容器中 shiro bean 的生命周期方法.
*
* @return
*/
@Bean
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
}
5, фильтр - междоменный фильтр
5.1 Междоменная фильтрация
public class CostFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
String origin = req.getHeader("Origin");
if (origin == null) {
origin = req.getHeader("Referer");
}
// 允许指定域访问跨域资源
resp.setHeader("Access-Control-Allow-Origin", origin);
// 允许客户端携带跨域cookie,此时origin值不能为“*”,只能为指定单一域名
resp.setHeader("Access-Control-Allow-Credentials", "true");
if ("OPTIONS".equals(req.getMethod())) {
String allowMethod = req.getHeader("Access-Control-Request-Method");
String allowHeaders = req.getHeader("Access-Control-Request-Headers");
// 浏览器缓存预检请求结果时间,单位:秒
resp.setHeader("Access-Control-Max-Age", "86400");
// 允许浏览器在预检请求成功之后发送的实际请求方法名
resp.setHeader("Access-Control-Allow-Methods", allowMethod);
// 允许浏览器发送的请求消息头
resp.setHeader("Access-Control-Allow-Headers", allowHeaders);
resp.setHeader("Content-Type", "application/json;charset=utf-8");
return;
}
chain.doFilter(request, response);
}
}
5.2 Конфигурация фильтра
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean configureFilter(){
FilterRegistrationBean bean = new FilterRegistrationBean<>();
bean.setName("costFilter");
CostFilter costFilter = new CostFilter();
bean.setFilter(costFilter);
bean.setOrder(1);
List<String> urlList = new ArrayList<String>();
urlList.add("/*");
bean.setUrlPatterns(urlList);
return bean;
}
}
6. Перехват токена
6.1JWT
класс инструментов jwt
public class JwtUtils {
public static SecretKey getBase64Key() {
String stringKey = "MyJwtSecret";
byte[] encodeKey = Base64.getDecoder().decode(stringKey);
SecretKey key = new SecretKeySpec(encodeKey, 0, encodeKey.length, "AES");
return key;
}
/**
* 签发token
*
* @param userName 用户名
* @return token
*/
public static String create(String userName) {
Date now = new Date(System.currentTimeMillis());
String token = Jwts.builder()
.setIssuedAt(now)
.setSubject(userName)
.setExpiration(new Date(System.currentTimeMillis() + 60 * 60 * 1000))
.signWith(SignatureAlgorithm.HS256, getBase64Key())
.compact();
return token;
}
/**
* 解析token
*
* @param token token
* @return 用户名
*/
public static String parse(String token) {
String username = null;
try {
username = Jwts.parser()
.setSigningKey(getBase64Key())
.parseClaimsJws(token.replace("Bearer ", ""))
.getBody()
.getSubject();
} catch (Exception e) {
e.printStackTrace();
}
return username;
}
/**
* 检验token是否过期
*
* @param token
* @return
*/
public static boolean verify(String token) {
Date expiraDate = null;
Date currentDate = new Date();
try {
expiraDate = Jwts.parser()
.setSigningKey(getBase64Key())
.parseClaimsJws(token.replace("Bearer ", ""))
.getBody()
.getExpiration();
if (currentDate.before(expiraDate)) {
return true;
} else {
return false;
}
} catch (Exception e) {
return false;
}
}
}
6.2 токен-перехватчик
@Component
public class TokenInterceptor implements HandlerInterceptor {
public Log log = LogFactory.getLog(TokenInterceptor.class);
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler){
if (request.getMethod().equals("OPTIONS")) {
response.setStatus(HttpServletResponse.SC_OK);
return true;
}
response.setCharacterEncoding("utf-8");
String token = request.getHeader("Authorization");
if (token != null) {
boolean result = JwtUtils.verify(token);
if (result) {
return true;
}
}
log.error("认证失败");
response.setStatus(HttpServletResponse.SC_NON_AUTHORITATIVE_INFORMATION);
return false;
}
}
6.3 Настройка перехватчика
@Configuration
public class InterceptorConfig extends WebMvcConfigurationSupport {
@Autowired
private TokenInterceptor tokenInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(tokenInterceptor)
.addPathPatterns("/**")
.excludePathPatterns("/**/login")
.excludePathPatterns("/**/logOut");
}
}
7, заполните интерфейс входа в системуLoginController
@RestController
@RequestMapping("/system")
public class LoginController extends BaseController {
@Autowired
private UserService userService;
/**
* 浏览器点击登录
*
* @param user
* @return
*/
@PostMapping("/login")
public R login(@RequestBody User user) {
log.debug("------浏览器点击登录------");
String userName = user.getUsername();
String passWord = user.getPassword();
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(userName, MD5.md5Salt(passWord, userName));
Subject subject = SecurityUtils.getSubject();
try {
subject.login(usernamePasswordToken);
String token = JwtUtils.create(userName);
return R.ok(R.SUCCESS, R.MSG_SUCCESS, token);
} catch (AuthenticationException e) {
e.printStackTrace();
return R.error(R.MSG_LOGIN_ERROR);
}
}
}
Нет публики: