在springboot中结合shiro搭建权限管理,其中几个小细节的地方对新手不友好,搭建过程容易遇坑,记录一下。关键的地方也给注释了。

版本:springboot版本2.x,shiro1.4

一、依赖

<dependency>
  
<groupId>org.apache.shiro</groupId>
  
<artifactId>shiro-spring</artifactId>
   <version>1.4.0</version>
</dependency>

二、实体

实体有三个,根据规则会自动生成两个中间表,数据库实际上会生成5张表。

分别是User,SysRole,SysPermission,中间表按照@JoinTable来生成。

@Entity
public class User {
@Id
@GenericGenerator(name="generator",strategy = "native")
@GeneratedValue(generator = "generator")
private Integer userId;
@Column(nullable = false, unique = true)
private String userName; //登录用户名
@Column(nullable = false)
private String name;//名称(昵称或者真实姓名,根据实际情况定义)
@Column(nullable = false)
private String password;
private String salt;//加密密码的盐
private byte state;//用户状态,0:创建未认证(比如没有激活,没有输入验证码等等)--等待验证的用户 , 1:正常状态,2:用户被锁定.
@ManyToMany(fetch= FetchType.EAGER)//立即从数据库中进行加载数据;
@JoinTable(name = "SysUserRole", joinColumns = { @JoinColumn(name = "userId") }, inverseJoinColumns ={@JoinColumn(name = "roleId") })
private List<SysRole> roleList;// 一个用户具有多个角色
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm")
private LocalDateTime createTime;//创建时间
@DateTimeFormat(pattern = "yyyy-MM-dd")
private LocalDate expiredDate;//过期日期
private String email; public String getEmail() {
return email;
} public void setEmail(String email) {
this.email = email;
} public LocalDateTime getCreateTime() {
return createTime;
} public void setCreateTime(LocalDateTime createTime) {
this.createTime = createTime;
} public LocalDate getExpiredDate() {
return expiredDate;
} public void setExpiredDate(LocalDate expiredDate) {
this.expiredDate = expiredDate;
} public Integer getUserId() {
return userId;
} public void setUserId(Integer userId) {
this.userId = userId;
} public String getUserName() {
return userName;
} public void setUserName(String userName) {
this.userName = userName;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public String getPassword() {
return password;
} public void setPassword(String password) {
this.password = password;
} public String getSalt() {
return salt;
} public void setSalt(String salt) {
this.salt = salt;
} public byte getState() {
return state;
} public void setState(byte state) {
this.state = state;
} public List<SysRole> getRoleList() {
return roleList;
} public void setRoleList(List<SysRole> roleList) {
this.roleList = roleList;
} /**
* 密码盐. 重新对盐重新进行了定义,用户名+salt,这样就不容易被破解,可以采用多种方式定义加盐
* @return
*/
public String getCredentialsSalt(){
return this.userName+this.salt;
} }
@Entity
public class SysRole {
@Id
@GenericGenerator(name="generator",strategy = "native")
@GeneratedValue(generator = "generator")
private Integer roleId; // 编号
@Column(nullable = false, unique = true)
private String role; // 角色标识程序中判断使用,如"admin",这个是唯一的:
private String description; // 角色描述,UI界面显示使用
private Boolean available = Boolean.TRUE; // 是否可用,如果不可用将不会添加给用户 //角色 -- 权限关系:多对多关系;
@ManyToMany(fetch= FetchType.EAGER)
@JoinTable(name="SysRolePermission",joinColumns={@JoinColumn(name="roleId")},inverseJoinColumns={@JoinColumn(name="permissionId")})
private List<SysPermission> permissions; // 用户 - 角色关系定义;
@ManyToMany
@JoinTable(name="SysUserRole",joinColumns={@JoinColumn(name="roleId")},inverseJoinColumns={@JoinColumn(name="userId")})
private List<User> users;// 一个角色对应多个用户 public Integer getRoleId() {
return roleId;
} public void setRoleId(Integer roleId) {
this.roleId = roleId;
} public String getRole() {
return role;
} public void setRole(String role) {
this.role = role;
} public String getDescription() {
return description;
} public void setDescription(String description) {
this.description = description;
} public Boolean getAvailable() {
return available;
} public void setAvailable(Boolean available) {
this.available = available;
} public List<SysPermission> getPermissions() {
return permissions;
} public void setPermissions(List<SysPermission> permissions) {
this.permissions = permissions;
} public List<User> getUsers() {
return users;
} public void setUsers(List<User> users) {
this.users = users;
}
}
@Entity
public class SysPermission {
@Id
@GenericGenerator(name="generator",strategy = "native")
@GeneratedValue(generator = "generator")
private Integer permissionId;//主键.
@Column(nullable = false)
private String permissionName;//名称.
@Column(columnDefinition="enum('menu','button')")
private String resourceType;//资源类型,[menu|button]
private String url;//资源路径.
private String permission; //权限字符串,menu例子:role:*,button例子:role:create,role:update,role:delete,role:view
private Long parentId; //父编号
private String parentIds; //父编号列表
private Boolean available = Boolean.TRUE;
//角色 -- 权限关系:多对多关系;
@ManyToMany
@JoinTable(name="SysRolePermission",joinColumns={@JoinColumn(name="permissionId")},inverseJoinColumns={@JoinColumn(name="roleId")})
private List<SysRole> roles; public Integer getPermissionId() {
return permissionId;
} public void setPermissionId(Integer permissionId) {
this.permissionId = permissionId;
} public String getPermissionName() {
return permissionName;
} public void setPermissionName(String permissionName) {
this.permissionName = permissionName;
} public String getResourceType() {
return resourceType;
} public void setResourceType(String resourceType) {
this.resourceType = resourceType;
} public String getUrl() {
return url;
} public void setUrl(String url) {
this.url = url;
} public String getPermission() {
return permission;
} public void setPermission(String permission) {
this.permission = permission;
} public Long getParentId() {
return parentId;
} public void setParentId(Long parentId) {
this.parentId = parentId;
} public String getParentIds() {
return parentIds;
} public void setParentIds(String parentIds) {
this.parentIds = parentIds;
} public Boolean getAvailable() {
return available;
} public void setAvailable(Boolean available) {
this.available = available;
} public List<SysRole> getRoles() {
return roles;
} public void setRoles(List<SysRole> roles) {
this.roles = roles;
}
}

