从零快速搭建一个SpringBoot Web项目
环境:
- IDEA+Navicat+Jdk1.8+Mysql5.7
- SpringBoot+Thymeleaf+SpringData-JPA+apache-shiro
目录
1.2 选择Spring Initializr,指定JDK版本,直接下一步
1.4 选择Web,勾选中间Spring Web,然后下一步
1.7 至此,已经可以直接运行项目(默认端口8080,项目访问路径为/)。
1.8 将项目端口改为8888,项目名称改为demo。新增application.yml(也可以直接在application.properties里面配置,主要取决于个人习惯)
1.10 测试项目,启动应用,使用浏览器访问:127.0.0.1:8888/demo/hello
二、 集成前端框架thymeleaf框架(或freemarker)
2.2 添加UserController用于测试Thymeleaf
2.3 在resources/templates添加user.html
三、 集成SpringDataJPA(或Mybatis-->MybatisPlus)
3.1 在pom.xml中引入SpringDataJPA相关依赖
3.3 完成User、UserRepository、UserService、UserServiceImpl
3.3.2新增接口repository.UserRepository
3.3.4新增类service.impl.UserServiceImpl
3.4 在UserController中使用UserService
四、 安全框架Apache Shiro(或SpringScerity)
一、新建一个SpringBoot项目
1.1 选择新增:File->New->Project
1.2 选择Spring Initializr,指定JDK版本,直接下一步
1.3填写项目相关信息,然后下一步
1.4 选择Web,勾选中间Spring Web,然后下一步
1.5 选择代码存放位置(可默认),点击完成。
1.6 等待代码下载完成,代码结构如下:
1.7 至此,已经可以直接运行项目(默认端口8080,项目访问路径为/)。
1.8 将项目端口改为8888,项目名称改为demo。新增application.yml(也可以直接在application.properties里面配置,主要取决于个人习惯)
配置内容如下:
server:
port: 8888
servlet:
context-path: /demo
1.9 添加HelloController测试Web,代码如下:
package com.oyc.demo.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @Description: Hello测试控制器
* @Author oyc
* @Date 2020/12/1 11:26 下午
*/
@RestController
@RequestMapping("hello")
public class HelloController {
@GetMapping
public String hello(){
return "Hello World";
}
}
1.10 测试项目,启动应用,使用浏览器访问:127.0.0.1:8888/demo/hello,结果如下:
二、集成前端框架thymeleaf框架(或freemarker)
2.1 在pom.xml中添加thymeleaf依赖
<!--thymeleaf 前端框架-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
2.2 添加UserController用于测试Thymeleaf,代码如下:
package com.oyc.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* @Description:用户控制器
* @Author oyc
* @Date 2020/12/1 11:26 下午
*/
@Controller
@RequestMapping("user")
public class UserController {
@GetMapping
public String user(Model model) {
model.addAttribute("title", "欢迎来到用户界面");
return "user";
}
}
2.3 在resources/templates添加user.html,代码如下:
<!DOCTYPE html>
<html lang="en" xmlns="http//www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>用户</title>
</head>
<body>
<h2>用户管理</h2>
<h2 th:text="${title}"></h2>
</body>
</html>
2.4 测试Thymeleaf
启动项目,打开浏览器,访问:127.0.0.1:8888/demo/user
三、集成SpringDataJPA(或Mybatis-->MybatisPlus)
3.1 在pom.xml中引入SpringDataJPA相关依赖
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- druid数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.9</version>
</dependency>
<!-- mybatis-plus https://mvnrepository.com/artifact/com.baomidou/mybatis-plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.1.2</version>
</dependency>
<!--lombok 可以为我们生产getter、setter、构造方法、toString方法等-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.18</version>
<scope>provided</scope>
</dependency>
3.2 配置数据源
spring:
datasource:
url: jdbc:mysql://146.56.192.87:3306/oyc?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&serverTimezone=GMT%2B8
username: oyc
password: 111111
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
### 打开PSCache,并且指定每个连接上PSCache的大小
poolPreparedStatements: true
maxPoolPreparedStatementPerConnectionSize: 20
### 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
filters: stat,wall,log4j
### 通过connectProperties属性来打开mergeSql功能;慢SQL记录
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
3.3 完成User、UserRepository、UserService、UserServiceImpl
3.3.1新增类domain.User,代码如下:
package com.oyc.demo.domain;
import lombok.Data;
import javax.persistence.*;
import java.io.Serializable;
/**
* @Description:
* @Author oyc
* @Date 2020/12/2 12:23 上午
*/
@Data
@Entity
@Table(name = "user")
public class User implements Serializable {
/**
* 用户id
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
/**
* 用户名称
*/
private String name;
/**
* 账号
*/
private String account;
/**
* 密码
*/
private String password;
}
3.4.2新增接口repository.UserRepository,代码如下:
package com.oyc.demo.repository;
import com.oyc.demo.domain.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import java.util.List;
/**
* @ClassName UserRepository
* @Description 用户JPA接口类,继承JPA的JpaRepository,利用Spring Data JPA 的JpaRepository实现数据的操作
* 继承JpaRepository接口 <实体类, 主键类型> JPA根据实体类的类名去对应表名(可以使用@Entity的name属性?@Table进行修改)
* @Author oyc
* @Date 2020/12/2 11:26
* @Version
*/
public interface UserRepository extends JpaRepository<User, Integer>, JpaSpecificationExecutor {
/**
* 根据用户名称查询用户
*
* @param name 用户名称
* @return
*/
List<User> findByName(String name);
/**
* 根据用户账号查询用户
*
* @param account 用户账号
* @return
*/
User findByAccount(String account);
}
3.4.3新增接口service.UserService,代码如下:
package com.oyc.demo.service;
import com.oyc.demo.domain.User;
import java.util.List;
/**
* @Description: 用户服务类接口
* @Author oyc
* @Date 2020/12/2 12:24 上午
*/
public interface UserService {
/**
* 根据id获取用户
*
* @return
*/
User findById(Integer uId);
/**
* 用户列表
*
* @return
*/
List<User> findAll();
/**
* 根据用户名称查询用户
*
* @param name 用户名称
* @return
*/
List<User> findByName(String name);
/**
* 根据用户账号查询用户
*
* @param account 用户账号
* @return
*/
User findByAccount(String account);
/**
* 删除用户
*
* @param uId
*/
void deleteById(Integer uId);
/**
* 删除用户
*
* @param user
*/
void delete(User user);
}
3.4.4新增类service.impl.UserServiceImpl,代码如下:
package com.oyc.demo.service.impl;
import com.oyc.demo.domain.User;
import com.oyc.demo.repository.UserRepository;
import com.oyc.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @Description:
* @Author oyc
* @Date 2020/12/2 12:24 上午
*/
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserRepository userRepository;
@Override
public User findById(Integer uId) {
return userRepository.getOne(uId);
}
@Override
public List<User> findAll() {
return userRepository.findAll();
}
@Override
public List<User> findByName(String name) {
return userRepository.findByName(name);
}
@Override
public User findByAccount(String account) {
return userRepository.findByAccount(account);
}
@Override
public void deleteById(Integer uId) {
userRepository.deleteById(uId);
}
@Override
public void delete(User user) {
userRepository.delete(user);
}
}
3.5 在UserController中使用UserService
添加:
@Autowired
private UserService userService;
和
model.addAttribute("userList", userService.list());
UserController的整体代码如下:
package com.oyc.demo.controller;
import com.oyc.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* @Description:用户控制器
* @Author oyc
* @Date 2020/12/1 11:26 下午
*/
@Controller
@RequestMapping("user")
public class UserController {
@Autowired
private UserService userService;
@GetMapping
public String user(Model model) {
model.addAttribute("title", "欢迎来到用户界面");
model.addAttribute("userList", userService.findAll());
return "user";
}
}
3.6 改造user.html,显示用户列表
添加代码:
<table>
<tr>
<th>id</td>
<th>用户名</td>
</tr>
<tr th:each="user : ${userList}">
<td th:text="${user.id}"></td>
<td th:text="${user.name}"></td>
</tr>
</table>
3.7 集成效果查看
启动项目,打开浏览器,访问:127.0.0.1:8888/demo/user,效果如下:
三、安全框架Apache Shiro(或SpringScerity)
4.1 在pom.xml中添加Apache Shiro依赖,配置如下:
<!--shiro 安全框架 -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.0</version>
</dependency>
4.2 配置CustomRealm和ShiroConfig
CustomRealm代码如下:
package com.oyc.demo.config;
import com.oyc.demo.domain.User;
import com.oyc.demo.service.UserService;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
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.springframework.beans.factory.annotation.Autowired;
/**
* @ClassName CustomRealm
* @Description 自定义用户认证授权器
* @Author oyc
* @Date 2020/12/2 14:07
* @Version
*/
public class CustomRealm extends AuthorizingRealm {
@Autowired
private UserService userService;
/**
* 鉴权
* @param principalCollection
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
//获取登录用户名
String name = (String) principalCollection.getPrimaryPrincipal();
//根据用户名去数据库查询用户信息
User user = userService.findByAccount(name);
if(user == null){
return null;
}
// 添加角色和权限
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
//添加角色
simpleAuthorizationInfo.addRole("admin");
//添加权限,admin:add/user:add
simpleAuthorizationInfo.addStringPermission("admin:add");
return simpleAuthorizationInfo;
}
/**
* 认证
* @param authenticationToken
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//加这一步的目的是在Post请求的时候会先进认证,然后在到请求
if (authenticationToken.getPrincipal() == null) {
return null;
}
//获取用户信息
String name = authenticationToken.getPrincipal().toString();
User user = userService.findByAccount(name);
if (user == null) {
//这里返回后会报出对应异常
return null;
} else {
//这里验证authenticationToken和simpleAuthenticationInfo的信息
return new SimpleAuthenticationInfo(name, user.getPassword(), getName());
}
}
}
ShiroConfig代码如下:
package com.oyc.demo.config;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* @Author: oyc
* @Date: 2020-06-02 16:11
* @Description: shiro配置
*/
@Configuration
public class ShiroConfig {
/**
* Filter工厂,设置对应的过滤条件和跳转条件
*/
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
//拦截器.
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
//配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了
filterChainDefinitionMap.put("/login", "anon");
filterChainDefinitionMap.put("/logout", "logout");
//过滤链定义,从上向下顺序执行,一般将/**放在最为下边 ,authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问
filterChainDefinitionMap.put("/static/**", "anon");
filterChainDefinitionMap.put("/js/**", "anon");
//swagger
filterChainDefinitionMap.put("/swagger-ui.html", "anon");
filterChainDefinitionMap.put("/swagger-resources", "anon");
filterChainDefinitionMap.put("/swagger-resources/configuration/security", "anon");
filterChainDefinitionMap.put("/swagger-resources/configuration/ui", "anon");
filterChainDefinitionMap.put("/v2/api-docs", "anon");
filterChainDefinitionMap.put("/webjars/springfox-swagger-ui/**", "anon");
//对所有用户认证
filterChainDefinitionMap.put("/**", "authc");
//未登录,重定向到登录页面
shiroFilterFactoryBean.setLoginUrl("/toLogin");
filterChainDefinitionMap.put("/**", "authc,user");
//错误页面,认证不通过跳转
shiroFilterFactoryBean.setUnauthorizedUrl("/error");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
/**
* 将自己的验证方式加入容器
*/
@Bean
public CustomRealm myShiroRealm() {
CustomRealm customRealm = new CustomRealm();
return customRealm;
}
/**
* 安全管理器,配置主要是Realm的管理认证
*/
@Bean
public SecurityManager securityManager(CustomRealm myShiroRealm) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
// 设置realm.
securityManager.setRealm(myShiroRealm);
return securityManager;
}
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
@Bean(name = "lifecycleBeanPostProcessor")
public static LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
/**
* 开启Shiro的注解(如@RequiresRoles,@RequiresPermissions),需借助SpringAOP扫描使用Shiro注解的类,并在必要时进行安全逻辑验证
* 配置以下两个bean(DefaultAdvisorAutoProxyCreator(可选)和AuthorizationAttributeSourceAdvisor)即可实现此功能
*
* @return
*/
@Bean
@DependsOn({"lifecycleBeanPostProcessor"})
public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
advisorAutoProxyCreator.setProxyTargetClass(true);
return advisorAutoProxyCreator;
}
}
4.3 添加管理界面admin.html,代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>欢迎使用系统</title>
</head>
<body>
<h1>登录成功,欢迎使用系统</h1>
</body>
</html>
4.4 测试集成效果
启动项目,打开浏览器访问:127.0.0.1:8888/demo,可以正常访问。访问:127.0.0.1:8888/demo/admin,会先出现登录界面,输入正确的用户名和密码之后,点击登录,正常跳转到管理界面。效果如下:
欢迎界面:
登录界面:
管理界面:
4.5 其他优化
密码加密、用户角色从数据库获取(user-->user_role-->role、user-->role_menu-->menu)
未完待续
注: