`
pangwu86
  • 浏览: 118542 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Nutz+ExtJS示例教程——后台Service实现

    博客分类:
  • nutz
阅读更多

 

 

后台的结构图如下:

 

 

这里是模仿了SSH的组织方式,因为毕竟大部分是学SSH过来的(ME也是其中之一),变化太大可能会有理解上的困难。

 

这里的Dao层被去掉了,因为Nutz本身提供的NutzDao就提供了基本的增删改查操作,因此这层可以去掉了,直接并入到Service层中。

 

接下来,先写model层,就是对于数据库表的JavaBean

详细步骤请参照Nutz 的文档Dao手册这部分:http://code.google.com/p/nutz/wiki/dao_hello

 

以User举例,其他模块类似

 

User类:

 

package org.nutz.demo.model;

import java.util.List;

import org.nutz.dao.entity.annotation.Column;
import org.nutz.dao.entity.annotation.Many;
import org.nutz.dao.entity.annotation.Table;

/**
 * 用户。
 * 
 * @author pangwu86@gmail.com
 * 
 */
@Table("t_user")
public class User extends Identity {

	@Column()
	private String userName;

	@Column()
	private String password;

	@Column()
	private String userType;

	@Many(target = ContactType.class, field = "userId")
	private List<ContactType> contactTypes;

	@Many(target = Contact.class, field = "userId")
	private List<Contact> contacts;

	@Many(target = Blog.class, field = "userId")
	private List<Blog> blogs;

	//  这里省略了get与set

}

 

要注意的是,不要忘了加Nutz的注释,同时如果字段与表中列名称有出入的话,要写入@Column("表列名")中,替换掉默认值。

 

下面开始写Service层共通的类,所有的Service都要继承这个基类,就可以实现增删改查的操作了。

 

这里对于增删改三项(查询操作的返回值就是查询的结果集,没有封装的必要)操作的返回值,做了一个简单的封装,其中包含了一部分业务信息,用一个枚举类型代替默认的返回值。

 

DbOperationResultEnum :

package org.nutz.demo.util.database;

/**
 * 封装了各种数据库操作结果。
 * 
 * @author pangwu86@gmail.com
 * 
 */
public enum DbOperationResultEnum {

	OPERATION_SUCCESS(true, "操作成功。"),

	OPERATION_FAILURE(false, "操作失败。"),

	INSERT_SUCCESS(true, "插入成功。"),

	INSERT_FAILURE(false, "插入失败。"),

	UPDATE_SUCCESS(true, "更新成功。"),

	UPDATE_FAILURE(false, "更新失败。"),

	DELETE_SUCCESS(true, "删除成功。"),

	DELETE_FAILURE(false, "删除失败,数据可能被引用,请先删引用关系。"),

	CLEAR_SUCCESS(true, "批量删除成功。"),

	CLEAR_FAILURE(false, "批量删除失败,数据可能被引用,请先删引用关系。");

	private boolean success;

	private String msg;

	private DbOperationResultEnum(boolean success, String msg) {
		this.success = success;
		this.msg = msg;
	}

	public boolean isSuccess() {
		return success;
	}

	public String getMsg() {
		return msg;
	}
}
 

BaseService:

package org.nutz.demo.service;

import java.util.List;

import org.nutz.dao.Chain;
import org.nutz.dao.Condition;
import org.nutz.dao.QueryResult;
import org.nutz.dao.sql.Sql;
import org.nutz.demo.util.database.DbOperationResultEnum;

/**
 * CRUD基本操作。<br>
 * 基于泛型类。
 * 
 * @author pangwu86@gmail.com
 * 
 * @param <T>
 *            实体类类型
 */
public interface BaseService<T> {

	/**
	 * 从配置SQL文件中取得SQL文。
	 * 
	 * @param key
	 * @return
	 */
	public Sql createSql(String key);

	/**
	 * 直接执行一组SQL语句。
	 * 
	 * @param sqls
	 * @return
	 */
	public boolean execute(Sql... sqls);

	/**
	 * 通用查询。(无分页)
	 * 
	 * @param cdn
	 * @return
	 */
	public List<T> query(Condition cdn);

	/**
	 * 通用查询。(带分页信息)
	 * 
	 * @param cdn
	 * @param pageNumber
	 * @param pageSize
	 * @return
	 */
	public QueryResult query(Condition cdn, int pageNumber, int pageSize);

	/**
	 * 通用获取,对象中引用的对象。(根据正则匹配)
	 * 
	 * @param obj
	 * @param regex
	 * @return
	 */
	public T fetchLinks(T obj, String regex);

	/**
	 * 通用获取。(根据条件)
	 * 
	 * @param cdn
	 * @return
	 */
	public T fetch(Condition cdn);

	/**
	 * 通用获取。(根据id)
	 * 
	 * @param id
	 * @return
	 */
	public T fetch(long id);

	/**
	 * 通用获取。(根据name)
	 * 
	 * @param name
	 * @return
	 */
	public T fetch(String name);

	/**
	 * 通用删除。(根据实体)
	 * 
	 * @param entity
	 * @return
	 */
	public DbOperationResultEnum delete(T entity);

	/**
	 * 通用插入。(根据实体)
	 * 
	 * @param entity
	 * @return
	 */
	public DbOperationResultEnum insert(T entity);

	/**
	 * 通用更新。(根据条件)
	 * 
	 * @param entity
	 * @return
	 */
	public DbOperationResultEnum update(Condition cnd, Chain chain);

	/**
	 * 通用更新。(根据实体)
	 * 
	 * @param entity
	 * @return
	 */
	public DbOperationResultEnum update(T entity);

	/**
	 * 通用批量删除。(删除全部)
	 * 
	 * @return
	 */
	public DbOperationResultEnum clear();

	/**
	 * 通用批量删除。(根据条件删除)
	 * 
	 * @param cdn
	 * @return
	 */
	public DbOperationResultEnum clear(Condition cdn);

	/**
	 * 返回该Service使用的实体类类型。
	 * 
	 * @return
	 */
	public Class<T> getEntryClz();

}

其中的方法可以根据你的需求再自行添加。

 

 

这里写到后来才发现,BaseService这个基类中的功能与Nutzorg.nutz.service 包下的几个类,EntityService,IdEntityServiceNameEntityService提供的功能相似

 

大家可以根据情况直接使用Nutz提供的,或作为参考,根据自身情况写出更符合自己使用习惯的共通类,来进行复用。

 

 

下面是BaseService的实现类:

package org.nutz.demo.service.impl;

import java.util.List;

import org.nutz.dao.Chain;
import org.nutz.dao.Condition;
import org.nutz.dao.Dao;
import org.nutz.dao.QueryResult;
import org.nutz.dao.impl.NutDao;
import org.nutz.dao.pager.Pager;
import org.nutz.dao.sql.Sql;
import org.nutz.demo.exception.BizException;
import org.nutz.demo.service.BaseService;
import org.nutz.demo.util.DaoUtil;
import org.nutz.demo.util.database.DSConfig;
import org.nutz.demo.util.database.DbOperationResultEnum;
import org.nutz.lang.Mirror;
import org.nutz.log.Log;
import org.nutz.log.Logs;

/**
 * 通用操作 实现。<br>
 * 
 * @author pangwu86@gmail.com
 * 
 */
public abstract class BaseServiceImpl<T> implements BaseService<T> {

	protected Log logger = Logs.getLog(getClass());

	private Mirror<T> mirror;

	@SuppressWarnings("unchecked")
	public BaseServiceImpl() {
		// 尝试获得泛型的类型
		try {
			Class<T> entryClass = (Class<T>) Mirror.getTypeParam(getClass(), 0);
			mirror = Mirror.me(entryClass);
			if (logger.isDebugEnabled())
				logger.debugf("获得泛型的实际类型: %s", entryClass.getName());
		} catch (Throwable e) {
			if (logger.isWarnEnabled())
				logger.warn("!!!无法获得泛型类型!", e);
			throw new RuntimeException(e);
		}
	}

	/**
	 * 方便的提供上层Dao。
	 * 
	 * @return
	 */
	public NutDao getDao() {
		return DaoUtil.getDao();
	}

	/**
	 * 方便的提供上层Dao。
	 * 
	 * @param dbConfig
	 * @return
	 */
	public NutDao getDao(DSConfig dbConfig) {
		return DaoUtil.getDao(dbConfig);
	}

	/**
	 * 获得当前泛型类型。
	 * 
	 * @return
	 */
	public Class<T> getEntryClz() {
		return mirror.getType();
	}

	/**
	 * 从配置SQL文件中取得SQL文。
	 * 
	 * @param key
	 * @return
	 */
	public Sql createSql(String key) {
		return DaoUtil.getSQLDao().sqls().create(key);
	}

	/**
	 * 直接执行一组SQL语句。
	 * 
	 * @param sqls
	 */
	public boolean execute(Sql... sqls) {
		try {
			DaoUtil.getDao().execute(sqls);
			return true;
		} catch (Throwable e) {
			if (logger.isErrorEnabled()) {
				logger.error("批量执行SQL语句报错。", e);
			}
			throw new RuntimeException(e);
		}
	}

	/**
	 * 通用查询。(无分页)
	 * 
	 * @param cdn
	 * @return
	 */
	public List<T> query(Condition cdn) {
		return DaoUtil.getDao().query(getEntryClz(), cdn, null);
	}

	/**
	 * 通用查询。(带分页信息)
	 * 
	 * @param cdn
	 * @param pageNumber
	 * @param pageSize
	 * @return
	 */
	public QueryResult query(Condition cdn, int pageNumber, int pageSize) {
		Dao dao = DaoUtil.getDao();
		Pager pager = dao.createPager(pageNumber, pageSize);
		List<T> list = dao.query(getEntryClz(), cdn, pager);
		if (null != pager) {
			pager.setRecordCount(dao.count(getEntryClz(), cdn));
		}
		return new QueryResult(list, pager);
	}

	/**
	 * 通用获取,对象中引用的对象。(根据正则匹配)
	 * 
	 * @param obj
	 * @param regex
	 * @return
	 */
	public T fetchLinks(T obj, String regex) {
		return DaoUtil.getDao().fetchLinks(obj, regex);
	}

	/**
	 * 通用获取。(根据条件)
	 * 
	 * @param cdn
	 * @return
	 */
	public T fetch(Condition cdn) {
		return DaoUtil.getDao().fetch(getEntryClz(), cdn);
	}

	/**
	 * 通用获取。(根据id)
	 * 
	 * @param id
	 * @return
	 */
	public T fetch(long id) {
		return DaoUtil.getDao().fetch(getEntryClz(), id);
	}

	/**
	 * 通用获取。(根据name)
	 * 
	 * @param name
	 * @return
	 */
	public T fetch(String name) {
		return DaoUtil.getDao().fetch(getEntryClz(), name);
	}

	/**
	 * 通用删除。(根据实体)
	 * 
	 * @param entity
	 * @return
	 */
	public DbOperationResultEnum delete(T entity) {
		try {
			return 1 == DaoUtil.getDao().delete(entity) ? DbOperationResultEnum.DELETE_SUCCESS
					: DbOperationResultEnum.DELETE_FAILURE;
		} catch (Throwable e) {
			if (logger.isErrorEnabled()) {
				logger.error("删除数据出错。", e);
			}
			throw new BizException(DbOperationResultEnum.DELETE_FAILURE, e);
		}
	}

	/**
	 * 通用插入。(根据实体)
	 * 
	 * @param entity
	 * @return
	 */
	public DbOperationResultEnum insert(T entity) {
		try {
			DaoUtil.getDao().insert(entity);
			return DbOperationResultEnum.INSERT_SUCCESS;
		} catch (Throwable e) {
			if (logger.isErrorEnabled()) {
				logger.error("插入数据出错。", e);
			}
			throw new BizException(DbOperationResultEnum.INSERT_FAILURE, e);
		}
	}

	/**
	 * 通用更新。(根据条件)
	 * 
	 * @param entity
	 * @return
	 */
	public DbOperationResultEnum update(Condition cnd, Chain chain) {
		try {
			return DaoUtil.getDao().update(getEntryClz(), chain, cnd) >= 0 ? DbOperationResultEnum.UPDATE_SUCCESS
					: DbOperationResultEnum.UPDATE_FAILURE;
		} catch (Throwable e) {
			if (logger.isErrorEnabled()) {
				logger.error("更新数据出错。", e);
			}
			throw new BizException(DbOperationResultEnum.UPDATE_FAILURE, e);
		}
	}

	/**
	 * 通用更新。(根据实体)
	 * 
	 * @param entity
	 * @return
	 */
	public DbOperationResultEnum update(T entity) {
		try {
			return 1 == DaoUtil.getDao().update(entity) ? DbOperationResultEnum.UPDATE_SUCCESS
					: DbOperationResultEnum.UPDATE_FAILURE;
		} catch (Throwable e) {
			if (logger.isErrorEnabled()) {
				logger.error("更新数据出错。", e);
			}
			throw new BizException(DbOperationResultEnum.UPDATE_FAILURE, e);
		}
	}

	/**
	 * 通用批量删除。(删除全部)
	 * 
	 * @return
	 */
	public DbOperationResultEnum clear() {
		return clear(null);
	}

	/**
	 * 通用批量删除。(根据条件删除)
	 * 
	 * @param cdn
	 * @return
	 */
	public DbOperationResultEnum clear(Condition cdn) {
		try {
			return DaoUtil.getDao().clear(getEntryClz(), cdn) >= 0 ? DbOperationResultEnum.CLEAR_SUCCESS
					: DbOperationResultEnum.CLEAR_FAILURE;
		} catch (Throwable e) {
			if (logger.isErrorEnabled()) {
				logger.error("批量删除数据出错。", e);
			}
			throw new BizException(DbOperationResultEnum.CLEAR_FAILURE, e);
		}
	}
}

其中导入的几个新类要简单介绍下:

 

DaoUtil类:

 

package org.nutz.demo.util;

import org.nutz.dao.impl.FileSqlManager;
import org.nutz.dao.impl.NutDao;
import org.nutz.demo.util.database.DSConfig;
import org.nutz.demo.util.database.DSContainer;
import org.nutz.demo.util.database.DSUtil;
import org.nutz.log.Log;
import org.nutz.log.Logs;

/**
 * DAO层切换类。
 * 
 * @author pangwu86@gmail.com
 * 
 */
public abstract class DaoUtil {

	protected static Log logger = Logs.getLog(DaoUtil.class);

	private static NutDao sqlDao = new NutDao();

	private static NutDao defaultDao = new NutDao(DSContainer.getDataSource(DSUtil
			.getDefaultDSConfig()));

	/**
	 * 加载配置SQL
	 */
	static {
		sqlDao.setSqlManager(new FileSqlManager("/config/sql"));
		if (logger.isDebugEnabled()) {
			logger.debugf("加载SQL配置文件成功,共%s条", sqlDao.sqls().count());
			for (String key : sqlDao.sqls().keys()) {
				String sql = sqlDao.sqls().get(key);
				logger.debugf("Key: %s Value: %s", key, sql);
			}
		}
	}

	public static NutDao getSQLDao() {
		return sqlDao;
	}

	/**
	 * 获得当前选中的Dao。
	 * 
	 * @return
	 */
	public static NutDao getDao() {
		return defaultDao;
	}

	/**
	 * 根据数据源配置信息,获得Dao。
	 * 
	 * @param dbConfig
	 * @return
	 */
	public static NutDao getDao(DSConfig dbConfig) {
		return new NutDao(DSContainer.getDataSource(dbConfig));
	}

}

这个类负责返回普通的NutzDao,跟一个用来获得自定义SQL语句的特殊的NutzDao

 

这里涉及到这个包下的几个类:

 

大家可能很奇怪为什么这里代码要这么多,这里其实从现有项目中搬过来的,是因为在做的项目中有这样一个需求——适应多数据源。

 

这个适应不只是在配置文件的时候要可以使用不同的数据源,在运行过程中,也要可以随时加入新的数据源,一个Service的每次执行都可以指定使用不同的数据源。

 

当然这里的系统不会有这么复杂的情况,代码的话大家可以选择性的看看,后面有时间了ME会把这部分精简掉。

 

BizException类:

package org.nutz.demo.exception;

import org.nutz.demo.util.database.constant.DbOperationResultEnum;

/**
 * 一个包含异常信息跟数据库操作结果信息的异常类。
 * 
 * @author pangwu86@gmail.com
 * 
 */
@SuppressWarnings("serial")
public class BizException extends RuntimeException {

	private DbOperationResultEnum dbOperationResultEnum = null;

	private Throwable cause = null;

	/**
	 * 业务异常。
	 * 
	 * @param dbOperationResultEnum
	 * @param cause
	 */
	public BizException(DbOperationResultEnum dbOperationResultEnum, Throwable cause) {
		super(cause);
		this.cause = cause;
		this.dbOperationResultEnum = dbOperationResultEnum;
	}

	public Throwable getCause() {
		return this.cause;
	}

	public DbOperationResultEnum getDBResult() {
		return this.dbOperationResultEnum;
	}
}

包含异常信息跟数据库操作结果信息的异常类,这里是为了保证在数据库出错的时候,仍然能正常的在页面上返回合理的结果,并将这个异常记录下来,这个类会跟后面的AOP配合使用,对其进行拦截,并将其异常写入日志,其结果返回页面。

 

好了,接下来开始实现四个模块的Service

 

这里以User为例子,展示Service接口与实现如何编写。


接口:

package org.nutz.demo.service;

import org.nutz.demo.model.User;

/**
 * 用户模块Service接口。
 * 
 * @author pangwu86@gmail.com
 * 
 */
public interface UserService extends BaseService<User> {

}
 

实现:

package org.nutz.demo.service.impl;

import org.nutz.demo.model.User;
import org.nutz.demo.service.UserService;

/**
 * 用户模块Service实现类。
 * 
 * @author pangwu86@gmail.com
 * 
 */
public class UserServiceImpl extends BaseServiceImpl<User> implements UserService {

}

是不是很简单,就这样,基本的增删改查功能就有了,那么接口与实现还存在的意义,就是在其中加入某个模块所具有的特殊的业务逻辑,而基本CRUD操作实现,你可以一行代码都不用写了,都在基类中实现好了。

 

最终代码如下:

 

下面把数据库配置文件加入,然后写几个测试类,看看刚才写的Service是否成功。

 

数据库配置文件ME这里采用了过去常用的properties文件,因为很多人还不是太熟悉用json格式(好吧,其实当时是ME忘了用json了)

 

 

放在这里,同时这里可以放一个log4j的配置文件,反正早晚都需要。

 

下面是测试类,还是以User为例,其他类似。

 

package org.nutz.demo.service;

import java.util.List;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.nutz.dao.Cnd;
import org.nutz.demo.model.User;
import org.nutz.demo.service.impl.UserServiceImpl;
import org.nutz.demo.util.database.constant.DbOperationResultEnum;

public class UserServiceTest {

	private static UserService userService;

	// 测试数据
	private final static String USERNAME1 = "testUser1";
	private final static String USERNAME2 = "testUser2";
	private final static String USERNAME3 = "testUser3";
	private final static String USERNAME4 = "testUser4";
	private final static String USERNAME4_2 = "testUser4_2";
	private final static String PASSWORD = "test123";

	private final static String ADMIN = "管理员";
	private final static String USER = "普通用户";

	@BeforeClass
	public static void beforeClass() {
		userService = new UserServiceImpl();
		// 准备测试数据
		User user1 = new User();
		user1.setUserName(USERNAME1);
		user1.setPassword(PASSWORD);
		user1.setUserType(ADMIN);

		User user2 = new User();
		user2.setUserName(USERNAME2);
		user2.setPassword(PASSWORD);
		user2.setUserType(USER);

		User user3 = new User();
		user3.setUserName(USERNAME3);
		user3.setPassword(PASSWORD);
		user3.setUserType(USER);

		// 清理当前数据
		userService.clear();
		// 插入测试数据
		userService.insert(user1);
		userService.insert(user2);
		userService.insert(user3);
	}

	@AfterClass
	public static void afterClass() {
		// 清理所有测试数据
		userService.clear();
	}

	@Before
	public void beforeMethod() {

	}

	@After
	public void afterMethod() {

	}

	@Test
	public void insert() throws Exception {
		User user = new User();
		user.setUserName(USERNAME4);
		user.setPassword(PASSWORD);
		user.setUserType(ADMIN);
		DbOperationResultEnum result = userService.insert(user);
		Assert.assertTrue(result.isSuccess());
	}

	@Test
	public void fetch() throws Exception {
		User user = userService.fetch(Cnd.where("userName", "=", USERNAME1));
		Assert.assertNotNull(user);
		Assert.assertTrue("管理员".equals(user.getUserType()));
	}

	@Test
	public void update() throws Exception {
		User user = userService.fetch(Cnd.where("userName", "=", USERNAME4));
		user.setUserName(USERNAME4_2);
		user.setUserType(USER);
		DbOperationResultEnum result = userService.update(user);
		Assert.assertTrue(result.isSuccess());
	}

	@Test
	public void query() throws Exception {
		List<User> users1 = userService.query(Cnd.where("userName", "=", USERNAME2).and("userType",
				"=", USER));
		List<User> users2 = userService.query(null);
		Assert.assertTrue(users1.size() == 1);
		Assert.assertTrue(users2.size() == 4);
	}

	@Test
	public void delete() throws Exception {
		User user = new User();
		user.setId(1000000);
		DbOperationResultEnum result = userService.delete(user);
		Assert.assertFalse(result.isSuccess());
	}

	@Test
	public void clear() throws Exception {
		DbOperationResultEnum result = userService.clear(Cnd.where("userName", "=", USERNAME4_2));
		Assert.assertTrue(result.isSuccess());
	}
}

 

确认无误后,说明后台的增删改查基本功能已经没有问题,可以开始进行下面的编码了。

 

下一集,将讲述MVC与IoC的使用。


PS:附件中为项目源码,无需解压直接导入Eclipse即可。
5
0
分享到:
评论
1 楼 hehebaiy 2012-08-17  
写的很好~~

相关推荐

    用OpenGL开发的机械臂运动仿真程序,并且实现机械手臂向四个方向的旋转.rar

    OpenGL是一种强大的图形库,用于创建2D和3D图形,广泛应用于游戏开发、科学可视化、工程设计等领域。在这个项目中,我们看到一个基于OpenGL的机械臂运动仿真程序,它能够实现机械臂在四个方向上的旋转。这样的模拟对于理解机械臂的工作原理、机器人控制算法以及进行虚拟环境中的机械臂运动测试具有重要意义。 我们需要了解OpenGL的基础知识。OpenGL是一个跨语言、跨平台的编程接口,用于渲染2D和3D矢量图形。它提供了大量的函数来处理图形的绘制,包括几何形状的定义、颜色设置、光照处理、纹理映射等。开发者通过OpenGL库调用这些函数,构建出复杂的图形场景。 在这个机械臂仿真程序中,C#被用来作为编程语言。C#通常与Windows平台上的.NET Framework配合使用,提供了一种面向对象的、类型安全的语言,支持现代编程特性如LINQ、异步编程等。结合OpenGL,C#可以构建高性能的图形应用。 机械臂的运动仿真涉及到几个关键的计算和控制概念: 1. **关节角度**:机械臂的每个部分(或关节)都有一个或多个自由度,表示为关节角度。这些角度决定了机械臂各部分的位置和方向。 2. **正向运动学**:根据关节角度计算机械臂末端执行器(如抓手)在空间中的位置和方向。这涉及将各个关节的角度转换为欧拉角或四元数,然后转化为笛卡尔坐标系的X、Y、Z位置和旋转。 3. **反向运动学**:给定末端执行器的目标位置和方向,计算出各关节所需的理想角度。这是一个逆向问题,通常需要解决非线性方程组。 4. **运动规划**:确定从当前状态到目标状态的路径,确保机械臂在运动过程中避免碰撞和其他约束。 5. **OpenGL的使用**:在OpenGL中,我们首先创建几何模型来表示机械臂的各个部分。然后,使用矩阵变换(如旋转、平移和缩放)来更新关节角度对模型的影响。这些变换组合起来,形成机械臂的动态运动。 6. **四向旋转**:机械臂可能有四个独立的旋转轴,允许它在X、Y、Z三个轴上旋转,以及额外的绕自身轴线的旋转。每个轴的旋转都由对应的关节角度控制。 7. **交互控制**:用户可能可以通过输入设备(如鼠标或键盘)调整关节角度,实时观察机械臂的运动。这需要将用户输入转换为关节角度,并应用到运动学模型中。 8. **图形渲染**:OpenGL提供了多种渲染技术,如深度测试、光照模型、纹理映射等,可以用于提高机械臂模拟的真实感。例如,可以添加材质和纹理来模拟金属表面,或者使用光照来增强立体感。 这个项目结合了OpenGL的图形渲染能力与C#的编程灵活性,构建了一个可以直观展示机械臂运动的仿真环境。通过理解并实现这些关键概念,开发者不仅能够学习到图形编程技巧,还能深入理解机器人学的基本原理。

    android11 udpate-engine 系统升级模块源码

    android11 udpate-engine 系统升级模块源码下载

    MATLAB环境下SVM二分类算法的实现与参数优化

    内容概要:本文详细介绍了如何在MATLAB环境中实现SVM二分类算法,涵盖数据预处理、参数寻优及结果可视化的全过程。首先进行数据归一化处理,确保各特征在同一量纲下参与模型训练。接着采用网格搜索法对SVM的关键参数c(惩罚系数)和g(核参数)进行自动化寻优,利用5折交叉验证评估每组参数的表现。最后通过等高线图和3D曲面图直观展示参数与准确率之间的关系,并完成最终模型的训练与预测。 适合人群:具有一定MATLAB编程基础的研究人员和技术爱好者,尤其是从事机器学习、数据分析领域的从业者。 使用场景及目标:适用于需要快速搭建SVM二分类模型并进行参数调优的项目。主要目标是在短时间内获得较高准确度的分类结果,同时掌握SVM的工作原理及其在MATLAB中的具体应用方法。 其他说明:文中提供了完整的代码示例,便于读者直接上手实践。此外还提到了一些常见的注意事项,如数据格式要求、类别不平衡处理以及特征工程的重要性等。

    ffmpeg liblame pcm转mp3教程.zip

    ffmpeg

    江科大CAN入门教程,万字长文理解

    江科大CAN入门教程,万字长文理解

    移动电源设计方案详解:基于新唐N79E814单片机的双路输出PCB设计与实现

    内容概要:本文详细介绍了基于新唐N79E814单片机的移动电源设计方案,涵盖硬件架构、PCB原理图、电路设计、代码实现等方面。移动电源主要由电池、充电电路和输出电路构成,文中重点讲解了5V1A和5V2.1A两路输出的设计思路,包括同步整流、PWM控制、充电管理等关键技术。同时,文章还探讨了PCB布局、烧录注意事项、效率优化等内容,并提供了具体的代码示例和调试建议。 适合人群:具有一定电子技术和单片机开发基础的工程师和技术爱好者。 使用场景及目标:适用于希望深入了解移动电源设计原理和实现方法的人群,旨在帮助读者掌握从原理图绘制到实际产品制作的全过程,提升电路设计和调试能力。 其他说明:文章不仅提供了理论知识,还包括大量实践经验分享,如常见的调试陷阱和解决方法,有助于读者在实践中少走弯路。

    动漫角色分割-基于深度学习实现的高精度动漫角色分割算法-附项目源码-优质项目实战.zip

    动漫角色分割_基于深度学习实现的高精度动漫角色分割算法_附项目源码_优质项目实战

    一款Java通过javacv实现的支持各种音视频播放的播放器项目源码

    javacv实现的支持多种音视频播放的播放器,比如MP4、avi、mkv、flv、MP3、ogg、wav、au等多种音视频格式,非常好用。

    浏览器插件+JS+自动登录+demo

    开发调试demo,简单的自动登录功能,插件开发入门参考

    【计算机管理与注册表编辑】Windows系统管理员工具与用户账户管理:本地用户和组、远程桌面配置及SAM权限设置,具体教学与批处理可私信我

    内容概要:本文详细介绍了通过修改Windows注册表来启用和配置被禁用的用户账户(如WDAGUtilityAccount)的过程。首先,通过计算机管理界面查看被禁用的用户账户,并进入注册表编辑器定位到HKEY_LOCAL_MACHINE\SAM\SAM\Domains\Account\Users路径下的相应用户条目。接着,通过对特定用户的二进制数据进行编辑,包括复制和修改关键字段,实现对被禁用账户的克隆与重新启用。最后,验证账户状态的变化,并通过远程桌面连接测试新配置的有效性。 适合人群:具备一定Windows系统管理基础的技术人员,尤其是负责企业内部网络和用户账户管理的IT管理员。 使用场景及目标:①当需要恢复或重新配置被禁用的用户账户时;②在进行系统故障排除或安全审计时,了解如何通过注册表直接操作用户账户;③确保特定用户能够正常登录并访问远程桌面服务。 阅读建议:本文涉及较为底层的系统操作,建议读者在实际操作前充分备份系统和注册表,避免误操作导致系统不稳定。同时,对于不熟悉注册表编辑的用户,应先在测试环境中练习,确保掌握相关技能后再应用于生产环境。此外,建议结合官方文档或其他权威资料,加深对Windows用户账户管理机制的理解。

    新冠抗原自测平台 2025免费JAVA微信小程序毕设

    2025免费微信小程序毕业设计成品,包括源码+数据库+往届论文资料,附带启动教程和安装包。 启动教程:https://www.bilibili.com/video/BV1BfB2YYEnS 讲解视频:https://www.bilibili.com/video/BV1BVKMeZEYr 技术栈:Uniapp+Vue.js+SpringBoot+MySQL。 开发工具:Idea+VSCode+微信开发者工具。

    基于S7-1200 PLC的两部六层电梯控制系统设计与梯形图编程详解

    内容概要:本文详细介绍了基于西门子S7-1200 PLC的两部六层电梯控制系统的设计与实现。主要内容涵盖前期准备工作,如选择合适的PLC型号和配置硬件;核心逻辑部分深入讲解了梯形图编程的具体实现方法,包括楼层呼叫逻辑、电梯运行方向控制以及两部电梯之间的协同工作;此外,文章还探讨了仿真测试的方法及其重要性,提供了许多实用技巧和注意事项。通过具体实例展示了如何利用博途V15软件进行电梯系统的开发,并分享了一些实际操作中的经验和常见问题解决方案。 适合人群:从事工业自动化领域的工程师和技术人员,特别是那些对PLC编程有兴趣或者正在参与类似项目的从业者。 使用场景及目标:适用于需要理解和掌握S7-1200 PLC编程技能的人群,尤其是希望通过实际案例加深对梯形图编程理解的学习者。目标是在实践中提高编程能力,能够独立完成类似的工程项目。 其他说明:文中不仅包含了详细的理论解释,还有丰富的代码片段供读者参考。对于初学者而言,建议先从单部电梯开始练习,逐步过渡到复杂的双梯联调。同时,作者强调了仿真测试的重要性,指出这是验证程序正确性和优化性能的关键步骤。

    农产品自主供销系统 2025免费JAVA微信小程序毕设

    2025免费微信小程序毕业设计成品,包括源码+数据库+往届论文资料,附带启动教程和安装包。 启动教程:https://www.bilibili.com/video/BV1BfB2YYEnS 讲解视频:https://www.bilibili.com/video/BV1BVKMeZEYr 技术栈:Uniapp+Vue.js+SpringBoot+MySQL。 开发工具:Idea+VSCode+微信开发者工具。

    大学英语四级听力练习音频MP3

    内容概要:该资源为大学英语四级听力练习音频 MP3,包含丰富多样的听力素材。涵盖四级考试常见的各类场景,如校园生活(课程学习、社团活动等)、日常社交(聚会、聊天等)、工作求职(面试、职场事务等)、旅行交通(出行方式、景点介绍等)、饮食健康(餐厅点餐、健康养生等)。音频内容依照四级听力考试题型和难度精心录制,有短对话、长对话、短文听力等形式,且语速、口音等符合四级考试要求,助力考生熟悉考试形式与节奏。 适合人群:正在备考大学英语四级考试,希望提升听力水平的学生;英语基础中等,需要通过针对性练习来适应四级听力难度、提升听力理解能力的学习者;对英语听力学习有需求,想通过大量练习积累场景词汇、熟悉英语表达习惯的人群。 能学到什么:①熟悉四级听力考试的各类场景词汇,增强词汇储备并提升在听力语境中的反应速度;②掌握不同场景下的英语常用表达和句式,提升英语语言运用能力;③锻炼听力理解技巧,如抓取关键词、推断隐含意思、梳理篇章逻辑等;④适应四级听力考试的语速、口音和题型设置,增强应试能力和自信心。 阅读建议:制定系统的练习计划,定期定量进行听力练习,如每天安排 30 - 60 分钟;第一遍泛听,了解大致内容和主题;第二遍精听,逐句听写或分析不懂的词汇和句子;对照听力原文,明确错误和没听懂的地方,积累生词和表达;定期进行模拟测试,利用该音频模拟考试环境,检验学习效果并调整学习策略。

    2000-2017年各省天然气消费量数据

    2000-2017年各省天然气消费量数据 1、时间:2000-2017年 2、来源:国家统计j、能源nj 3、指标:行政区划代码、城市、年份、天然气消费量 4、范围:31省

    西门子PLC1200与库卡机器人协同控制系统的多设备集成方案

    内容概要:本文详细介绍了基于西门子PLC1200的自动化控制系统,涵盖了PLC与库卡机器人通过Profinet通讯、PTO模式控制松下伺服、36路模拟量处理(包括压力检测、位置检测及压力输出)、以及26个温控器通过485总线通讯的关键技术和实现方法。此外,还包括了昆仑通态触摸屏的人机交互界面设计,提供了详细的硬件组态、软件编程指导和设备操作说明。 适合人群:从事工业自动化领域的工程师和技术人员,尤其是那些负责多设备协同控制项目的设计和实施的专业人士。 使用场景及目标:适用于需要整合多种设备(如PLC、机器人、伺服系统、温控器等)的复杂自动化生产线。主要目标是提高生产效率、增强系统的稳定性和可靠性,同时降低维护成本。 其他说明:文中不仅提供了具体的编程实例和硬件配置指南,还分享了许多实际调试过程中积累的经验教训,有助于读者在实际应用中少走弯路。

    汽车电子基于AUTOSAR的BSW层功能详解:服务、驱动、接口与管理器模块设计及应用了文档的主要内容

    内容概要:本文深入探讨了AUTOSAR BSW(Basic Software)层所提供的各类服务、驱动、接口和管理器模块及其功能。BSW提供的服务包括I/O、Memory、Crypto、Communication、Off-board Communication和System等,涵盖了标准化的访问方式以确保不同硬件和系统的兼容性与安全性。BSW里的驱动分为内部驱动和外部驱动,分别用于控制和访问微控制器内部和外部的设备,确保硬件功能的正常运作。BSW里的接口(xx_IF)对下层模块进行抽象和封装,提供标准API接口,使上层应用无需关注底层硬件细节。BSW里的管理器(xxxM)则为多个客户端提供特定服务,能够修改或适配调整一些数据,以满足复杂需求。此外,文中还简要介绍了AUTOSAR里的库文件,它们是无状态的函数集合,可被多个模块调用以实现特定功能。 适合人群:对汽车电子软件架构有一定了解,尤其是对AUTOSAR标准感兴趣的工程师和技术人员。 使用场景及目标:①理解BSW层提供的各类服务及其应用场景;②掌握BSW中驱动、接口和管理器模块的设计原理和功能;③了解库文件的作用及其在AUTOSAR架构中的位置。 其他说明:本文详细解释了BSW层各组件的功能和作用,帮助读者更好地理解AUTOSAR架构的设计思想和实现方法。建议读者结合实际项目经验,深入研究各模块的具体实现和应用场景。

    西门子1200伺服步进FB块程序:支持多轴调用的自动化控制解决方案

    内容概要:本文介绍了西门子1200系列PLC的伺服步进FB块程序,该程序由两个FB块组成,分别采用SCL语言和梯形图编写,支持PTO和PN模式,适用于多种伺服系统和步进电机。程序经过实际调试,稳定性高,兼容性强,能够灵活应用于单轴或多轴控制系统。文中提供了详细的代码示例和调试指南,帮助用户快速上手并解决常见问题。 适合人群:从事工业自动化控制领域的工程师和技术人员,尤其是使用西门子1200系列PLC进行项目开发的人员。 使用场景及目标:①用于单轴或多轴伺服步进系统的控制;②提高项目的开发效率和稳定性;③减少重复开发的工作量,加快项目进度。 其他说明:程序需要在TIA V14及以上版本打开,附带详细的文档说明和实际项目视频链接,方便用户理解和使用。

    基于SpringBoot+Vue的电子招投标系统源码+数据库.zip

    基于SpringBoot+Vue的电子招投标系统源码+数据库.zip 高分通过项目,已获导师指导。 本项目是一套基于Springboot的电子招投标系统,主要针对计算机相关专业的正在做毕设的学生和需要项目实战练习的Java学习者。也可作为课程设计、期末大作业 包含:项目源码、数据库脚本、开发说明文档、演示视频等,该项目可以直接作为毕设使用。 项目都经过严格调试,确保可以运行! 基于SpringBoot+Vue的电子招投标系统源码+数据库.zip 高分通过项目,已获导师指导。 本项目是一套基于Springboot的电子招投标系统,主要针对计算机相关专业的正在做毕设的学生和需要项目实战练习的Java学习者。也可作为课程设计、期末大作业 包含:项目源码、数据库脚本、开发说明文档、演示视频等,该项目可以直接作为毕设使用。 项目都经过严格调试,确保可以运行! 基于SpringBoot+Vue的电子招投标系统源码+数据库.zip 高分通过项目,已获导师指导。 本项目是一套基于Springboot的电子招投标系统,主要针对计算机相关专业的正在做毕设的学生和需要项目实战练习的Java学习者。也可

Global site tag (gtag.js) - Google Analytics