三、DAO,这里用JPA

public interface UserRepository extends JpaRepository<User,Integer> {
User findByUserName(String userName);
}

依赖是

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

四、Service

public interface UserService {
User findByUserName(String userName);
} public interface LoginService {
LoginResult login(String userName,String password);
void logout();
}

五、Service.impl

@Service
public class UserServiceImpl implements UserService {
@Resource
private UserRepository userRepository;
@Override
public User findByUserName(String userName) {
return userRepository.findByUserName(userName);
}
}

//内部使用的一个model,根据需要扩展

public class LoginResult {
private boolean isLogin = false;
private String result; public boolean isLogin() {
return isLogin;
} public void setLogin(boolean login) {
isLogin = login;
} public String getResult() {
return result;
} public void setResult(String result) {
this.result = result;
}
}
@Service
public class LoginServiceImpl implements LoginService {
@Override
public LoginResult login(String userName, String password) {
LoginResult loginResult = new LoginResult();
if(userName==null || userName.isEmpty())
{
loginResult.setLogin(false);
loginResult.setResult("用户名为空");
return loginResult;
}
String msg="";
// 1、获取Subject实例对象
Subject currentUser = SecurityUtils.getSubject(); // // 2、判断当前用户是否登录
// if (currentUser.isAuthenticated() == false) {
//
// } // 3、将用户名和密码封装到UsernamePasswordToken
UsernamePasswordToken token = new UsernamePasswordToken(userName, password); // 4、认证
try {
currentUser.login(token);// 传到MyAuthorizingRealm类中的方法进行认证
Session session = currentUser.getSession();
session.setAttribute("userName", userName);
loginResult.setLogin(true);
return loginResult;
//return "/index";
}catch (UnknownAccountException e)
{
e.printStackTrace();
msg = "UnknownAccountException -- > 账号不存在:";
}
catch (IncorrectCredentialsException e)
{
msg = "IncorrectCredentialsException -- > 密码不正确:";
}
catch (AuthenticationException e) {
e.printStackTrace();
msg="用户验证失败";
} loginResult.setLogin(false);
loginResult.setResult(msg); return loginResult;
} @Override
public void logout() {
Subject subject = SecurityUtils.getSubject();
subject.logout();
}
}

