工作流activiti笔记(三)坑!!!手把手!!
1、使用candidateUser会报错:
List<Task> tasks = taskService.createTaskQuery()
.taskCandidateUser(flowTaskReq.getAssignee())
org.springframework.security.core.userdetails.UsernameNotFoundException: 张三
解决方案:
关于解决方案,往上其实有很多答案,但是每个都只是贴代码,而没有解释说明该怎么用!!!!!
新建两个类:SpringSecurityConfig 和SecurityUtil
package com.xy.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;/*** 如果不存在该WebSecurityConfigurerAdapter的实现类,启动的时候,会报错:* Consider defining a bean of type 'org.springframework.security.config.annotation.web.builders.HttpSecurity' in your configuration.*/
@Configuration
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {@Beanpublic UserDetailsService myUserDetailsService() {return SecurityUtil.findInstance();}}
SecurityUtil
package com.xy.config;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.context.SecurityContextImpl;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.stereotype.Component;import java.util.ArrayList;
import java.util.Collection;
import java.util.List;@Component
public class SecurityUtil {private Logger logger = LoggerFactory.getLogger(SecurityUtil.class);private static InMemoryUserDetailsManager inMemoryUserDetailsManager;//查询实例public static InMemoryUserDetailsManager findInstance(){if(inMemoryUserDetailsManager==null){inMemoryUserDetailsManager = new InMemoryUserDetailsManager();}return inMemoryUserDetailsManager;}//createUser() 方法用于创建一个新的用户,如果该用户已经存在则先删除再创建。新创建的用户需要设置两个角色:"ROLE_ACTIVITI_USER" 和 "GROUP_activitiTeam"private void createUser(String userName) {inMemoryUserDetailsManager = findInstance();if(inMemoryUserDetailsManager.userExists(userName)) {inMemoryUserDetailsManager.deleteUser(userName);}//SimpleGrantedAuthority 是一个自定义的权限类,用于设置角色的名称。List<SimpleGrantedAuthority> roles = new ArrayList<SimpleGrantedAuthority>(){{add(new SimpleGrantedAuthority("ROLE_ACTIVITI_USER"));add(new SimpleGrantedAuthority("GROUP_activitiTeam"));}};//passwordEncoder() 方法用于设置密码加密方式为 BCryptPasswordEncoderinMemoryUserDetailsManager.createUser(new User(userName, passwordEncoder().encode("password"),roles));}//logInAs() 方法用于以指定用户名登录系统,并获取当前用户的用户名和权限信息public void logInAs(String username) {createUser(username);UserDetails user = findInstance().loadUserByUsername(username);if (user == null) {throw new IllegalStateException("User " + username + " doesn't exist, please provide a valid user");}logger.info("> Logged in as: " + username);//SecurityContextHolder 是一个 Spring Security 提供的上下文处理器,用于在请求处理过程中维护用户的认证状态和权限信息SecurityContextHolder.setContext(new SecurityContextImpl(new Authentication() {@Overridepublic Collection<? extends GrantedAuthority> getAuthorities() {return user.getAuthorities();}@Overridepublic Object getCredentials() {return user.getPassword();}@Overridepublic Object getDetails() {return user;}@Overridepublic Object getPrincipal() {return user;}@Overridepublic boolean isAuthenticated() {return true;}@Overridepublic void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {}@Overridepublic String getName() {return user.getUsername();}}));org.activiti.engine.impl.identity.Authentication.setAuthenticatedUserId(username);}private PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}
}
上面说了,调用下面这个会报错:
taskService.createTaskQuery().taskCandidateUser
所以解决方案是在调用前准备我说的那两个类,然后在使用taskService.createTaskQuery().taskCandidateUser时,先把下面这段代码放到最前面。
SecurityUtil bean = SpringUtils.getBean(SecurityUtil.class);bean.logInAs("张三");
SpringUtils自不必说,获取spring容器中的bean,这个没人不会,就不贴代码了 。
自此,问题解决!!!
2、查询Task 直接放回List<Task>报错
.converter.HttpMessageNotWritableException: Could not write JSON: (was java.lang.NullPointerException); nested exception is com.fasterxml.jackson.databind.JsonMappingException: (was java.lang.NullPointerException) (through reference chain: com.xy.util.R["data"]->com.baomidou.mybatisplus.extension.plugins.pagination.Page["records"]->java.util.ArrayList[0]->org.activiti.engine.impl.persistence.entity.TaskEntityImpl["candidates"])]
由于Task中某些字段会导致转换json错误,因此解决方案就是转成自己的。
for (Task task : tasks) {// 根据需要打印其他任务信息 list.add(parseTask(task));}private static TaskVo parseTask(Task task) {log.debug("任务ID: " + task.getId());log.debug("任务名称: " + task.getName());TaskVo taskVo = new TaskVo();taskVo.setId(task.getId());taskVo.setStartTime(task.getCreateTime());taskVo.setName(task.getName());taskVo.setAssignee(task.getAssignee());taskVo.setOwner(task.getOwner());taskVo.setProcessInstanceId(task.getProcessInstanceId());taskVo.setProcessDefinitionId(task.getProcessDefinitionId());taskVo.setCreateTime(task.getCreateTime());taskVo.setDueDate(task.getDueDate());taskVo.setTaskInstName(task.getName());taskVo.setProcInstId(task.getProcessInstanceId());return taskVo;}