- 浏览: 56125 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
hy2012_campus:
想想你请教下你们是在什么情况下不适用spring合适选择gui ...
几个关于Guice的问题,关心Guice的请进 -
楚天阔:
楼主好样的
connect to the matrix -
楚天阔:
楼主确实是swing强人。。。膜拜你。我们公司正在转型swin ...
回国工作 -
wyi23:
最近想用SWING做个东西,去网上找了找,发现国内对SWING ...
实例源代码 - 适用于各类Swing应用的通用数据验证模块 -
guojch:
请问密码是多少啊?
实例源代码 - 适用于各类Swing应用的通用数据验证模块
请注意:本文的版权归作者所有,如转载请注明出处。
这段时间真是忙得要死,一方面要开发公司项目的系统框架,要将项目分成不同的子项目,编写核心代码;另一方面要将极限编程(XP)引入团队开发,部署各类XP需要的服务例如subversion啦,ant+ivy啦,Hudson啦等等。顺便说句题外话,ubuntu还真是不是一般的好用,建议有能力的全部转到ubuntu上去开发。
我目前开发的这个框架的客户端是具肥的客户端,也就是Swing客户端了。Swing应用相对于Web应用有很多优势,因为它更肥。数据验证就是其中一个。当然现在的Web应用通过使用Ajax也要比以前强很多了,但是还是避免不了在验证数据时向服务段发出请求,至少你无法避免验证结果从Web服务器传输到用户浏览器上这段过程。而Swing这类肥客户端可以实现完全在本地对数据进行验证,甚至可以断网继续工作(这也是Web应用目前在研发的一个重要课题)。
前段时间开发出了一个可以应用于所有Swing应用的通用数据验证模块,发现它在项目中使用后,对于普通的数据验证,程序员几乎不需要编码,效率提高了不少,就写了一篇博文拿出来和大家分享。原文是用英文写的,在这里:http://polygoncell.blogspot.com/2008/07/validation-module-for-swing-application.html
。英文好的朋友可以直接去那里看。
编写这个模块使用了很多不同的开源框架和类库,其中很重要的一个就是JXLayer。文章写完后,我就跑去邀请JXLayer的作者Alexp来指点一下,然后就在我的文章后面开始了一段讨论,挺有意思的,他不愧为是Swing team里面的牛人啊!厉害啊!呵呵。
ok,回到今天这篇文章的正题。今天的主要目的是将我的英文博文翻译成中文(自己的文章,我就不逐字逐句翻译了,意思到了就行了,可能还会随兴展开一番讨论)在这里展示给大家,与大家分享开发经验,希望大家能够从中获益,也希望能够以文会友,广交朋友。废话少说,切入正题。
数据验证(Validation)一直是软件开发中非常重要的一环,有了它,你的系统会让客户感到更加友善,同时你的系统也得到了一定程度的保护。一般来说,数据验证既可以在客户端也可以在服务端。默认的JSF数据验证就是在服务端,数据只能在被提交以后才能够被验证,然后把错误信息传递回用户的浏览器。后来大规模使用Ajax后,基本可以实现对修改的数据“即时”验证,注意这里是个打了引号的即时,数据事实上还是要在浏览器和服务端之间进行传递的,只不过Ajax将这种传递改为隐式了而已,理论上并没有真正实现(断网)即时验证。而在Swing应用上就能够达成这种愿望。
事实上,开发Swing应用时,数据验证一直比较棘手,需要手工编码的地方太多,效率不高。后来出了JGoodies Validation 结合JGoodies binding后,好了一些。这个JGoodies Validation既可以实现model层面的验证,也可以实现Bean层面的验证,但是多年使用下来,发现其实它比较适用于中小项目,而且要编写的代码其实一点不比自己手动编写的少。
JGoodies流行了一段时间后,sun开始推出自己的bean绑定方案:beansbinding(JSR 295),我个人感觉要比JGoodies binding好用(JGoodies的作者Karsten也在专家组里,这个人我以前和他一起共事过,我的msn space里面还有跟他的合影,绝对是Swing界的牛人)。这个beansbinding也提供数据验证,但是它的这个数据验证只是在target被改动后,数据被同步回source之前才会起作用,使用起来局限性比较大,而且编码量也不小。
由于目前绝大部分项目是基于POJO的,Hibernate validator已经提供了一个很好的数据验证框架,我们完全没必要再重复发明轮子,我们应该努力站在巨人的肩膀上,这样我们才能站得更高,看得更远。于是我考虑结合beansbinding和Hibernate Validator开发数据验证。还有一个重要的问题,那就是数据错误的时候,需要在用户界面上展示相应的信息,例如Error icon和错误提示,这部分我考虑使用JXLayer。
你可以在如下链接中找到相关框架的具体信息:
1. Hibernate Validator: http://www.hibernate.org/hib_docs/validator/reference/en/html_single/
2. Beansbinding: https://beansbinding.dev.java.net/
3. JXlayer: http://weblogs.java.net/blog/alexfromsun/
阅读这篇文章,不需要你熟悉这些类库,不过了解这些类库能够帮助你更好地理解这篇文章。
我的这个通用模块是参考JXLayer里面的一个demo类TextValidationDemo的,这个JXlayer是由Alexander Potochkin开发的,我很喜欢,使用起来很顺手,强烈推荐使用。
下面开始介绍代码。首先是建立一个java项目,对于这个小项目,我使用netbeans。这里说句题外话,中型和大型的Swing应用,建议最好还是不要使用netbeans的GUI Builder,一方面它生成的代码超级烂,另一方面很难测试。目前市面上有很多好用的layout的框架,例如 JGoodies form和MigLayout,开发效率绝对不比netbeans的GUI builder差,你还不需要面对令人头疼的机器成的代码。
项目创建好后,加入类库:
然后写一个persistence bean:
package de.jingge.domain; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import org.hibernate.validator.Length; import org.hibernate.validator.NotEmpty; @Entity public class Country extends AbstractBean { private static final long serialVersionUID = 5341382564159667599L; public static final String PROPERTYNAME_NAME = "name"; public static final String PROPERTYNAME_CODE = "code"; private String name; private String code; private Long id; public Country() { } public Country(String code, String name) { super(); setCode(code); setName(name); } @Id @GeneratedValue(strategy = GenerationType.AUTO) public Long getId() { return id; } public void setId(Long id) { this.id = id; } @NotEmpty public String getName() { return name; } public void setName(String name) { firePropertyChange(PROPERTYNAME_NAME, this.name, this.name = name); } @Length(min=2, max= 2, message="Code length must be 2") @NotEmpty public String getCode() { return code; } public void setCode(String code) { firePropertyChange(PROPERTYNAME_CODE, this.code, this.code = code); } }
这里我为了强调可以在Swing客户端直接使用和验证persistence bean,故意写了一个persistence bean,实际应用中,这个类只需要是一个pojo就行了。
这个Country类代表一个国家,它有两个属性,code和name,我给他们分别加上个各自的验证限制。code不能为空,且必须正好是两个字符,例如CN,DE,US。name不能为空。这些annotaion均出自Hibernate Validator。那个父类AbstractBean出自SwingX类库,我们的Country类继承了它之后就可以支持property change event了。
ok, 下面可以开始编写这个模块的核心代码了。前面说过,我会使用JXlayer。使用它的好处是:所有JXlayer的painting event都会被转到UI类来,我们只需要编写一个集成Hibernate Validator的UI类就可以了,我称这个类为HibernateValidationUI,代码如下:
package de.jingge.view; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import javax.swing.BorderFactory; import javax.swing.JComponent; import javax.swing.text.JTextComponent; import org.hibernate.validator.ClassValidator; import org.hibernate.validator.InvalidValue; import org.jdesktop.beansbinding.ELProperty; import org.jdesktop.beansbinding.PropertyStateEvent; import org.jdesktop.beansbinding.PropertyStateListener; import org.jdesktop.jxlayer.JXLayer; import org.jdesktop.jxlayer.plaf.AbstractLayerUI; /** * Header: * Description: A layerUI which will validate the referenced property value of * the object each time when the paint(...) method is called. * The value of the given object property will be observed. * Note: This UI works only with {@link JXLayer}. Any change of the property * will force repainting the UI. The work process looks like: property changed -> * jxlayer will be repainted -> the paint(...) method of this UI will be called. * The logic of validation will be handled by the Hibernate validator * framework. * */ public class HibernateValidationUI extends AbstractLayerUI<jTextComponent> { private Object object; private String propertyName; private ClassValidator validator; private ELProperty elProperty; private PropertyStateListener propertyChangeHandler; public HibernateValidationUI(Object obj, String propertyName) { this.object = obj; this.propertyName = propertyName; propertyChangeHandler = new PropertyChangeHandler(); validator = new ClassValidator(obj.getClass()); elProperty = ELProperty.create("${" + propertyName + "}"); } public void installUI(JComponent c) { super.installUI(c); elProperty.addPropertyStateListener(object, propertyChangeHandler); } public void uninstallUI(JComponent c) { super.uninstallUI(c); elProperty.removePropertyStateListener(object, propertyChangeHandler); } protected void paintLayer(Graphics2D g2, JXLayer<jTextComponent> l) { super.paintLayer(g2, l); InvalidValue[] validationMessages = validator.getInvalidValues(object, propertyName); if (validationMessages.length > 0) { BufferedImage image = Java2DIconFactory.createErrorIcon(); g2.drawImage(image, l.getWidth() - image.getWidth() - 1, l.getHeight() - 8, null); l.getView().setToolTipText(validationMessages[0].getMessage()); return; } l.getView().setToolTipText(null); } boolean isValid() { return validator.getInvalidValues(object, propertyName).length == 0; } class PropertyChangeHandler implements PropertyStateListener { @Override public void propertyStateChanged(PropertyStateEvent pse) { setDirty(true); } } }
这个HibernateValidationUI类只有一个构建器,它接收两个参数,一个是source object,也就是我们要修改的那个Bean类的实例,另外一个是这个bean的一个属性,这个HibernateValidationUI就负责验证这个属性。
在installUI()方法中,我们启动对属性变化的观察类,而在uninstallUI()方法里面,我们需要卸载这个观察类。
当给定对象的属性值发生变化时,PropertyChangeHandler的propertyStateChanged()方法就会被调用,这个功能是通过elProperty和PropertzChangeHandler相结合来实现的。在propertyStateChangeed()方法里UI类的方法setDirty()会被调用,该方法的调用会导致UI类的状态变化,进而引发(re)painting,之后经过一系列的方法调用传递,paintLayer(Graphics2D g2, JXLayer<jTextComponent> l)这个方法将会被调用,这个方法要做的就是我们这个数据验证模块的核心功能:
1. 调用Hibernate Validator验证该属性。
2. 如果数据不正确,则在GUI上显示一个error icon,并且将错误信息作为tooltip展示给用户。
在第二点里面产生了一个问题,谢谢Alexp对我的指点。Swing team里面有一些规定,其中之一就是,在paint()方法里面最好不要改变Component的状态,而setTooltip()方法将会改变component的状态,因此需要在paint()方法之外调用。我目前使用下来,还没有发现什么严重的错误,决定暂时不改了,回头有时间在将这个代码翻新一下。
类中用到的Java2DIconFactory代码如下:
package de.jingge.view; import java.awt.Color; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.image.BufferedImage; public class Java2DIconFactory { public static BufferedImage createErrorIcon() { return createErrorIcon(7, 8); } public static BufferedImage createErrorIcon(int width, int height) { BufferedImage icon = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = (Graphics2D) icon.getGraphics(); g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE); g2.setColor(Color.RED); g2.fillRect(0, 0, width, height); g2.setColor(Color.WHITE); g2.drawLine(0, 0, width, height); g2.drawLine(0, height, width, 0); g2.dispose(); return icon; } }
没什么太多好解释的,就是使用Java 2D画一个Error icon。
接着,我们需要编写一个Factory类,构建一个JTextField,尽量把复杂技术封装起来,这样程序员开发起来可以提高效率,代码如下:
package de.jingge.view; import javax.swing.JTextField; import javax.swing.text.JTextComponent; import org.jdesktop.beansbinding.AutoBinding; import org.jdesktop.beansbinding.BeanProperty; import org.jdesktop.beansbinding.BindingGroup; import org.jdesktop.beansbinding.Bindings; import org.jdesktop.beansbinding.ELProperty; import org.jdesktop.jxlayer.JXLayer; import static org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.*; public class GuiComponentFactory { public static JXLayer<jTextComponent> createTextField( BindingGroup bindingGroup, Object sourceObject, String sourceProperty) { JTextField field = new JTextField(); AutoBinding binding = Bindings.createAutoBinding(READ_WRITE, sourceObject, ELProperty.create("${" + sourceProperty + "}"), field, BeanProperty.create("text")); bindingGroup.addBinding(binding); bindingGroup.bind(); return new JXLayer<jTextComponent>(field, new HibernateValidationUI( sourceObject, sourceProperty)); } }
createTextField()方法主要将给定对象属性的值与JTextField的text绑定,然后将JTextField纳入到JXLayer的管理之下。这样一来,一旦用户在JTextField里面修改数据,这个改变就会同步到该对象属性上,然后就引发了前面描述的一系列逻辑,最终改变的数据就会被Hiberante Validator加以验证。
最后,我们可以编写一个Demo application来看看效果如何,代码如下:
package de.jingge.main; import de.jingge.domain.Country; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.Toolkit; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; import javax.swing.text.JTextComponent; import net.miginfocom.swing.MigLayout; import org.jdesktop.beansbinding.BindingGroup; import org.jdesktop.jxlayer.JXLayer; import static de.jingge.view.GuiComponentFactory.*; public class ValidationApplicaton { private BindingGroup bg; private Country country; private JXLayer<jTextComponent> codeField; private JXLayer<jTextComponent> nameField; /** * @param args the command line arguments */ public static void main(String[] args) { try { UIManager.setLookAndFeel( "com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel"); } catch (UnsupportedLookAndFeelException ex) { System.err.println( "Nimbus L&F does not support. Default L&F will be used."); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } ValidationApplicaton app = new ValidationApplicaton(); JFrame frame = new JFrame("Demo Validation Application"); frame.setPreferredSize(new Dimension(360, 150)); frame.getContentPane().add(app.buildPanel(), BorderLayout.CENTER); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setCenter(frame); frame.setVisible(true); frame.pack(); } private static void setCenter(JFrame frame) { Toolkit toolkit = Toolkit.getDefaultToolkit(); Dimension screenSize = toolkit.getScreenSize(); // Calculate the frame location int x = (screenSize.width - (int) frame.getPreferredSize().getWidth()) / 2; int y = (screenSize.height - (int) frame.getPreferredSize().getHeight()) / 2; // Set the new frame location frame.setLocation(x, y); } public ValidationApplicaton() { country = new Country(); bg = new BindingGroup(); } private JPanel buildPanel() { codeField = createTextField(bg, country, Country.PROPERTYNAME_CODE); nameField = createTextField(bg, country, Country.PROPERTYNAME_NAME); JPanel panel = new JPanel(new MigLayout("", "[50px, right]10[200px:250px:300px]", "[center]")); panel.add(new JLabel("Code:"), "cell 0 0"); panel.add(codeField, "cell 1 0, w 200px:250px:300px"); panel.add(new JLabel("Name:"), "cell 0 1"); panel.add(nameField, "cell 1 1, w 200px:250px:300px"); return panel; } }
这个类比较简单了,我简单解释一下:
在main()方法里面,我们创建了一个JFrame,然后放入一个JPanel
setCenter()方法负责将窗口至于屏幕的正中间。
在构建器里面,我们创建了Country和BindingGroup的对象实例。
在buildPanel()方法里面,我们使用MigLayout构建了一个Panel,其中codeField和nameField对应各自的对象属性。更多关于MigLayout的信息看这里:http://www.miglayout.com/
。这也是一个例子,大家可以看到使用MigLayout开发Swing真的是非常方便。
从这个Demo里面也可以看出,编写好pojo后,程序员只需要调用createTextField(bg, country, Country.PROPERTYNAME_CODE); 就可以创建一个支持数据验证的JTextField,编码量已经可以说是最大限度的降低了。
运行程序,你会看到:
这个code和name的数据都不合法,用户看到了error icon。
将鼠标移到Text field上,你会看到:
填好合法数据后,Error icon就不见了:
总结:
使用这个通用数据验证模块有很多好处:
1. 如果项目使用ORM,例如Hibernate,这个方案应该是解决数据验证的最好方案之一。
2. 对于普通的数据验证,例如非空,email,长度等等,程序员根本不需要编码,只要在POJO上使用相应的Hibernate Validator annotation就可以了。
3. 对于复杂的数据验证,Hibernate Validator提供了很好的扩展机制,只要写一个annotation外加一个Validator就可以了。Swing应用这边仍然不需要编写任何代码。
综上所述,可以看出通过使用这个通用数据验证模块,开发效率会提高很多。
对这个项目感兴趣的朋友可以给我留言,人数够多的话,我会考虑将整个netbeans项目上传到javaeye上来。
评论
不过这套结构感觉还是不错的
在 form 的布局方面,我还是觉得 jgoodies 的formlayout比较好用,配合jformdesigner,真的是无敌啊
在错误提示方面,如果只是为了显示那个叉叉,我觉得没有必要用第三方jar,自己写个简易的 JLayeredPane 就 OK 了
最后加一句,我总觉得 配置文件就是配置文件,代码就是代码,把代码和配置文件混起来(注解)玩是一件很难让我接受的事情.
历史总在螺旋式前进;反复的、不停的迭代
<div class='quote_div'>我觉得netbeans那个还是不错的,但那个玩意有时候也很不爽就是了。关键还是swing市场不够大。我个人还是很喜欢swing的。这东西怎么看怎么比web程序顺眼。不过十来年了真的进步有限</div>
<p>你看走眼了吧,Swing在目前界面开发工具库的市场是老大,从2005年9月开始swing就开始占据了界面开发市场的首把交椅:</p>
<p>http://weblogs.java.net/blog/hansmuller/archive/2005/10/official_swing.html</p>
<p>"Java Swing with 47% use, has surpassed WinForms as the dominant GUI development toolkit, an increase of 27% since fall 2004." </p>
<p>我觉得大家对于Swing的偏见基本上是源于对Swing技术本身和Swing现在的市场状况太缺乏了解,太缺乏了解,许多印象和资料都停留在7、8年以前的状况。想想看如果Swing是一个人的话,被误解这么多年,被偏见笼盖这么多年,郁闷也郁闷死了。</p>
}这样的语句?
我现在都用 new Panel(){{
setLayout();
add(...);
}}
就为了好看,真他妈的忧伤,我总觉得该有do ...with之类的啊
NetBeans当然不需要你进行事件托管了,你完全可以自己手工添加事件粘结代码。如过你嫌这样测试麻烦,完全可以只用netbeans设计界面,自己粘结事件代码。
我也做了一个开源项目,目的是实现NetBeans的界面设计功能,生成类似VE风格的代码,生成的代码比较好维护,不需要form文件。是一个Eclipse插件,现在已经有一定的使用价值,这篇文章是我的一篇介绍文章:
http://www.iteye.com/topic/208787
开源项目的位置在:
http://code.google.com/p/visualswing4eclipse/
欢迎光临串门。
如果这样做的话,就只用了个布局,而且还要面对一大堆机器生成的代码,有点得不偿失。 想想看,整个程序里面,花在编写loyout的代码能有多少?不如直接用JGoodies的form layout或者是migLayout,效率很高,手写的代码量很少。个人认为综合考虑可测试性,灵活性,和可扩展性,后者要好很多。
我是主持开发框架的,有很多自己的组件,swing已有的组件还要和其他的类库建立关联,大量封装,开发完全基于TDD。如果使用Gui builder就得把这些技术细节全部推给普通程序员去做,开发的效率会下降很多。
使用这类Gui builder感觉就是束手束脚,而且无法TDD。
你做的那个插件我看到了,感觉很棒,对于直接做项目的团队应该是个不错的选择,希望你能坚持下去。不知道你能不能写篇文章强调一下你的这个插件对比netbeans的那个都有哪些优势。
NetBeans当然不需要你进行事件托管了,你完全可以自己手工添加事件粘结代码。如过你嫌这样测试麻烦,完全可以只用netbeans设计界面,自己粘结事件代码。
我也做了一个开源项目,目的是实现NetBeans的界面设计功能,生成类似VE风格的代码,生成的代码比较好维护,不需要form文件。是一个Eclipse插件,现在已经有一定的使用价值,这篇文章是我的一篇介绍文章:
http://www.iteye.com/topic/208787
开源项目的位置在:
http://code.google.com/p/visualswing4eclipse/
欢迎光临串门。
维护起来可就是噩梦了......
手写的未必好维护。只让netbeans帮你管理布局就好了。 难道VB就不用维护了?
如果手写的代码还不好维护,那真得好好检讨一下了,考虑学学TDD。
使用netbeans的Gui builder托管的可不单单是布局,整个事件系统全部托管,开发员只是编写事件触发后所要调用的逻辑。这样做测试起来很麻烦。
维护起来可就是噩梦了......
手写的未必好维护。只让netbeans帮你管理布局就好了。 难道VB就不用维护了?
维护起来可就是噩梦了......
我在英文博客新写了一篇博文,里面更新了HibernateValidationUI.java的代码,移除了一个antipattern,英文不是很多, 有兴趣的朋友可以去哪里看看。地址: http://polygoncell.blogspot.com/2008/07/update-common-validation-module-for.html
回头有时间了我再用中文写一下。
可惜我搞了一年swing就没做这方面了,现在回头看看,swing确实改变了很多。
我也是搞SWING的
你的东东不错,迫切想用用!
swingx主要是缺少文档,如果有人愿意下功夫看源代码的话,里面有很多很棒的模块,可以直接用到企业开发中去。对于我现在主持开发的框架而言,Swingx也是一个很重要的类库,已经有很多模块派上用场了。
你的东东不错,迫切想用用!
相关推荐
#### (二) 适用于各类Swing应用的通用数据验证模块 **项目创建好后,加入类库**:通常需要引入用于数据验证的库,如Hibernate Validator等。 **然后写一个persistence bean**:该bean用于执行数据验证逻辑。 - **...
通过提供的文件列表,我们可以推测这两个通用安全模块可能涉及到用户身份验证(登录)和数据传输加密。下面将详细探讨这些知识点。 1. **Java编程基础**: Java是一种面向对象的、跨平台的编程语言,广泛应用于...
在实际项目中,这两个通用安全模块可能涉及身份验证、数据加密、安全通信等方面。身份验证可能通过用户名密码或者更复杂的机制如OAuth进行;数据加密可能利用了Java提供的加密算法如AES或RSA;而安全通信则可能使用...
- 辅助类:可能包含日志记录、数据验证等通用功能。 文档和视频教程将详细解释各个部分的功能和实现方式,帮助学习者了解如何组织代码、设计数据库表结构、编写SQL语句以及如何利用Swing组件构建用户界面。通过学习...
7. **框架与模板**:这个项目提供了一个通用模板,适用于课程设计或毕业设计,可以帮助初学者快速搭建项目结构,理解业务流程和模块划分。 8. **视频教程**:提供的教学视频(BV1mz421d7nG)将帮助学生直观地学习...
《Java Swing GUI工具包+JDBC实现校园信息管理系统》是一个基于Java编程语言的项目,它利用Swing图形用户界面(GUI)工具包构建了一个管理校园信息的系统,并通过JDBC(Java Database Connectivity)与数据库进行...
javax.security.auth.spi 此包提供用于实现可插入验证模块的接口。 javax.security.auth.x500 此包包含应该用来在 Subject 中存储 X500 Principal 和 X500 Private Crendentials 的类。 javax.security.cert 为...
Java 是一种广泛应用于个人 PC、数据中心、游戏控制台、科学超级计算机、移动和互联网的面向对象的程序设计语言。Swing 是一个为 Java 设计的 GUI 工具包,提供了许多比 AWT 更好的屏幕显示元素。MySQL 是一个关系型...
java毕设 本系统是一套基于Java...该系统具有简单、易用的操作界面,实用的功能模块,可靠的数据存储,为百货店提供了一套专业、高效的POS积分管理系统。通过不断优化和升级,该系统将更好地服务于会员,促进百货店的发展。
此外,为了保证软件的质量,项目可能还包含了单元测试和集成测试,使用JUnit等测试框架来验证各个功能模块的正确性。良好的代码组织结构,如合理的类和方法划分,以及适当的注释,都是初学者应该学习的重要部分。 ...
6. **工具模块(tools)**:`tools`通常包含一些通用的功能,比如日志记录、数据验证、数据库连接池管理等。这些工具类可以提高代码的复用性和可维护性。 7. **数据库设计**:数据库设计是关键部分,可能包括学生表...
- **查询统计模块**:提供各类统计报告和数据分析功能。 - **库存管理模块**:监控库存状态,预警库存不足的情况。 - **销售管理模块**:记录销售详情,支持多种支付方式。 - **系统管理模块**:管理用户权限、系统...
2. **基础设施支持**:Struts 提供了一系列的功能支持,如表单验证、错误处理、工作流控制等,这些功能有助于提高 Web 应用的健壮性和可维护性。 3. **易于扩展**:由于采用了 MVC 模式,Struts 可以轻松地添加新的...
这种架构将业务逻辑、数据处理和用户界面分离,有利于代码的重用和系统的维护。 8. **问题解决与调试**:在实训过程中,可能会遇到代码错误、页面设置等问题,例如UTF-8编码设置、数据库连接验证方式选择等。这需要...
【标题】:选择城市模块——SelectCityModule...综上所述,SelectCityModule是一个用Java编写的,优化过的选择城市模块,适用于需要进行省份和城市选择的各类应用,其良好的可复用性和稳定性使其成为开发者的得力工具。
1. **ean码结构理解**:ean码分为EAN-8和EAN-13两种类型,前者适用于小型商品,后者更通用。ean-13码由1位国别码、2位出版者代码、5位产品代码和2位校验码组成。 2. **数据编码**:ean码使用二进制编码,将数字转换...
org.ietf.jgss 此包提供一个框架,该框架允许应用程序开发人员通过利用统一的 API 使用一些来自各种基础安全机制(如 Kerberos)的安全服务,如验证、数据完整性和和数据机密性。 org.omg.CORBA 提供 OMG CORBA API ...
由于比较大分为两个部分,这是第一...org.ietf.jgss 此包提供一个框架,该框架允许应用程序开发人员通过利用统一的 API 使用一些来自各种基础安全机制(如 Kerberos)的安全服务,如验证、数据完整性和和数据机密性。 ...
由于文件比较大 分为两个部分,这是...org.ietf.jgss 此包提供一个框架,该框架允许应用程序开发人员通过利用统一的 API 使用一些来自各种基础安全机制(如 Kerberos)的安全服务,如验证、数据完整性和和数据机密性。...
jdk_api_1_6帮助开发 ...org.ietf.jgss 此包提供一个框架,该框架允许应用程序开发人员通过利用统一的 API 使用一些来自各种基础安全机制(如 Kerberos)的安全服务,如验证、数据完整性和和数据机密性。 org.omg....