六、config,配置类

shiro核心配置

public class MyShiroRealm extends AuthorizingRealm {
@Resource
private UserService userService; //权限信息,包括角色以及权限
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
System.out.println("权限配置-->MyShiroRealm.doGetAuthorizationInfo()");
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
//如果身份认证的时候没有传入User对象,这里只能取到userName
//也就是SimpleAuthenticationInfo构造的时候第一个参数传递需要User对象
User user = (User)principals.getPrimaryPrincipal(); for(SysRole role:user.getRoleList()){
authorizationInfo.addRole(role.getRole());
for(SysPermission p:role.getPermissions()){
authorizationInfo.addStringPermission(p.getPermission());
}
}
return authorizationInfo;
} /*主要是用来进行身份认证的,也就是说验证用户输入的账号和密码是否正确。*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)
throws AuthenticationException {
System.out.println("MyShiroRealm.doGetAuthenticationInfo()");
//获取用户的输入的账号.
String userName = (String)token.getPrincipal();
System.out.println(token.getCredentials());
//通过username从数据库中查找 User对象.
//实际项目中,这里可以根据实际情况做缓存,如果不做,Shiro自己也是有时间间隔机制,2分钟内不会重复执行该方法
User user = userService.findByUserName(userName);
System.out.println("----->>user="+user);
if(user == null){
return null;
}
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
user, //这里传入的是user对象,比对的是用户名,直接传入用户名也没错,但是在授权部分就需要自己重新从数据库里取权限
user.getPassword(), //密码
ByteSource.Util.bytes(user.getCredentialsSalt()),//salt=username+salt
getName() //realm name
);
return authenticationInfo;
} }
@Configuration
public class ShiroConfig {
@Bean
public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
System.out.println("ShiroConfiguration.shirFilter()");
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
//拦截器.
Map<String,String> filterChainDefinitionMap = new LinkedHashMap<String,String>();
// 配置不会被拦截的链接 顺序判断,因为前端模板采用了thymeleaf,这里不能直接使用 ("/static/**", "anon")来配置匿名访问,必须配置到每个静态目录
filterChainDefinitionMap.put("/css/**", "anon");
filterChainDefinitionMap.put("/fonts/**", "anon");
filterChainDefinitionMap.put("/img/**", "anon");
filterChainDefinitionMap.put("/js/**", "anon");
filterChainDefinitionMap.put("/html/**", "anon");
//配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了
filterChainDefinitionMap.put("/logout", "logout");
//<!-- 过滤链定义,从上向下顺序执行,一般将/**放在最为下边 -->:这是一个坑呢,一不小心代码就不好使了;
//<!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问-->
filterChainDefinitionMap.put("/**", "authc");
// 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
shiroFilterFactoryBean.setLoginUrl("/login");
// 登录成功后要跳转的链接
shiroFilterFactoryBean.setSuccessUrl("/index"); //未授权界面;
shiroFilterFactoryBean.setUnauthorizedUrl("/403");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
} /**
* 凭证匹配器
* (由于我们的密码校验交给Shiro的SimpleAuthenticationInfo进行处理了
* )
* @return
*/
@Bean
public HashedCredentialsMatcher hashedCredentialsMatcher(){
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
hashedCredentialsMatcher.setHashAlgorithmName("md5");//散列算法:这里使用MD5算法;
hashedCredentialsMatcher.setHashIterations(2);//散列的次数,比如散列两次,相当于 md5(md5(""));
return hashedCredentialsMatcher;
} @Bean
public MyShiroRealm myShiroRealm(){
MyShiroRealm myShiroRealm = new MyShiroRealm();
myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());
return myShiroRealm;
} @Bean
public SecurityManager securityManager(){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(myShiroRealm());
return securityManager;
} /**
* 开启shiro aop注解支持.
* 使用代理方式;所以需要开启代码支持;
* @param securityManager
* @return
*/
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
} @Bean(name="simpleMappingExceptionResolver")
public SimpleMappingExceptionResolver
createSimpleMappingExceptionResolver() {
SimpleMappingExceptionResolver r = new SimpleMappingExceptionResolver();
Properties mappings = new Properties();
mappings.setProperty("DatabaseException", "databaseError");//数据库异常处理
mappings.setProperty("UnauthorizedException","/user/403");
r.setExceptionMappings(mappings); // None by default
r.setDefaultErrorView("error"); // No default
r.setExceptionAttribute("exception"); // Default is "exception"
//r.setWarnLogCategory("example.MvcLogger"); // No default
return r;
}
}

