项目导入
如果因为环境或者项目导入的困难,而不能成功跑起来,那是真的飞jr烦
尽管现在idea都很好的解决了相关的问题,但并不觉得这玩意就完全碾压eclipse
项目导入的问题,一定要一次性解决好,做好记录,不要因为这玩意占据太多时间
让该bos项目跑起来:
事先配好maven(这东西因为很多时候不能联网,最好把仓库拷到本地),jdk7,tomcat7,mysql,仓库(直接用这个E: epository_bos epository)
(eclipse)每次删除tomcat及Server项目,重新建,部署启动
https://github.com/ChenCurry/bos.git(GitHub提示有安全问题,对外不可见)
持久层代码抽取
/** * 持久层通用接口 * @param <T> */ public interface IBaseDao<T> { public void save(T entity); public void delete(T entity); public void update(T entity); public T findById(Serializable id); public List<T> findAll(); }
/** * 持久层通用实现 * @param <T> */ public class BaseDaoImpl<T> extends HibernateDaoSupport implements IBaseDao<T> { //代表的是某个实体的类型 private Class<T> entityClass; @Resource//根据类型注入spring工厂中的会话工厂对象sessionFactory public void setMySessionFactory(SessionFactory sessionFactory){ super.setSessionFactory(sessionFactory); } //在父类(BaseDaoImpl)的构造方法中动态获得entityClass public BaseDaoImpl() { ParameterizedType superclass = (ParameterizedType) this.getClass().getGenericSuperclass(); //获得父类上声明的泛型数组 Type[] actualTypeArguments = superclass.getActualTypeArguments(); entityClass = (Class<T>) actualTypeArguments[0]; } public void save(T entity) { this.getHibernateTemplate().save(entity); } public void delete(T entity) { this.getHibernateTemplate().delete(entity); } public void update(T entity) { this.getHibernateTemplate().update(entity); } public T findById(Serializable id) { return this.getHibernateTemplate().get(entityClass, id); } public List<T> findAll() { String hql = "FROM " + entityClass.getSimpleName(); return (List<T>) this.getHibernateTemplate().find(hql); } }
表现层代码抽取
/** * 表现层通用实现 * @param <T> */ public class BaseAction<T> extends ActionSupport implements ModelDriven<T> { //模型对象 private T model; public T getModel() { return model; } //在构造方法中动态获取实体类型,通过反射创建model对象 public BaseAction() { ParameterizedType genericSuperclass = (ParameterizedType) this.getClass().getGenericSuperclass(); //获得BaseAction上声明的泛型数组 Type[] actualTypeArguments = genericSuperclass.getActualTypeArguments(); Class<T> entityClass = (Class<T>) actualTypeArguments[0]; //通过反射创建对象 try { model = entityClass.newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } }
拦截器实现
BOSLoginInterceptor.java
/** * BOS项目的工具类 */ public class BOSUtils { //获取session对象 public static HttpSession getSession(){ return ServletActionContext.getRequest().getSession(); } //获取登录用户对象 public static User getLoginUser(){ return (User) getSession().getAttribute("loginUser"); } }
/** * 自定义的拦截器,实现用户未登录自动跳转到登录页面*/ public class BOSLoginInterceptor extends MethodFilterInterceptor{ //拦截方法 protected String doIntercept(ActionInvocation invocation) throws Exception { //从session中获取用户对象 User user = BOSUtils.getLoginUser(); if(user == null){ //没有登录,跳转到登录页面 return "login"; } //放行 return invocation.invoke(); } }
struts.xml
<interceptors> <!-- 注册自定义拦截器 --> <interceptor name="bosLoginInterceptor" class="com.itheima.bos.web.interceptor.BOSLoginInterceptor"> <!-- 指定哪些方法不需要拦截 --> <param name="excludeMethods">login</param> </interceptor> <!-- 定义拦截器栈 --> <interceptor-stack name="myStack"> <interceptor-ref name="bosLoginInterceptor"></interceptor-ref> <interceptor-ref name="defaultStack"></interceptor-ref> </interceptor-stack> </interceptors> <default-interceptor-ref name="myStack"/> <!-- 全局结果集定义 --> <global-results> <result name="login">/login.jsp</result> </global-results>
分页代码抽取
public class BaseDaoImpl<T> extends HibernateDaoSupport implements IBaseDao<T> {}
传递引用?
/** * 通用分页查询方法 */ public void pageQuery(PageBean pageBean) { int currentPage = pageBean.getCurrentPage(); int pageSize = pageBean.getPageSize(); DetachedCriteria detachedCriteria = pageBean.getDetachedCriteria(); //查询total---总数据量 detachedCriteria.setProjection(Projections.rowCount());//指定hibernate框架发出sql的形式----》select count(*) from bc_staff; List<Long> countList = (List<Long>) this.getHibernateTemplate().findByCriteria(detachedCriteria); Long count = countList.get(0); pageBean.setTotal(count.intValue()); //查询rows---当前页需要展示的数据集合 detachedCriteria.setProjection(null);//指定hibernate框架发出sql的形式----》select * from bc_staff; int firstResult = (currentPage - 1) * pageSize; int maxResults = pageSize; List rows = this.getHibernateTemplate().findByCriteria(detachedCriteria, firstResult, maxResults); pageBean.setRows(rows); }
//属性驱动,接收页面提交的分页参数 private int page; private int rows; /** * 分页查询方法 * @throws IOException */ public String pageQuery() throws IOException{ PageBean pageBean = new PageBean(); pageBean.setCurrentPage(page); pageBean.setPageSize(rows); //创建离线提交查询对象 DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Staff.class); pageBean.setDetachedCriteria(detachedCriteria); staffService.pageQuery(pageBean); //使用json-lib将PageBean对象转为json,通过输出流写回页面中 //JSONObject---将单一对象转为json //JSONArray----将数组或者集合对象转为json JsonConfig jsonConfig = new JsonConfig(); //指定哪些属性不需要转json jsonConfig.setExcludes(new String[]{"currentPage","detachedCriteria","pageSize"}); String json = JSONObject.fromObject(pageBean,jsonConfig).toString(); ServletActionContext.getResponse().setContentType("text/json;charset=utf-8"); ServletActionContext.getResponse().getWriter().print(json); return NONE; }
另:该页面(取派员)增删改
WebService服务(apche CXF)
基于CXF开发crm服务(WebService服务端)
数据库crm_heima32
/* Navicat MySQL Data Transfer Source Server : root Source Server Version : 50022 Source Host : localhost:3306 Source Database : crm Target Server Type : MYSQL Target Server Version : 50022 File Encoding : 65001 Date: 2015-04-19 17:46:45 */ SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- -- Table structure for `t_customer` -- ---------------------------- DROP TABLE IF EXISTS `t_customer`; CREATE TABLE `t_customer` ( `id` int(11) NOT NULL auto_increment, `name` varchar(255) default NULL, `station` varchar(255) default NULL, `telephone` varchar(255) default NULL, `address` varchar(255) default NULL, `decidedzone_id` varchar(255) default NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of t_customer -- ---------------------------- INSERT INTO `t_customer` VALUES ('1', '张三', '百度', '13811111111', '北京市西城区长安街100号', null); INSERT INTO `t_customer` VALUES ('2', '李四', '哇哈哈', '13822222222', '上海市虹桥区南京路250号', null); INSERT INTO `t_customer` VALUES ('3', '王五', '搜狗', '13533333333', '天津市河北区中山路30号', null); INSERT INTO `t_customer` VALUES ('4', '赵六', '联想', '18633333333', '石家庄市桥西区和平路10号', null); INSERT INTO `t_customer` VALUES ('5', '小白', '测试空间', '18511111111', '内蒙古自治区呼和浩特市和平路100号', null); INSERT INTO `t_customer` VALUES ('6', '小黑', '联想', '13722222222', '天津市南开区红旗路20号', null); INSERT INTO `t_customer` VALUES ('7', '小花', '百度', '13733333333', '北京市东城区王府井大街20号', null); INSERT INTO `t_customer` VALUES ('8', '小李', '长城', '13788888888', '北京市昌平区建材城西路100号', null);
导入项目https://github.com/ChenCurry/crm_heima32.git
启动,服务便已经存在;访问http://localhost:8080/crm_heima32/service查看服务
cmd:wsimport -s . http://192.168.1.8:8080/crm_heima32/service/customer?wsdl(生成客户端调用服务需要的代码)
将生成的代码拷到项目中,即可在业务代码中进行调用,如
public class App { public static void main(String[] args) { CustomerServiceImplService ss = new CustomerServiceImplService(); ICustomerService proxy = ss.getCustomerServiceImplPort(); List<Customer> list = proxy.findAll(); for (Customer customer : list) { System.out.println(customer); } } }
权限控制(apche shiro)
先引入一个小例子clone https://github.com/ChenCurry/privilegedemo.git,了解如何进行权限控制
常见的权限控制方式
URL拦截权限控制
方法注解权限控制
创建权限数据模型(准备整合shiro)
- 权限表
- 角色表
- 用户表
- 角色权限关系表
- 用户角色关系表
角色就是权限的集合,引入角色表,是为了方便授权
PowerDesigner导出sql
整合到项目中
<!-- 引入shiro框架的依赖 --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-all</artifactId> <version>1.2.2</version> </dependency>
过滤器要放到web.xml中struts过滤器的前面
<!-- 配置spring框架提供的用于整合shiro框架的过滤器 --> <filter> <filter-name>shiroFilter</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter> <filter-mapping> <filter-name>shiroFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
applicationContext.xml
<!-- 配置shiro框架的过滤器工厂对象 --> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <!-- 注入安全管理器对象 --> <property name="securityManager" ref="securityManager"/> <!-- 注入相关页面访问URL --> <property name="loginUrl" value="/login.jsp"/> <property name="successUrl" value="/index.jsp"/> <property name="unauthorizedUrl" value="/unauthorized.jsp"/> <!--注入URL拦截规则 --> <property name="filterChainDefinitions"> <value> /css/** = anon /js/** = anon /images/** = anon /validatecode.jsp* = anon /login.jsp = anon /userAction_login.action = anon /page_base_staff.action = perms["staff-list"] /* = authc </value> </property> </bean> <!-- 注册安全管理器对象 --> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="bosRealm"/> </bean> <!-- 注册realm --> <bean id="bosRealm" class="com.itheima.bos.realm.BOSRealm"></bean>
认证要交给shiro框架来做,不然永远会被拦截出来
/** * 用户登录,使用shiro框架提供的方式进行认证操作 */ public String login(){ //从Session中获取生成的验证码 String validatecode = (String) ServletActionContext.getRequest().getSession().getAttribute("key"); //校验验证码是否输入正确 if(StringUtils.isNotBlank(checkcode) && checkcode.equals(validatecode)){ //使用shiro框架提供的方式进行认证操作 Subject subject = SecurityUtils.getSubject();//获得当前用户对象,状态为“未认证” AuthenticationToken token = new UsernamePasswordToken(model.getUsername(),MD5Utils.md5(model.getPassword()));//创建用户名密码令牌对象 try{ subject.login(token); }catch(Exception e){ e.printStackTrace(); return LOGIN; } User user = (User) subject.getPrincipal(); ServletActionContext.getRequest().getSession().setAttribute("loginUser", user); return HOME; }else{ //输入的验证码错误,设置提示信息,跳转到登录页面 this.addActionError("输入的验证码错误!"); return LOGIN; } }
安全管理器(框架自己)调下面的对象
public class BOSRealm extends AuthorizingRealm{ @Autowired private IUserDao userDao; //认证方法 protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { System.out.println("自定义的realm中认证方法执行了。。。。"); UsernamePasswordToken passwordToken = (UsernamePasswordToken)token; //获得页面输入的用户名 String username = passwordToken.getUsername(); //根据用户名查询数据库中的密码 User user = userDao.findUserByUsername(username); if(user == null){ //页面输入的用户名不存在 return null; } //简单认证信息对象 AuthenticationInfo info = new SimpleAuthenticationInfo(user, user.getPassword(), this.getName()); //框架负责比对数据库中的密码和页面输入的密码是否一致 return info; } //授权方法 protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { return null; } }
在realm中进行授权
①url拦截(上面的方式)
②使用shiro的方法注解方式权限控制
<!-- 开启shiro框架注解支持 --> <bean id="defaultAdvisorAutoProxyCreator" class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"> <!-- 必须使用cglib方式为Action对象创建代理对象 --> <property name="proxyTargetClass" value="true"/> </bean> <!-- 配置shiro框架提供的切面类,用于创建代理对象 --> <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"/>
action中用注解控制(主要工作量在这里边)
@Controller @Scope("prototype") public class StaffAction extends BaseAction<Staff>{ @Autowired private IStaffService staffService; /** * 添加取派员 */ public String add(){ staffService.save(model); return LIST; } /** * 分页查询方法 * @throws IOException */ public String pageQuery() throws IOException{ staffService.pageQuery(pageBean); this.java2Json(pageBean, new String[]{"decidedzones","currentPage","detachedCriteria","pageSize"}); return NONE; } //属性驱动,接收页面提交的ids参数 private String ids; /** * 取派员批量删除 */ @RequiresPermissions("staff-delete")//执行这个方法,需要当前用户具有staff-delete这个权限 public String deleteBatch(){ staffService.deleteBatch(ids); return LIST; } /** * 修改取派员信息 */ @RequiresPermissions("staff-edit") public String edit(){ //Subject subject = SecurityUtils.getSubject(); //subject.checkPermission("staff-edit"); //显查询数据库,根据id查询原始数据 Staff staff = staffService.findById(model.getId()); //使用页面提交的数据进行覆盖 staff.setName(model.getName()); staff.setTelephone(model.getTelephone()); staff.setHaspda(model.getHaspda()); staff.setStandard(model.getStandard()); staff.setStation(model.getStation()); staffService.update(staff); return LIST; } /*public static void main(String[] args) { PageBean pageBean = new PageBean(); pageBean.setCurrentPage(2); pageBean.setPageSize(30); String json = JSONObject.fromObject(pageBean ).toString(); System.out.println(json); }*/ /** * 查询所有未删除的取派员,返回json */ public String listajax(){ List<Staff> list = staffService.findListNotDelete(); this.java2Json(list, new String[]{"decidedzones"}); return NONE; } public String getIds() { return ids; } public void setIds(String ids) { this.ids = ids; } }
struts.xml全局异常捕获
<!-- 全局结果集定义 --> <global-results> <result name="login">/login.jsp</result> <result name="unauthorized">/unauthorized.jsp</result> </global-results> <global-exception-mappings> <exception-mapping result="unauthorized" exception="org.apache.shiro.authz.UnauthorizedException"></exception-mapping> </global-exception-mappings> <!-- 需要进行权限控制的页面访问 --> <action name="page_*_*"> <result type="dispatcher">/WEB-INF/pages/{1}/{2}.jsp</result> </action> <!-- 用户管理 --> <action name="userAction_*" class="userAction" method="{1}"> <result name="home">/index.jsp</result> </action> <!-- 取派员管理 --> <action name="staffAction_*" class="staffAction" method="{1}"> <result name="list">/WEB-INF/pages/base/staff.jsp</result> </action> <!-- 区域管理 --> <action name="regionAction_*" class="regionAction" method="{1}"> </action> <!-- 分区管理 --> <action name="subareaAction_*" class="subareaAction" method="{1}"> <result name="list">/WEB-INF/pages/base/subarea.jsp</result> </action> <!-- 定区管理 --> <action name="decidedzoneAction_*" class="decidedzoneAction" method="{1}"> <result name="list">/WEB-INF/pages/base/decidedzone.jsp</result> </action> <!-- 业务通知单管理 --> <action name="noticebillAction_*" class="noticebillAction" method="{1}"> <result name="noticebill_add">/WEB-INF/pages/qupai/noticebill_add.jsp</result> </action> <!-- 工作单 管理 --> <action name="workordermanageAction_*" class="workordermanageAction" method="{1}"> </action> <!-- 权限管理 --> <action name="functionAction_*" class="functionAction" method="{1}"> <result name="list">/WEB-INF/pages/admin/function.jsp</result> </action>
③使用页面标签方式权限控制
引入shiro标签库
<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
使用shiro元素控制页面展示
④代码级别权限控制(基于代理技术实现)
初始化权限数据
权限控制整理完成,项目上线需要导入初始化权限数据
INSERT INTO `auth_function` VALUES ('11', '基础档案', 'jichudangan', null, null, '1', '0', null); INSERT INTO `auth_function` VALUES ('112', '收派标准', 'standard', null, 'page_base_standard.action', '1', '1', '11'); INSERT INTO `auth_function` VALUES ('113', '取派员设置', 'staff', null, 'page_base_staff.action', '1', '2', '11'); INSERT INTO `auth_function` VALUES ('114', '区域设置', 'region', null, 'page_base_region.action', '1', '3', '11'); INSERT INTO `auth_function` VALUES ('115', '管理分区', 'subarea', null, 'page_base_subarea.action', '1', '4', '11'); INSERT INTO `auth_function` VALUES ('116', '管理定区/调度排班', 'decidedzone', null, 'page_base_decidedzone.action', '1', '5', '11'); INSERT INTO `auth_function` VALUES ('12', '受理', 'shouli', null, null, '1', '1', null); INSERT INTO `auth_function` VALUES ('121', '业务受理', 'noticebill', null, 'page_qupai_noticebill_add.action', '1', '0', '12'); INSERT INTO `auth_function` VALUES ('122', '工作单快速录入', 'quickworkordermanage', null, 'page_qupai_quickworkorder.action', '1', '1', '12'); INSERT INTO `auth_function` VALUES ('124', '工作单导入', 'workordermanageimport', null, 'page_qupai_workorderimport.action', '1', '3', '12'); INSERT INTO `auth_function` VALUES ('13', '调度', 'diaodu', null, null, '1', '2', null); INSERT INTO `auth_function` VALUES ('131', '查台转单', 'changestaff', null, null, '1', '0', '13'); INSERT INTO `auth_function` VALUES ('132', '人工调度', 'personalassign', null, 'page_qupai_diaodu.action', '1', '1', '13'); INSERT INTO `auth_function` VALUES ('14', '物流配送流程管理', 'zhongzhuan', null, null, '1', '3', null); INSERT INTO `auth_function` VALUES ('141', '启动配送流程', 'start', null, 'workOrderManageAction_list.action', '1', '0', '14'); INSERT INTO `auth_function` VALUES ('142', '查看个人任务', 'personaltask', null, 'taskAction_findPersonalTask.action', '1', '1', '14'); INSERT INTO `auth_function` VALUES ('143', '查看我的组任务', 'grouptask', null, 'taskAction_findGroupTask.action', '1', '2', '14'); INSERT INTO `auth_function` VALUES ('8a7e843355a4392d0155a43aa7150000', '删除取派员', 'staff.delete', 'xxx', 'staffAction_delete.action', '0', '1', '113'); INSERT INTO `auth_function` VALUES ('8a7e843355a442460155a442bcfc0000', '传智播客', 'itcast', '', 'http://www.itcast.cn', '1', '1', null);
上线之后,再开发新的功能,分配新的权限,可在页面进行配置。
用ehcache缓存权限数据
也是属于shiro的一部分,用于缓存Java对象,注入到项目中即可用
<!-- 引入ehcache的依赖 --> <dependency> <groupId>net.sf.ehcache</groupId> <artifactId>ehcache-core</artifactId> <version>2.6.6</version> </dependency>
需要引入配置文件(用于设置缓存的规则)
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd"> <diskStore path="java.io.tmpdir"/> <defaultCache maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true" maxElementsOnDisk="10000000" diskPersistent="false" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU" /> </ehcache>
applicationContext.xml中注入
<!-- 注册安全管理器对象 --> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="bosRealm"/> <!-- 注入缓存管理器 --> <property name="cacheManager" ref="cacheManager"/> </bean> <!-- 注册缓存管理器 --> <bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager"> <!-- 注入ehcache的配置文件 --> <property name="cacheManagerConfigFile" value="classpath:ehcache.xml"/> </bean>
完了之后,就不会每次都进行BOSRealm类的授权方法了
任务调度Quartz
即定时任务,发邮件
http://www.quartz-scheduler.org/
<!-- 引入quartz对应的依赖 --> <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.2.3</version> </dependency> <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz-jobs</artifactId> <version>2.2.3</version> </dependency> <!-- 引入JavaMail的依赖 --> <dependency> <groupId>javax.mail</groupId> <artifactId>mail</artifactId> <version>1.4</version> </dependency>
创建任务类
/** * 发送邮件的作业 */ public class MailJob { @Resource private IWorkbillDao workbillDao; private String username;//发件人的邮箱账号 private String password;//密码 private String smtpServer;//服务器 public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public void execute() { System.out.println("要发邮件了。。。" + new Date()); try { //查询工单类型为新单的所有工单 List<Workbill> list = workbillDao.findAll(); if(null != list && list.size() > 0){ final Properties mailProps = new Properties(); mailProps.put("mail.smtp.host", this.getSmtpServer()); mailProps.put("mail.smtp.auth", "true"); mailProps.put("mail.username", this.getUsername()); mailProps.put("mail.password", this.getPassword()); // 构建授权信息,用于进行SMTP进行身份验证 Authenticator authenticator = new Authenticator() { protected PasswordAuthentication getPasswordAuthentication() { // 用户名、密码 String userName = mailProps.getProperty("mail.username"); String password = mailProps.getProperty("mail.password"); return new PasswordAuthentication(userName, password); } }; // 使用环境属性和授权信息,创建邮件会话 Session mailSession = Session.getInstance(mailProps, authenticator); for(Workbill workbill : list){ // 创建邮件消息 MimeMessage message = new MimeMessage(mailSession); // 设置发件人 InternetAddress from = new InternetAddress(mailProps.getProperty("mail.username")); message.setFrom(from); // 设置收件人 InternetAddress to = new InternetAddress("test@itcast.cn"); message.setRecipient(RecipientType.TO, to); // 设置邮件标题 message.setSubject("系统邮件:新单通知"); // 设置邮件的内容体 message.setContent(workbill.toString(), "text/html;charset=UTF-8"); // 发送邮件 Transport.send(message); } } } catch (Exception ex) { ex.printStackTrace(); } } public String getSmtpServer() { return smtpServer; } public void setSmtpServer(String smtpServer) { this.smtpServer = smtpServer; } }
注入到spring
<!-- 注册自定义作业类 --> <bean id="myJob" class="com.itheima.jobs.MailJob"> <property name="username" value="xxxx@126.com"/> <property name="password" value="xxxx"/> <property name="smtpServer" value="smtp.126.com"/> </bean> <!-- 配置JobDetail --> <bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <!-- 注入目标对象 --> <property name="targetObject" ref="myJob"/> <!-- 注入目标方法 --> <property name="targetMethod" value="execute"/> </bean> <!-- 配置触发器 --> <bean id="myTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean"> <!-- 注入任务详情对象 --> <property name="jobDetail" ref="jobDetail"/> <!-- 注入cron表达式,通过这个表达式指定触发的时间点 --> <property name="cronExpression"> <value>0/5 * * * * ?</value> </property> </bean> <!-- 配置调度工厂 --> <bean id="schedulerFactoryBean" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <!-- 注入触发器 --> <property name="triggers"> <list> <ref bean="myTrigger"/> </list> </property> </bean>
自动表达式生成https://qqe2.com/cron