Springboot
SpringBoot所具备的特征有:
(1)可以创建独立的Spring应用程序,并且基于其Maven或Gradle插件,可以创建可执行的JARs和WARs;
(2)内嵌Tomcat或Jetty等Servlet容器;
(3)提供自动配置的“starter”项目对象模型(POMS)以简化Maven配置;
(4)尽可能自动配置Spring容器;
(5)提供准备好的特性,如指标、健康检查和外部化配置;
(6)绝对没有代码生成,不需要XML配置。
Springboot–Maven的依赖
<!-- 版本仲裁中心 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.3.RELEASE</version>
<relativePath/>
</parent>
<dependencies>
<!-- 场景启动器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 集成swgger -->
<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>
<!-- 集成SpringSecurity-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- thymeleaf整合springsecurity5 -->
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
<version>3.0.4.RELEASE</version>
</dependency>
<!-- Shiro依赖 -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.5.3</version>
</dependency>
<!--shiro整合spring的包-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.5.3</version>
</dependency>
<!-- 集成lombok 自动生成getset -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- 集成redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--导入配置文件处理器,配置文件进行绑定就会有提示-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- 集成jdbc -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!-- juint测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!-- druid数据源 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.18</version>
</dependency>
<!-- mysql驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!-- 集成jquery -->
<dependency>
<groupId>org.webjars.bower</groupId>
<artifactId>jquery</artifactId>
<version>3.3.0</version>
</dependency>
<!-- Springboot对thymeleaf的支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- 分页助手 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.3</version>
</dependency>
<!-- 集成fastjson-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.68</version>
</dependency>
<!--集成 Mybaits -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.2</version>
</dependency>
<!-- jsr303数据校验 -->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
<!-- 集成swgger -->
<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>
<!-- 阿里云的短信服务 -->
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>4.5.3</version>
</dependency>
<!-- Springboot继承jpa -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
</dependencies>
Springboot–properties
# 主配置文件
# 设置端口号
server.port=8181
# 设置项目访问路径
# server.servlet.context-path=/crud
# 设置日志输出的级别
logging.level.com.bdqn.augiugn=trace
logging.level.com.bdqn.dao=debug
#
spring.output.ansi.enabled=ALWAYS
# 指定运行配置文件 application-dev.properties
spring.profiles.active=dev
# 不指定路径在当前项目下生成springboot.log日志
# 可以指定完整的路径;
logging.file.name=spring_boot.log
# 在当前磁盘的根路径下创建spring文件夹和里面的log文件夹;使用?spring.log 作为默认文件
#logging.path=/spring/log
# 在控制台输出的日志的格式
logging.pattern.console=%d{yyyy-MM-dd} [%thread] %-5level %logger{50} - %msg%n
# 指定文件中日志输出的格式
logging.pattern.file=%d{yyyy-MM-dd} === [%thread] === %-5level === %logger{50} ==== %msg%n
##配置数据源
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/smbms?useEncoding=true&characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=123456
#选择druid数据源
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
# 配置mybaits
# 指定全局配置文件的位置
#mybatis.config-location=classpath:mybatis/mybatis-config.xml
# 所有的mapper映射文件
mybatis.mapper-locations=classpath:mybaits/mapper/*.xml
# 定义所有操作类的别名所在包
mybatis.type-aliases-package=com.bdqn.entity
# thymeleaf前缀
spring.thymeleaf.prefix=classpath:/templates/
# thymeleaf后缀
spring.thymeleaf.suffix=.html
spring.thymeleaf.mode=HTML5
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.content-type=text/html
# 开发过程中 建议关闭缓存 false就是关闭,避免改了模板还要重启服务器
spring.thymeleaf.cache=false
#文件上传 限制
spring.http.multipart.maxFileSize=30MB
spring.http.multipart.maxRequestSize=30MB
#不限制大小
#spring.http.multipart.maxFileSize=-1
#spring.http.multipart.maxRequestSize=-1
# 配置redis
spring.redis.host=192.168.92.130
spring.redis.port=6379
# --- jpa ---
# 更新或者创建数据表结构
spring.jpa.hibernate.ddl-auto: update
# 控制台显示SQL
spring.jpa.show-sql=true
#国际化
spring.messages.basename=i18n.index
Config配置
dirud监控
package com.bdqn.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.Arrays;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class DruidConfig {
@ConfigurationProperties(prefix = "spring.datasource")
@Bean
public DataSource druid(){
return new DruidDataSource();
}
//配置Druid的监控
//1、配置一个管理后台的Servlet
@Bean
public ServletRegistrationBean statViewServlet(){
//参数2 设置druid后台的访问路径
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;
}
//2、配置一个web监控的filter
@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;
}
}
加载dirud相关配置
package com.bdqn.util;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.context.annotation.Bean;
import javax.sql.DataSource;
/**
* Generic DataSource configuration.
*/
//@ConditionalOnMissingBean(DataSource.class)
//@ConditionalOnProperty(name = "spring.datasource.type")
public class Generic {
@Bean
public DataSource dataSource(DataSourceProperties properties) {
//使用DataSourceBuilder创建数据源,利用反射创建响应type的数据源,并且绑定相关属性
return properties.initializeDataSourceBuilder().build();
}
}
Springboot自定义异常处理
package com.bdqn.config;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
@ControllerAdvice
public class MyExceptionHandler {
@ResponseBody
@ExceptionHandler(Exception.class)
public Map<String,Object> handleException(Exception e){
Map<String,Object> map = new HashMap<>();
map.put("code","user.notexist");
map.put("message",e.getMessage());
return map;
}
@ExceptionHandler(Exception.class)
public String handleException(Exception e, HttpServletRequest request){
Map<String,Object> map = new HashMap<>();
//传入我们自己的错误状态码 4xx 5xx,否则就不会进入定制错误页面的解析流程
/**
* Integer statusCode = (Integer) request
.getAttribute("javax.servlet.error.status_code");
*/
request.setAttribute("javax.servlet.error.status_code",500);
map.put("code","user.notexist");
map.put("message",e.getMessage());
//转发到/error 下的4xx或者5xx页面
return "forward:/error";
}
}
Swagger
package com.bdqn.config;
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.RequestHandler;
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;
// 项目目录加swagger-ui.html访问swagger
@Configuration //配置类
@EnableSwagger2// 开启Swagger2的自动配置
public class SwaggerConfig {
//如果要设置多个分组 则设置多个docket
@Bean
public Docket docket1(){
return new Docket(DocumentationType.SWAGGER_2).groupName("group1");
}
@Bean
public Docket docket2(){
return new Docket(DocumentationType.SWAGGER_2).groupName("group2");
}
@Bean
public Docket docket3(){
return new Docket(DocumentationType.SWAGGER_2).groupName("group3");
}
@Bean //配置docket以配置Swagger具体参数
public Docket docket(Environment environment) {
// 设置要显示swagger的环境 判断当前是否处于该环境
Profiles of = Profiles.of("dev", "test");
// 通过 enable() 接收此参数判断是否要显示 如果是dev或者text环境则返回true
boolean b = environment.acceptsProfiles(of);
return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo())
.groupName("阿桐幕") // 配置分组
.enable(true) // 配置是否开启Swagger
.select() //通过select()方法,去配置扫描接口,RequestHandlerSelectors配置如何扫描接口
.apis(RequestHandlerSelectors.basePackage("com.bdqn.controller"))
.build();
}
//配置文档信息
private ApiInfo apiInfo() {
Contact contact = new Contact("阿桐幕", "https://gitee.com/", "2661184062@QQ.com");
return new ApiInfo(
"阿桐幕的Swggger", // 标题
"讨厌自己明明不甘于平凡,却又不好好努力!", // 描述
"v1.0", // 版本
"https://www.cnblogs.com/3306La/articles/13790270.html", // 组织链接
contact, // 联系人信息
"Apach 2.0 许可", // 许可
"https://gitee.com/", // 许可连接
new ArrayList<>()// 扩展
);
}
}
自定义拦截器
package com.bdqn.config;
import com.bdqn.util.LoginHandlerInterceptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
//@Configuration
public class MvcInterceptorConfig extends WebMvcConfigurationSupport{
@Autowired
private LoginHandlerInterceptor loginInterceptor;
@Override
protected void addInterceptors(InterceptorRegistry registry) {
// 多个拦截器组成一个拦截器链
// addPathPatterns 用于添加拦截规则,/**表示拦截所有请求
// excludePathPatterns 用户排除拦截 不拦截的请求
registry.addInterceptor(new LoginHandlerInterceptor()).addPathPatterns("/**")
.excludePathPatterns("/login.jsp","/","/user/Login.do");
super.addInterceptors(registry);
}
}
拦截处理页
package com.bdqn.util;
import com.bdqn.config.MvcInterceptorConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 自定义拦截器
*/
@Component
public class LoginHandlerInterceptor implements HandlerInterceptor {
private final Logger logger = LoggerFactory.getLogger(MvcInterceptorConfig.class);
/**
* controller方法执行前,进行拦截的方法
* return true放行
* return false拦截
* 可以使用转发或者重定向直接跳转到指定的页面。
* */
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//request.getHeader(String) 从请求头中获取数据
//从请求头中获取用户token(登陆凭证根据业务而定)
logger.info("request请求地址path[{}] uri[{}]", request.getServletPath(),request.getRequestURI());
Object user = request.getSession().getAttribute("user");
System.out.println(121);
System.out.println(user);
if (user == null){
response.sendRedirect("login.jsp");
return false;
}
return true;
}
/**
* 后处理回调方法,实现处理器(controller)的后处理,但在渲染视图之前
* 此时我们可以通过modelAndView对模型数据进行处理或对视图进行处理
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
/**
* 后处理回调方法,实现处理器(controller)的后处理,但在渲染视图之前
* 此时我们可以通过modelAndView对模型数据进行处理或对视图进行处理
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
分页插件Config
package com.bdqn.config;
import com.github.pagehelper.PageHelper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Properties;
//加入此配置类才能使用分页插件
@Configuration
public class MyBatisPageHelperConfigurition {
@Bean
public PageHelper pageHelper() {
System.out.println("MyBatisConfiguration.pageHelper()");
PageHelper pageHelper = new PageHelper();
Properties p = new Properties();
p.setProperty("offsetAsPageNum", "true");
p.setProperty("rowBoundsWithCount", "true");
p.setProperty("reasonable", "true");
pageHelper.setProperties(p);
return pageHelper;
}
}
pagehelper分页插件简单使用
@RequestMapping("/getAll")
public String getAll(Model model, Integer pageNum , HttpSession session){
System.out.println(pageNum);
Integer pagenum = 1;
if (pageNum != null){
pagenum = pageNum;
}
//封装pagehelper的分页对象 参数 页面 页大小
PageHelper.startPage(pagenum,5);
List<user> userList = users.findAllByempty();
//将集合存入到pageinfo对象中
PageInfo<user> pageInfo = new PageInfo<user>(userList);
// session.setAttribute("pageinfo",pageInfo);
model.addAttribute("pageinfo",pageInfo);
return "index";
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-osxf6ajr-1602653907210)(C:\Users\阿桐慕\AppData\Roaming\Typora\typora-user-images\image-20201013093909810.png)]
自定义RedisTemplate
package com.bdqn.config;
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;
@Configuration
public class RedisConfig {
// 这是我给大家写好的一个固定模板,大家在企业中,拿去就可以直接使用!
// 自己定义了一个 RedisTemplate
@Bean
@SuppressWarnings("all")
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
// 我们为了自己开发方便,一般直接使用 <String, Object>
RedisTemplate<String, Object> template = new RedisTemplate<String,Object>();
template.setConnectionFactory(factory);
// Json序列化配置
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
// String 的序列化
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
// key采用String的序列化方式
template.setKeySerializer(stringRedisSerializer);
// hash的key也采用String的序列化方式
template.setHashKeySerializer(stringRedisSerializer);
// value序列化方式采用jackson
template.setValueSerializer(jackson2JsonRedisSerializer);
// hash的value序列化方式采用jackson
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
}
权限控制
SpringSecurity
package com.spring_boot_security.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.crypto.bcrypt.BCryptPasswordEncoder;
@EnableWebSecurity // 开启WebSecurity模式
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
// 定制请求的授权规则
// 首页所有人可以访问
http.authorizeRequests().antMatchers("/").permitAll()
// antMatchers中的请求 需要hasRole对应的角色权限
.antMatchers("/level1/**").hasRole("vip1")
.antMatchers("/level2/**").hasRole("vip2")
.antMatchers("/level3/**").hasRole("vip3");
// 开启自动配置的登录功能
// /login 请求来到登录页
// /login?error 重定向到这里表示登录失败
http.formLogin();
//开启自动配置的注销的功能
// /logout 注销请求
http.logout();
}
//定义认证规则
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//在内存中定义,也可以在jdbc中去拿....
//Spring security 5.0中新增了多种加密方式,也改变了密码的格式。
//要想我们的项目还能够正常登陆,需要修改一下configure中的代码。我们要将前端传过来的密码进行某种方式加密
//spring security 官方推荐的是使用bcrypt加密方式。
auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
// 给 角色赋予相应的权限
.withUser("loser").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","vip2");
}
}
shior
shior验证流程
shior验证流程:
1、先走controller中的登录请求 Subject的login(AuthenticationToken)方法.
2、再走myrealm类中的doGetAuthenticationInfo()方法的进行登录验证如果登录失败就抛出异常给controller中的登录请求来获取, 然后进行相应的错误处理。如果登录成功(即密码比对成功后)则将当前登录的用户对象存入到Subject对象中后
再执行AuthorizationInfo()方法的授权管理 即对当前登录的用户(注:用户对象通过Subject来获取)进行权限给予
3、最后走ShiroConfig配置类中的getshiroFilterFactoryBean()方法进行请求权限控制 === >>>
如果authc 权限不通过就走setLoginUrl设置的url 即:shiroFactoryBean.setLoginUrl("/toLogin");
如果perms未授权通过页面就走:shiroFactoryBean.setUnauthorizedUrl("/pected");
自定义realm
package com.bdqn.config;
import com.bdqn.dao.Userdao;
import com.bdqn.pojo.User;
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;
<!--
Subject 用户
SecurityManager 管理所有用户
Realm 连接数据库
-->
public class myrealm extends AuthorizingRealm {
@Autowired
Userdao userdao;
//授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("执行了授权---------》》》》》》");
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//拿到当前登录的这个对象
Subject subject = SecurityUtils.getSubject();
User currentUser = (User)subject.getPrincipal();//拿到下面认证时存入的user对象
//设置当前用户的权限 即 user:?
info.addStringPermission("user:"+currentUser.getGender().toString());
return info;
}
//认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println("执行了认证---------》》》》》》");
UsernamePasswordToken userToken = (UsernamePasswordToken)token;
User user = userdao.login(userToken.getUsername());
if (user == null){
return null; //抛出UnknownAccountException异常 用户名不存在
}
// 密码认证,shiro做 将user对象存入到Subject对象中
return new SimpleAuthenticationInfo(user,user.getUserPassword(),"");
}
}
编写配置ShiroConfig
package com.bdqn.config;
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 {
//3. ShiroFilterFactoryBean
@Bean
public ShiroFilterFactoryBean getshiroFilterFactoryBean(@Qualifier("SecurityManager") DefaultWebSecurityManager SecurityManager){
ShiroFilterFactoryBean shiroFactoryBean = new ShiroFilterFactoryBean();
//设置安全管理器
shiroFactoryBean.setSecurityManager(SecurityManager);
/**
- anon: 无需认证就可以访问
- authc: 必须认证了才能访问
- user: 必须拥有记住我功能才能用
- perms: 拥有对某个资源的权限才能访问
- role: 拥有某个角色权限
*/
Map<String,String> filterMap = new LinkedHashMap<>();
//对指定的请求进行权限控制
filterMap.put("/level1/2","perms[user:1]");
filterMap.put("/level2/2","perms[user:1]");
filterMap.put("/level3/2","perms[user:2]");
filterMap.put("/level1/1","anon");
filterMap.put("/level2/1","authc");
filterMap.put("/level3/1","authc");
shiroFactoryBean.setFilterChainDefinitionMap(filterMap);
// authc 权限不通过就走 setLoginUrl 设置的url
shiroFactoryBean.setLoginUrl("/toLogin");
// perms 未授权 页面就走
shiroFactoryBean.setUnauthorizedUrl("/pected");
return shiroFactoryBean;
}
//2. DefaultWebSecurityManager
@Bean(name = "SecurityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("returnMyrealm") myrealm mrealm){
DefaultWebSecurityManager SecurityManager = new DefaultWebSecurityManager();
// 关联myrealm
SecurityManager.setRealm(mrealm);
return SecurityManager;
}
//1. 创建realm对象,需要自定义类
@Bean
public myrealm returnMyrealm(){
return new myrealm();
}
}
登录验证
@PostMapping("/login")
public String login(String username , String password , Model model){
//获取一个用户
Subject subject = SecurityUtils.getSubject();
// 封装用户的登录数据
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
try {
subject.login(token);// 执行登录的方法,如果没有异常就说明登录成功成功了
return "index";
} catch (UnknownAccountException e) { //用户名不存在
model.addAttribute("msg","用户名错误");
return "views/login";
} catch (IncorrectCredentialsException e) {//密码不存在
model.addAttribute("msg","密码错误");
return "views/login";
}
}
跨域解决CorsConfig
package com.bdqn.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
/**
* <p>Title: CorsConfig .java</p>
* <p>Description:跨域问题解决 </p>
* @author youthMing
* @date 2020年5月18日
*/
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowCredentials(true)
.allowedMethods("GET", "POST", "DELETE", "PUT")
.maxAge(3600);
}
}
Springboot整合jpa
实体类配置
package com.bdqn.entity;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import javax.persistence.*;
import java.util.Date;
// 用户表
//使用JPA注解配置映射关系
@Entity //告诉JPA这是一个实体类(和数据表映射的类)
@Table(name = "smbms_user") //@Table来指定和哪个数据表对应;如果省略默认表名就是user(类名首字母小写);
@Data //自动生成getset
public class User {
@Id //这是一个主键
@GeneratedValue(strategy = GenerationType.IDENTITY)//自增主键
private int id ; //id
@Column(name = "username") //省略的话 默认类名就是属性名
private String userName; //用户姓名
@Column(name = "usercode",length = 50) //这是和数据表对应的一个列
private String userCode; //用户编码
@Column(name = "userpassword") //省略的话 默认类名就是属性名
private String userPassword; //用户密码
@Column //省略的话 默认类名就是属性名
private int gender; // 性别 (1女 2男)
@Column //省略的话 默认类名就是属性名
@JsonFormat(pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date birthday; //出生日期
@Column //省略的话 默认类名就是属性名
private String phone; //手机号码
@Column //省略的话 默认类名就是属性名
private String address; //地址
@Column //省略的话 默认类名就是属性名
private int createdBy; //创建者
@Column //省略的话 默认类名就是属性名
private Date creationDate; //创建时间
@Column //省略的话 默认类名就是属性名
private int modifyBy; //更新者
@Column //省略的话 默认类名就是属性名
private Date modifyDate; //更新时间
}
mapper接口配置
apackage com.bdqn.mapper;
import com.bdqn.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import java.util.List;
public interface Usermapper extends JpaRepository<User,Integer> {
// 自定义sql语句
@Query(value = "select * from smbms_user where like username=?",nativeQuery = true)
List<User> queryByNameUser(String name);
}
@GetMapping("/findAll/{pageindex}/{pagesize}")
public Page<User> findAll(@PathVariable(name = "pageindex") Integer pageindex , @PathVariable(name = "pagesize") Integer pagesize){
//jpa的分页实现
Pageable pageable = PageRequest.of(pageindex-1,pagesize);
return usermapper.findAll(pageable);
}
XML配置
Mybaits的mapper.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">
<!-- namespace:接口名 -->
<mapper namespace="com.bdqn.dao.smbms_userdao">
<!--
id:语句的唯一标示 即dao接口中的方法名
parameterType:入参的数据类型
resultType:返回结果的数据类型
#{}:点位符,相当于jdbc的?,里面写个传入对象的属性名字就好 将参数值都改成‘参数’
${}:字符串拼接指令,如果入参为普通数据类型,括号内只能写value 将参数值都改成 参数
-->
<select id="getAlluser" resultType="user">
SELECT u.* , r.`roleName` ,YEAR(NOW())-YEAR(u.`birthday`) AS age FROM smbms_user u
INNER JOIN smbms_role r ON u.`roleId`= r.`id` ORDER BY u.id DESC
limit ${currentPageNo},${pagesize}
</select>
<select id="getbillByparam" resultMap="billList" parameterType="map">
SELECT b.* ,p.* FROM smbms_bill AS b INNER JOIN smbms_provider AS p ON p.id = b.providerId
where 1=1
<!--
prefix 是给sql语句拼接的前缀,
suffix 是给sql语句拼接的后缀。
prefixOverrides 去除sql语句前面的关键字或者字符,该关键字或者字符由prefixOverrides属性指定,
假设该属性指定为"AND",当sql语句的开头为"AND",trim标签将会去除该"AND"
-->
<if test="id != null">and p.id = #{id}</if>
<if test="ductname !=null and ductname != '' ">AND b.`productName` LIKE CONCAT('%',# {ductname},'%')</if>
<if test="isPayment !=null ">AND b.`isPayment` = #{isPayment}</if>
ORDER BY b.creationDate DESC limit #{currentPageNo},#{pageSize}
</select>
<!-- collection begin 一对多《集合》-->
<resultMap id="providerListsS" type="provider">
<!-- property为类中的属性 column为数据库中的字段名 即将column赋值给property -->
<result property="id" column="id"/>
<result property="proCode" column="proCode"/>
<!-- ofType是属性对应的集合当中的类的名称 property表示所属类中的属性名 -->
<collection property="billList" ofType="bill">
<result property="id" column="id"/>
<result property="productName" column="productName"/>
</collection>
</resultMap>
<!-- collection end 一对多-->
<!-- association begin 一对一《类》-->
<resultMap id="billList2" type="bill">
<!-- property为类中的属性 column为数据库中的字段名 即将column赋值给property -->
<result property="productName" column="productName"/>
<result property="billCode" column="billCode"/>
<result property="totalPrice" column="totalPrice"/>
<result property="isPayment" column="isPayment"/>
<result property="creationDate" column="creationDate"/>
<!-- javaType表示该属性对应的类型名称 resultMap《使用外部resultMap》-->
<association property="provi" javaType="provider" resultMap="providerList"/>
</resultMap>
<resultMap id="providerList" type="provider">
<result property="proName" column="proName"/>
<result property="proCode" column="proCode"/>
<result property="proContact" column="proContact"/>
<result property="proPhone" column="proPhone"/>
</resultMap>
<!-- association end 一对一-->
</mapper>
Spring.xml配置
<!-- applicationContext-mybaits.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd">
<!-- 可引入多个配置文件-->
<!--<import resource="xx.xml"/>-->
<!-- 设置spring创建容器时要扫描的包-->
<context:component-scan base-package="bdqn">
<!-- 不扫描控制器Controller注解 -->
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>
<!-- 开启aop注解 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
<!-- 引入properties文件 -->
<context:property-placeholder location="classpath:database.properties"/>
<!-- 配置 数据源 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${user}"/>
<property name="password" value="${pwd}"/>
</bean>
<!-- 配置数据源 -->
<!--<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">-->
<!--<property name="jndiName" value="java:comp/env/smbms"/>-->
<!--</bean>-->
<!-- 配置sqlsessionFactoryBean -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 引用数据源组件 -->
<property name="dataSource" ref="dataSource"/>
<!-- 引用mybaits配置文件 -->
<property name="configLocation" value="classpath:mybaits-cofig.xml"/>
<!-- 配置mapper映射文件 -->
<property name="mapperLocations" value="classpath:bdqn/dao/mapper/*.xml">
<!--<list>-->
<!--<value>classpath:bdqn/dao/mapper/*.xml</value>-->
<!--</list>-->
</property>
<!-- 取别名 -->
<property name="typeAliasesPackage" value="classpath:bdqn.entity"/>
</bean>
<!-- 配置sqlsession -->
<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
<!-- 配置dao方式1 -->
<!--<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">-->
<!-- mapperInterface属性指定映射器 只能是接口类型 -->
<!--<property name="mapperInterface" value="bdqn.dao.smbms_userdao"/>-->
<!--<property name="sqlSessionFactory" ref="sqlSessionFactory"/>-->
<!--</bean>-->
<!-- 配置dao方式2 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 批量生产映射器 生成的dao层bean id为对应的dao接口名(首字母小写)会自动生成sqlSessionFactory-->
<!-- 默认生成dao的实现类 -->
<property name="basePackage" value="bdqn.dao"/>
<!-- 配置sqlsession -->
<!--<property name="sqlSessionFactory" ref="sqlSessionFactory"/>-->
</bean>
<!-- 配置dao方式3 (有实现类)-->
<!--<bean id="userMapper" class="bdqn.dao.impl.userimpl">-->
<!-- 给session赋值 -->
<!--<property name="sqlSessionFactory" ref="sqlSessionFactory"/>-->
<!--</bean>-->
<!-- ================================================================== -->
<!-- 定义事务管理器 -->
<bean id = "txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 为指定的事务管理器设置属性 -->
<tx:advice id = "txAdvice" transaction-manager="txManager">
<!-- 定义属性并声明事务规则 -->
<tx:attributes>
<tx:method name="*" propagation="REQUIRED" />
<!-- read-only="true" 只读 -->
<tx:method name="find*" propagation="SUPPORTS" read-only="true"/>
</tx:attributes>
</tx:advice>
<!-- 定义切面 -->
<aop:config>
<!-- 定义切入点 -->
<aop:pointcut id="pointcut" expression="execution( * bdqn.service.impl.*.*(..))"/>
<!-- 将事务增强与切入点结合-->
<aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut"/>
</aop:config>
<tx:annotation-driven transaction-manager="txManager"/>
</beans>
SpringMvc.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=" http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 开启注解扫描 -->
<context:component-scan base-package="bdqn.controller"/>
<!-- 配置视图解析器对象 -->
<bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 文件所在目录 -->
<property name="prefix" value="/"/>
<!-- 文件的后缀 -->
<property name="suffix" value=".jsp"/>
</bean>
<!-- 注册自定义类型转换器 -->
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="bdqn.util.StringToDateConverter"/>
</set>
</property>
</bean>
<!-- 前端控制器 哪些静态资源不拦截 -->
<!--<mvc:resources mapping="/js/" location="/js/**"/>-->
<!-- 1. location元素表示webapp目录下的包下的所有文件
2. mapping元素表示以/static开头的所有请求路径,如/static/a 或者/static/a/b
-->
<mvc:resources location="/js/" mapping="/js/**"/> <!-- javascript -->
<mvc:resources location="/css/" mapping="/css/**"/>
<mvc:resources location="/images/" mapping="/images/**"/>
<mvc:resources location="/statics/" mapping="/statics/**"/>
<mvc:resources location="/js/" mapping="/smbms/**"/>
<!-- 配置自定义异常处理器 -->
<bean id="sysExceptionResolver" class="bdqn.util.SysExceptionResolver"/>
<!-- 配置全局异常 -->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<prop key="java.lang.RuntimeException">error</prop>
</props>
</property>
</bean>
<!-- 文件上传解析器 --> <!-- id 的值是固定的-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 设置上传文件的最大尺寸为 5MB -->
<property name="maxUploadSize" value="5242880"/>
<!-- 1024*10*5 -->
</bean>
<!-- 配置拦截器 -->
<!--<mvc:interceptors>-->
<!--<mvc:interceptor>-->
<!--<!– 哪些方法进行拦截 –>-->
<!--<mvc:mapping path="/**"/>-->
<!--<!–哪些方法不进行拦截–>-->
<!--<mvc:exclude-mapping path="/Login.do"/>-->
<!--<mvc:exclude-mapping path="/login.jsp"/>-->
<!--<!– 注册拦截器对象 –>-->
<!--<bean class="bdqn.util.MyInterceptor"/>-->
<!--</mvc:interceptor>-->
<!--</mvc:interceptors>-->
<!--<bean name="/index.jsp" class="bdqn.controller.Usercontrollerntroller"/> 相当于resultmapper注解-->
<!-- 开启SpringMvc注解 -->
<mvc:annotation-driven >
<!--消息转换器 -->
<mvc:message-converters>
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<!--加ResponseBody注解 返回string内容运行 -->
<property name="supportedMediaTypes">
<list>
<!--<value>application/json;charset=UTF-8</value>-->
<value>text/html;charset=utf-8</value>
</list>
</property>
</bean>
<!--<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">-->
<!--<property name="supportedMediaTypes">-->
<!--<list>-->
<!--<value>application/json;charset=UTF-8</value>-->
<!--</list>-->
<!--</property>-->
<!--</bean>-->
<!-- 返回对象内容运行 -->
<bean class = "com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>application/json;charset=utf-8</value>
</list>
</property>
<!--<property name="features" value="WriteDateUseDateFormat">-->
<!--</property>-->
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
</beans>
web.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<display-name>Archetype Created Web Application</display-name>
<!--配置Spring的监听器,默认只加载WEB-INF目录下的applicationContext-mybaits.xml配置文件-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!--设置配置文件的路径 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext-mybaits.xml</param-value>
</context-param>
<!-- 配置前端控制器 -->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 加载spring的配置文件 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:SpringMvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- 拦截所有的jsp请求 -->
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- 配置过滤器,解决中文乱码的问题 -->
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<!-- 指定字符集 -->
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<welcome-file-list>
<welcome-file>/login.jsp</welcome-file>
</welcome-file-list>
</web-app>
vue的初始化
vue init webpack myvue 创建一个vue-cil项目 名字为myvue
npm install 初始化项目 需要先进入到myvue项目目录下
npm install vue-router 引入路由
npm install axios 引入axios通信
npm i element-ui -S 引入 element-ui
cnpm install sass-loader node-sass --save-dev 引入sass加载