七、controller

HomeController用来处理登录

@Controller
public class HomeController {
@Resource
private LoginService loginService; @RequestMapping({"/","/index"})
public String index(){
return"/index";
} @RequestMapping("/403")
public String unauthorizedRole(){
System.out.println("------没有权限-------");
return "/user/403";
} @RequestMapping(value = "/login",method = RequestMethod.GET)
public String toLogin(Map<String, Object> map,HttpServletRequest request)
{
loginService.logout();
return "/user/login";
} @RequestMapping(value = "/login",method = RequestMethod.POST)
public String login(Map<String, Object> map,HttpServletRequest request) throws Exception{
System.out.println("login()");
String userName = request.getParameter("userName");
String password = request.getParameter("password"); LoginResult loginResult = loginService.login(userName,password);
if(loginResult.isLogin())
{
return "/index";
}
else {
map.put("msg",loginResult.getResult());
map.put("userName",userName);
return "/user/login";
}
} @RequestMapping("/logout")
public String logOut(HttpSession session) {
loginService.logout();
return "/user/login";
}
}

UserController用来测试访问,权限全部采用注解的方式。

@Controller
@RequestMapping("/user")
public class UserController {
/**
* 用户查询.
* @return
*/
@RequestMapping("/userList")
@RequiresPermissions("user:view")//权限管理;
public String userInfo(){
return "userList";
} /**
* 用户添加;
* @return
*/
@RequestMapping("/userAdd")
@RequiresPermissions("user:add")//权限管理;
public String userInfoAdd(){
return "userAdd";
} /**
* 用户删除;
* @return
*/
@RequestMapping("/userDel")
@RequiresPermissions("user:del")//权限管理;
public String userDel(){
return "userDel";
}
}

八、html

Login.html

<!DOCTYPE html>
<html lang="en"
xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="../static/css/bootstrap.min.css" th:href="@{/css/bootstrap.min.css}"></link> <title>用户登录</title> <style>
.bgColor{
background-color:rgba(243,66,111,0.15)
}
.divBorder{
border: solid 1px rgba(12,24,255,0.15);
padding: 10px;
margin-top: 10px;
border-radius: 10px;
text-align: center;
vertical-align: middle;
}
.h4font{
margin-top: 0px;
font-family: 微软雅黑;
font-weight: 500;
} .center {
padding: 20% 0;
} </style> </head>
<body> <div class="container">
<div class="row center">
<div class="divBorder col-sm-offset-3 col-sm-6">
<h3 class="panel panel-heading h4font">
用户登录
</h3>
<h4 th:text="${msg}"></h4>
<form class="form-horizontal" th:action="@{/login}" method="post">
<div class="input-group input-group-lg">
<span class="input-group-addon"><i class="glyphicon glyphicon-user" aria-hidden="true"></i></span>
<input type="text" class="form-control" id="userName" name="userName" placeholder="请输入用户名称" th:value="${userName}"/>
</div>
<br>
<div class="input-group input-group-lg">
<span class="input-group-addon"><i class="glyphicon glyphicon-lock"></i></span>
<input type="password" class="form-control" id="password" name="password" placeholder="请输入密码"/>
</div> <br>
<input type="submit" class="btn btn-lg btn-block btn-info" value="登 录">
</form>
</div> </div> </div> </body>
</html>

九、数据库里预设一些数据

注意admin的密码是123456,这里保存的是加密后的密码,根据前面的设置,是md5,散列2次。

登录的时候shiro会根据配置自动给密码123456加密,然后与数据库里取出的密码比对。

注意先运行一遍程序,JPA生成数据库表后,手工执行sql脚本插入样本数据。

INSERT INTO `user` (`userId`,`username`,`name`,`password`,`salt`,`state`)
VALUES ('', 'admin', '管理员', 'd3c59d25033dbf980d29554025c23a75', '8d78869f470951332959580424d4bf4f', 0); INSERT INTO `syspermission` (`permissionId`,`available`,`permissionname`,`parentid`,`parentids`,`permission`,`resourcetype`,`url`)
VALUES (1,0,'用户管理',0,'0/','user:view','menu','user/userList');
INSERT INTO `syspermission` (`permissionId`,`available`,`permissionname`,`parentid`,`parentids`,`permission`,`resourcetype`,`url`)
VALUES (2,0,'用户添加',1,'0/1','user:add','button','user/userAdd');
INSERT INTO `syspermission` (`permissionId`,`available`,`permissionname`,`parentid`,`parentids`,`permission`,`resourcetype`,`url`)
VALUES (3,0,'用户删除',1,'0/1','user:del','button','user/userDel'); INSERT INTO `sysrole` (`roleid`,`available`,`description`,`role`) VALUES (1,0,'管理员','admin');
INSERT INTO `sysrole` (`roleid`,`available`,`description`,`role`) VALUES (2,0,'VIP会员','vip');
INSERT INTO `sysrole` (`roleid`,`available`,`description`,`role`) VALUES (3,1,'test','test'); INSERT INTO `sysrolepermission` (`permissionid`,`roleid`) VALUES (1,1);
INSERT INTO `sysrolepermission` (`permissionid`,`roleid`) VALUES (2,1);
INSERT INTO `sysrolepermission` (`permissionid`,`roleid`) VALUES (3,2); INSERT INTO `sysuserrole` (`roleid`,`userId`) VALUES (1,1);

十、其他配置

Application.yml

server:
servlet:
context-path: /
port: 80 spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/crmData?characterEncoding=utf8&useSSL=false
username: root
password: root
jpa:
hibernate:
ddl-auto: update
naming:
physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl #按字段名字建表
show-sql: true
database: mysql
database-platform: org.hibernate.dialect.MySQL5InnoDBDialect thymeleaf:
cache: false messages:
basename: myconfig

所有依赖:

    <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency> <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> <dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-java8time</artifactId>
<!--<version>3.0.1.RELEASE</version>-->
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>compile</scope>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency> <dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency> <dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.0</version>
</dependency>
</dependencies>

目录图:

其他的html页面自己随便生成就可以。

到此基本实现简单的权限管理。

代码可以参考这个地址:https://github.com/asker124143222/bus

Springboot2.0 集成shiro权限管理的更多相关文章

  1. (补漏)Springboot2.0 集成shiro权限管理

    原文Springboot2.0 集成shiro权限管理 一.关于停止使用外键. 原本集成shiro建立用户.角色.权限表的时候使用了外键,系统自动创建其中两个关联表,用@JoinTable.看起来省事 ...

  2. SpringBoot2.0集成Shiro

    1.shiro的三个核心概念: 1)Subject:代表当前正在执行操作的用户,但Subject代表的可以是人,也可以是任何第三方系统帐号.当然每个subject实例都会被绑定到SercurityMa ...

  3. springboot2.0集成shiro出现ShiroDialect报错找不到AbstractTextChildModifierAttrPr

    @Bean public ShiroDialect shiroDialect() { return new ShiroDialect(); } 报错出现找不到org/thymeleaf/process ...

  4. Spring Boot Shiro 权限管理 【转】

    http://blog.csdn.net/catoop/article/details/50520958 主要用于备忘 本来是打算接着写关于数据库方面,集成MyBatis的,刚好赶上朋友问到Shiro ...

  5. (39.4) Spring Boot Shiro权限管理【从零开始学Spring Boot】

    在读此文章之前您还可能需要先了解: (39.1) Spring Boot Shiro权限管理[从零开始学Spring Boot] http://412887952-qq-com.iteye.com/b ...

  6. (39.3) Spring Boot Shiro权限管理【从零开始学Spring Boot】

    在学习此小节之前您可能还需要学习: (39.1) Spring Boot Shiro权限管理[从零开始学Spring Boot] http://412887952-qq-com.iteye.com/b ...

  7. (39.2). Spring Boot Shiro权限管理【从零开始学Spring Boot】

    (本节提供源代码,在最下面可以下载) (4). 集成Shiro 进行用户授权 在看此小节前,您可能需要先看: http://412887952-qq-com.iteye.com/blog/229973 ...

  8. (39.1) Spring Boot Shiro权限管理【从零开始学Spring Boot】

    (本节提供源代码,在最下面可以下载)距上一个章节过了二个星期了,最近时间也是比较紧,一直没有时间可以写博客,今天难得有点时间,就说说Spring Boot如何集成Shiro吧.这个章节会比较复杂,牵涉 ...

  9. Spring Boot Shiro 权限管理

    Spring Boot Shiro 权限管理 标签: springshiro 2016-01-14 23:44 94587人阅读 评论(60) 收藏 举报 .embody{ padding:10px ...

随机推荐

  1. MySQL建表

    -- 1.创建部门表dept 1 CREATE TABLE dept( 2 deptno INT PRIMARY KEY, 3 dname VARCHAR(20) UNIQUE NOT NULL, 4 ...

  2. Java : JPA相关以及常用注解

    SpringDataJPA自定义的查询方法 定义规范       And 并且 Or 或     Is,Equals 等于 Between 两者之间 LessThan 小于 LessThanEqual ...

  3. Java学习笔记五:Java中常用的运算符

    Java中常用的运算符 运算符是一种“功能”符号,用以通知 Java 进行相关的运算.譬如,我们需要将变量 score 的值设置为 20 ,这时候就需要一个“=”,告诉程序需要进行赋值操作. Java ...

  4. 来自一个大三开学三周的huster的迷茫与失措

    大三开学考研保研的话题开始多了起来.自从前天去听了一回谢长生教授的实验室宣讲会,回来直到现在都好像心头上压了些东西,喘不过气来.本来我就少与外界接触,加之我自己一个人主动学习的积极性也很是缺乏,所以当 ...

  5. 002---Python基本数据类型--字符串

    字符串 .caret, .dropup > .btn > .caret { border-top-color: #000 !important; } .label { border: 1p ...

  6. 动态规划----FatMouse’s Speed(HDU 1160)

    参考:https://blog.csdn.net/u012655441/article/details/64920825 https://blog.csdn.net/wy19910326/articl ...

  7. CSS3实现3D球体旋转动画

    html <div class="ball-box"> <div class="ball"> <div class="l ...

  8. [Jmeter]jmeter数据库性能测试配置

    学习jmeter过程中,记录一些学习过程中的点点滴滴,用于备忘.本文主要介绍的是如何创建一个简单的测试计划用户测试数据库服务器. 一.添加线程组 二.添加JDBC请求 1.在第一步里面定义并发用户以及 ...

  9. DSP28335的XINTF操作SRAM实验

    1. 本次使用三兄弟的XDS28335开发板,研究一下XINTF操作SRAM的代码.哈弗结构,奇怪,DSP28335是哈弗结构,那么数据和程序空间应该独立的,为啥书上说采用统一的寻址方式?估计只是读写 ...

  10. 从浏览器或者Webview 中唤醒APP

    本文来自网易云社区 作者:刘新奇 移动互联时代,很多互联网服务都会同时具备网站以及移动客户端,很多人认为APP的能帮助建立更稳固的用户关系,于是经常会接到各种从浏览器.webview中唤醒APP的需求 ...