1.新建项目,添加jar包
tomcat
jsp
struts、hibernate、spring
2.配置
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<!--配置spring监听器-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<!--配置struts核心过滤器-->
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>*.action</url-pattern>
</filter-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
struts.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd"> <struts>
<!-- 禁用动态方法访问!userAction -->
<constant name="struts.enable.DynamicMethodInvocation" value="false" />
<!-- 配置成开发模式 -->
<constant name="struts.devMode" value="true" />
<!-- 配置拓展名为action -->
<constant name="struts.action.extention" value="action" />
<!-- 把主题配置成simple -->
<constant name="struts.ui.theme" value="simple" />
</struts>
3.测试spring
创建测试类TestService,并使用注解方式加入容器;
创建测试配置文件test-spring.xml(开启注解扫描)
<context:component-scan base-package="com.juaner.test.service.impl"></context:component-scan>
在主配置文件中引入配置文件
<import resource="classpath:com/juaner/*/conf/*-spring.xml"/>
测试spring
@Test
public void testSpring(){
TestService ts= (TestService) ct.getBean("testService");
ts.say();
}
4.测试struts-spring
创建action,注入testService,并调用方法;
配置test-struts.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd"> <struts>
<package name="test-action" namespace="/" extends="struts-default">
<action name="test_*" class="com.juaner.test.action.TestAction" method="{1}">
<result name="success">/WEB-INF/jsp/test/test.jsp</result>
</action>
</package>
</struts>
在struts.xml中引入配置文件
<include file="com/juaner/test/conf/test-struts.xml"/>
访问action
5.测试hibernate-spring
配置数据源
<!-- 导入外部的properties配置文件 -->
<context:property-placeholder location="classpath:db.properties" /> <!-- 配置c3p0数据源 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="jdbcUrl" value="${jdbcUrl}"></property>
<property name="driverClass" value="${driverClass}"></property>
<property name="user" value="${user}"></property>
<property name="password" value="${password}"></property>
<!--初始化时获取三个连接,取值应在minPoolSize与maxPoolSize之间。Default: 3 -->
<property name="initialPoolSize" value="${initialPoolSize}"></property>
<!--连接池中保留的最小连接数。Default: 3 -->
<property name="minPoolSize" value="3"></property>
<!--连接池中保留的最大连接数。Default: 15 -->
<property name="maxPoolSize" value="${maxPoolSize}"></property>
<!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 -->
<property name="acquireIncrement" value="3"></property>
<!--最大空闲时间,1800秒内未使用则连接被丢弃,若为0则永不丢弃。Default: 0 -->
<property name="maxIdleTime" value="1800"></property>
</bean>
配置db.properties
jdbcUrl=jdbc:mysql://localhost:3306/itcastTax?useUnicode=true&characterEncoding=utf8
driverClass=com.mysql.jdbc.Driver
user=root
password=juaner767
initialPoolSize=10
maxPoolSize=30
新建实例类Person及相应的配置文件person.hbm.xml
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping>
<class name="com.juaner.test.entity.Person" table="person">
<id name="id" type="java.lang.String">
<column name="id" length="32" />
<generator class="uuid" />
</id>
<property name="name" type="java.lang.String">
<column name="name" length="20" not-null="true" />
</property>
</class>
</hibernate-mapping>
配置hibernate sessionfactory属性及映射文件
<bean id="sf" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="javax.persistence.validation.mode">none</prop>
</props>
</property>
<property name="mappingLocations">
<list>
<value>classpath:com/juaner/test/entity/*.hbm.xml</value>
</list>
</property>
</bean>
测试hibernate
ClassPathXmlApplicationContext ct = new ClassPathXmlApplicationContext("applicationContext.xml");
@Test
public void testHibernate(){
SessionFactory sf = (SessionFactory) ct.getBean("sf");
Session session = sf.openSession();
Transaction transaction = session.beginTransaction(); session.save(new Person("人员1")); transaction.commit();
session.close();
}
6.事务控制
配置事务
<!--事务管理-->
<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sf"/>
</bean>
<!--事务增强-->
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="find*" read-only="true"/>
<tx:method name="get*" read-only="true"/>
<tx:method name="list*" read-only="true"/>
<tx:method name="search*" read-only="true"/>
<tx:method name="*" rollback-for="Throwable" />
</tx:attributes>
</tx:advice>
<!--aop-->
<aop:config>
<aop:pointcut id="serviceOperation" expression="bean(*Service)"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="serviceOperation"/>
</aop:config> <bean id="testDao" class="com.juaner.test.dao.impl.TestDaoImpl">
<property name="sessionFactory" ref="sf"/>
</bean>
开发TestDao、TestService接口及其实现类
public class TestDaoImpl extends HibernateDaoSupport implements TestDao{ @Override
public void save(Person person) {
getHibernateTemplate().save(person);
} @Override
public Person findPerson(Serializable id) {
return getHibernateTemplate().get(Person.class,id);
}
}
<bean id="testDao" class="com.juaner.test.dao.impl.TestDaoImpl">
<property name="sessionFactory" ref="sf"/>
</bean>
@Service("testService")
public class TestServiceImpl implements TestService{
@Resource
private TestDao testDao;
@Override
public void say() {
System.out.println("hi");
} @Override
public void save(Person person) {
testDao.save(person);
} @Override
public Person findPerson(Serializable id) {
return testDao.findPerson(id);
}
}
测试:必须用TestService接口接收,不能用TestServiceImpl接收,因为TestServiceImpl实现了TestService接口,生成的代理类也是TestService的子类,无法转成TestServiceImpl
@Test
public void testReadOnly(){
TestService testService= (TestService) ct.getBean("testService");
System.out.println(testService.findPerson("fd5872945599fd07015599fd08580000").getName());
} @Test
public void testRollBack(){
TestService testService= (TestService) ct.getBean("testService");
testService.save(new Person("人员4"));
}
7.资源分类
8.配置log4j
导入jar包
配置log4j.xml
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p [%t] %c{1}:%L - %m%n log4j.rootLogger=error, stdout,R
#log4j.logger.com.juaner=error log4j.appender.R=org.apache.log4j.DailyRollingFileAppender
log4j.appender.R.File=/itcastTax.log
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%d [%t] %5p %c - %m%n
9.用户的增删改查
抽取BaseDao
BaseDao、BaseDaoImpl
public interface BaseDao<T> {
public void save(T entity);
public void delete(Serializable id);
public void update(T entity);
public T findObjectById(Serializable id);
public List<T> findObjects();
}
反射
public abstract class BaseDaoImpl<T> extends HibernateDaoSupport implements BaseDao<T>{
private Class<T> clazz; public BaseDaoImpl(){
//获取被实例化的类泛型 BaseDaoImpl<User>=
ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();
clazz = (Class<T>) pt.getActualTypeArguments()[0];
} @Override
public void save(Object entity) {
getHibernateTemplate().save(entity);
} @Override
public void delete(Serializable id) {
getHibernateTemplate().delete(findObjectById(id));
} @Override
public void update(Object entity) {
getHibernateTemplate().update(entity);
} @Override
public T findObjectById(Serializable id) {
return getHibernateTemplate().get(clazz,id);
} @Override
public List<T> findObjects() {
Session session = getSession();
Query query = session.createQuery("from "+clazz.getSimpleName());
return query.list();
}
}
User实体类及映射
public class User {
private String id;
private String dept;
private String name;
private String account;
private String password;
//头像
private String headImg;
private boolean gender;
private String state;
private String mobile;
private String email;
private Date birthday;
private String memo;
set...
get...
}
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping>
<class name="com.juaner.nsfw.user.entity.User" table="user">
<id name="id" type="java.lang.String">
<column name="id" length="32" />
<generator class="uuid" />
</id>
<property name="name" type="java.lang.String">
<column name="name" length="20" not-null="true" />
</property>
<property name="dept" type="java.lang.String">
<column name="dept" length="20" not-null="true" />
</property>
<property name="account" type="java.lang.String">
<column name="account" length="50" not-null="true" />
</property>
<property name="password" type="java.lang.String">
<column name="password" length="50" not-null="true" />
</property>
<property name="headImg" type="java.lang.String">
<column name="headImg" length="100" />
</property>
<property name="gender" type="java.lang.Boolean">
<column name="gender" />
</property>
<property name="email" type="java.lang.String">
<column name="email" length="50" />
</property>
<property name="mobile" type="java.lang.String">
<column name="mobile" length="20" />
</property>
<property name="birthday" type="java.util.Date">
<column name="birthday" length="10" />
</property>
<property name="state" type="java.lang.String">
<column name="state" length="1" />
</property>
<property name="memo" type="java.lang.String">
<column name="memo" length="200" />
</property>
</class> </hibernate-mapping>
UserDao、UserDaoImpl
public interface UserDao extends BaseDao<User> {
}
public class UserDaoImpl extends BaseDaoImpl<User> implements UserDao{
}
UserService、UserServiceImpl
public interface UserService {
public void save(User user);
public void delete(Serializable id);
public void update(User user);
public User findObjectById(Serializable id);
public List<User> findObjects();
}
@Service("userService")
public class UserServiceImpl implements UserService{
@Resource
private UserDao userDao;
@Override
public void save(User user) {
userDao.save(user);
} @Override
public void delete(Serializable id) {
userDao.delete(id);
} @Override
public void update(User user) {
userDao.update(user);
} @Override
public User findObjectById(Serializable id) {
return userDao.findObjectById(id);
} @Override
public List<User> findObjects() {
return userDao.findObjects();
}
}
user-spring配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <bean id="userDao" class="com.juaner.nsfw.user.dao.impl.UserDaoImpl" parent="baseDao">
</bean>
<context:component-scan base-package="com.juaner.nsfw.user.conf"/>
</beans>
其中,baseDao在spring的主配置文件中配置,这样可以避免为sf的更改带来dao的大量改变。
<bean id="baseDao" abstract="true">
<property name="sessionFactory" ref="sf"/>
</bean>
UserAction及struts配置
注意:add方法之后跳转需要重定向地址,但是listUI位于WEB-INF下,而且需要重新查询所有的user,所以需要redirectAction,调用listUI方法。
public class UserAction extends ActionSupport{
//IOC容器根据名称查询是否存在叫userService的bean,然后赋值
//所以必须叫userService,否则出错
@Resource
private UserService userService;
private List<User> userList;
private User user; /**
* 新增:跳转
*/
public String addUI(){
return "addUI";
}
/**
*新增:增加
*/
public String add(){
if(user != null)
userService.save(user);
return SUCCESS;
}
/**
*删除:删除一个
*/
public String delete(){
if(user != null && user.getId()!= null)
userService.delete(user.getId());
return SUCCESS;
}
/**
*删除:批量删除
*/
public String deleteSelected(){
return SUCCESS;
}
/**
*修改:跳转
*/
public String editUI(){
return "editUI";
}
/**
*修改:修改
*/
public String edit(){
if(user != null && user.getId()!= null)
userService.update(user);
return SUCCESS;
}
/**
*查询
*/
public String listUI(){
userList = userService.findObjects();
return "listUI";
}
get...
set...
}
user-struts.xml
<struts>
<package name="user-action" extends="struts-default" namespace="/nsfw">
<global-results>
<result name="success">/WEB-INF/jsp/nsfw/user/listUI.jsp</result>
</global-results>
<action name="user_*" class="com.juaner.nsfw.user.action.UserAction" method="{1}">
<result name="{1}">/WEB-INF/jsp/nsfw/user/{1}.jsp</result>
</action>
</package>
</struts>
struts iterator标签
<s:iterator value="userList" status="st">
<tr <s:if test="#st.odd"> bgcolor="f8f8f8"</s:if>>
<td align="center"><input type="checkbox" name="selectedRow" value="<s:property value="id" />"/></td>
<td align="center"><s:property value="name" /></td>
<td align="center"><s:property value="account" /></td>
<td align="center"><s:property value="dept" /></td>
<td align="center"><s:property value="gender?'男':'女'"/> </td>
<td align="center"><s:property value="email" /></td>
<td align="center">
<a href="javascript:doEdit('<s:property value='id'/>')">编辑</a>
<a href="javascript:doDelete('<s:property value='id'/>')">删除</a>
</td>
</tr>
</s:iterator>
10.使用datepicker插件
在js中导入WdataPicker,并引入
<script type="text/javascript" src="${basePath}js/datepicker/WdatePicker.js"></script>
使用
<s:textfield id="birthday" name="user.birthday" readonly="true"
onfocus="WdatePicker({skin:'whyGreen',dateFmt:'yyyy-MM-dd'})"/>
<s:textfield id="birthday" name="user.birthday" readonly="true"
onfocus="WdatePicker({skin:'whyGreen',dateFmt:'yyyy-MM-dd'})">
<s:param name="value"><s:date name='user.birthday' format='yyyy-MM-dd' /></s:param>
</s:textfield>
11.头像的上传与下载
struts上传文件,需要一个File,contentType,filename。
add.jsp
提交的表单enctype
<form id="form" name="form" action="${basePath}nsfw/user_add.action" method="post" enctype="multipart/form-data">
<tr>
<td class="tdBg" width="200px">头像:</td>
<td>
<input type="file" name="headImg"/>
</td>
</tr>
UserAction方法添加字段及上传方法
private File headImg;
private String headImgContentType;
private String headImgFileName;
public String add(){
try {
if(user != null) {
if (headImg != null) {
//获取保存路径的绝对地址
String filePath= ServletActionContext.getServletContext().getRealPath("upload/user");
//防止被覆盖需要重命名,中文文件名可能无法正常显示
String fileName = UUID.randomUUID().toString().replace("-","")+headImgFileName.substring(headImgFileName.lastIndexOf("."));
//复制文件
FileUtils.copyFile(headImg,new File(filePath,fileName));
//设置用户头像路径
user.setHeadImg("user/"+fileName);
}
userService.save(user);
}
} catch (IOException e) {
e.printStackTrace();
}
return "list";
}
edit.jsp
<td>
<s:if test="%{user.headImg != null && user.headImg != ''}">
<img src="${basePath}upload/<s:property value='user.headImg'/> " width="100" height="100"/>
<%--防止图片丢失--%>
<s:hidden name="user.headImg"/>
</s:if>
<input type="file" name="headImg"/>
</td>
12.POI实现excel导入导出
导入和导出按钮设置
function doImportExcel(){
document.forms[0].action = "${basePath}nsfw/user_importExcel.action";
document.forms[0].submit();
}
function doExportExcel(){
window.open("${basePath}nsfw/user_exportExcel2.action");
}
UserAction中添加方法
//导出数据
public void exportExcel(){
try {
users = userService.findObjects();
HttpServletResponse response = ServletActionContext.getResponse();
response.setContentType("application/x-excel");
response.setHeader("Content-Disposition", "attachment;filename=" + new String("用户列表.xls".getBytes(), "ISO-8859-1"));
ServletOutputStream outputStream = response.getOutputStream();
userService.exportExcel(outputStream,users); if(outputStream != null)
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
} } //导入数据
private File userExcel;
private String userExcelContentType;
private String userExcelFileName; public String importExcel(){
if(userExcel != null)
{
if(userExcelFileName.matches("^.+\\.(?i)((xls)|(xlsx))$")){
try {
userService.importExcel(userExcel,userExcelFileName);
} catch (IOException e) {
e.printStackTrace();
}
}
}
return "list";
} public File getUserExcel() {
return userExcel;
} public void setUserExcel(File userExcel) {
this.userExcel = userExcel;
} public String getUserExcelContentType() {
return userExcelContentType;
} public void setUserExcelContentType(String userExcelContentType) {
this.userExcelContentType = userExcelContentType;
} public String getUserExcelFileName() {
return userExcelFileName;
} public void setUserExcelFileName(String userExcelFileName) {
this.userExcelFileName = userExcelFileName;
}
抽取方法到ExcelUtil
public class ExcelUtil {
public static void exportUserExcel(List<User> userList, ServletOutputStream outputStream) throws Exception{
HSSFWorkbook workbook = new HSSFWorkbook();
CellRangeAddress cellRangeAddress = new CellRangeAddress(0, 0, 0, 4); HSSFCellStyle headStyle = createCellStyle(workbook, (short) 16);
HSSFCellStyle colStyle = createCellStyle(workbook, (short) 13); HSSFSheet sheet = workbook.createSheet("用户列表");
sheet.addMergedRegion(cellRangeAddress); HSSFRow headRow = sheet.createRow(0);
HSSFCell headCell = headRow.createCell(0);
headCell.setCellStyle(headStyle);
headCell.setCellValue("用户列表"); sheet.setDefaultColumnWidth(25);
HSSFRow colRow = sheet.createRow(1);
String[] titles = new String[]{"用户名","账户名","所属部门","性别","电子邮箱"};
for(int i=0;i<titles.length;i++){
HSSFCell cell = colRow.createCell(i);
cell.setCellStyle(colStyle);
cell.setCellValue(titles[i]);
}
if(userList!=null&& userList.size()>0)
{
for(int i=0;i<userList.size();i++)
{
HSSFRow row = sheet.createRow(i + 2);
HSSFCell cell1 = row.createCell(0);
cell1.setCellValue(userList.get(i).getName());
HSSFCell cell2 = row.createCell(1);
cell2.setCellValue(userList.get(i).getAccount());
HSSFCell cell3 = row.createCell(2);
cell3.setCellValue(userList.get(i).getDept());
HSSFCell cell4 = row.createCell(3);
cell4.setCellValue(userList.get(i).isGender()?"男":"女");
HSSFCell cell5 = row.createCell(4);
cell5.setCellValue(userList.get(i).getEmail());
}
}
workbook.write(outputStream);
workbook.close();
} private static HSSFCellStyle createCellStyle(HSSFWorkbook workbook, short fontSize) {
HSSFCellStyle style = workbook.createCellStyle();
style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER); HSSFFont headFont = workbook.createFont();
headFont.setBold(true);
headFont.setFontHeightInPoints(fontSize);
style.setFont(headFont);
return style;
}
}
给UserService和UserServiceImpl添加方法
@Override
public void exportExcel(ServletOutputStream outputStream, List<User> users) throws IOException {
ExcelUtil.exportUserExcel(outputStream,users); } @Override
public void importExcel(File userExcel, String fileName) throws IOException {
FileInputStream fileInputStream = new FileInputStream(userExcel);
//判断03或者07
boolean is03Excel = fileName.matches("^.+\\.(?i)(xls)&");
Workbook workbook = is03Excel?new HSSFWorkbook(fileInputStream):new XSSFWorkbook(fileInputStream);
Sheet sheet = workbook.getSheetAt(0);
if(sheet.getPhysicalNumberOfRows() > 2){
User user = null;
for(int i=2;i<sheet.getPhysicalNumberOfRows();i++){
Row row = sheet.getRow(i);
String acount = row.getCell(1).getStringCellValue();
if(isUserExists(acount))
continue;
user = new User();
user.setName(row.getCell(0).getStringCellValue());
user.setAccount(row.getCell(1).getStringCellValue());
user.setDept(row.getCell(2).getStringCellValue());
user.setGender(row.getCell(3).getStringCellValue().equals("男")?true:false);
// 如果电话用科学计数法,转为string
String mobile = "";
try {
mobile = row.getCell(4).getStringCellValue();
}catch (Exception e){
double dMobile = row.getCell(4).getNumericCellValue();
mobile = BigDecimal.valueOf(dMobile).toString();
}
user.setMobile(mobile);
user.setEmail(row.getCell(5).getStringCellValue());
user.setBirthday(row.getCell(6).getDateCellValue());
user.setState(User.USER_STATE_VALID);
user.setPassword("123456");
save(user);
}
}
workbook.close();
fileInputStream.close(); }
导入数据
action中
public String importExcel(){
if(userExcel !=null){
try {
if(userExcelFileName.matches("^.+\\.(?i)((xls)|(xlsx))$")){
userService.importExcel(userExcel,userExcelFileName);
}
}catch (Exception e){
e.printStackTrace();
}
}
return SUCCESS;
}
service中
public void importExcel(File userExcel, String userExcelFileName) throws Exception {
boolean is03Excel = userExcelFileName.matches("^.+\\.(?i)(xls)$");
FileInputStream inputStream = new FileInputStream(userExcel);
Workbook workbook = is03Excel ? new HSSFWorkbook(inputStream) : new XSSFWorkbook(inputStream);
Sheet sheet = workbook.getSheetAt(0);
if(sheet.getPhysicalNumberOfRows()>2){
for(int i=2;i<sheet.getPhysicalNumberOfRows();i++){
User user = new User();
Row row = sheet.getRow(i);
String name = row.getCell(0).getStringCellValue();
user.setName(name);
String account = row.getCell(1).getStringCellValue();
user.setAccount(account);
String dept = row.getCell(2).getStringCellValue();
user.setDept(dept);
String gender = row.getCell(3).getStringCellValue();
user.setGender(true);
String mobile = "";
try {
mobile = row.getCell(4).getStringCellValue();
}catch (Exception e){
double dmobile = row.getCell(4).getNumericCellValue();
mobile = BigDecimal.valueOf(dmobile).toString();
}
user.setMobile(mobile);
String email = row.getCell(5).getStringCellValue();
user.setEmail(email);
Date birthday = row.getCell(6).getDateCellValue();
user.setBirthday(birthday);
user.setPassword("123456");
user.setState(User.USER_STATE_VALID);
save(user);
}
}
inputStream.close();
}
13账号唯一性校验
在增加和修改页面中需要进行账号唯一性校验。编辑页面查找账号唯一性需要先排除正在编辑的用户的账号。
spring提供了StringUtils.isNotBlank来检查字符串。
点击提交按钮后,需要使用ajax同步来验证是否账号唯一。
addUI.jsp
<script type="text/javascript">
var result = false;
function verifyAccount(){
var account = $("#account").val();
if(account.trim()=="")
return ;
var url = "${basePath}nsfw/user_verifyAccount.action?time="+new Date().getTime();
var content = {
"user.account":account
};
$.ajax({
type:"POST",
url:url,
data:content,
async:false,
success:function(msg) {
if ("true" == msg){
alert("账号已经存在,请使用其他账号!");
$("#account").focus();
result = false;
}else{
result = true;
}
}
})
}
function doSubmit(){
verifyAccount();
if(result==true)
document.forms[0].submit();
}
</script>
editUI.jsp
<script type="text/javascript">
var result = false;
function verifyAccount(){
var account = $("#account").val();
if(account.trim()=="")
return ;
var url = "${basePath}nsfw/user_verifyAccount.action?time="+new Date().getTime();
var content = {
"user.account":account,
"user.id":"${user.id}"
};
$.ajax({
type:"POST",
url:url,
data:content,
async:false,
success:function(msg) {
if ("true" == msg){
alert("账号已经存在,请使用其他账号!");
$("#account").focus();
result = false;
}else{
result = true;
}
}
})
}
function doSubmit(){
verifyAccount();
if(result==true)
document.forms[0].submit();
}
</script>
aciton
public void verifyAccount() throws IOException {
HttpServletResponse response = ServletActionContext.getResponse();
PrintWriter writer = response.getWriter();
String msg = "false";
if(user != null && StringUtils.isNotBlank(user.getAccount())){
int ret = userService.findUserByAccountAndId(user.getAccount(),user.getId());
if(ret >0){
msg = "true";
}
}
writer.write(msg);
writer.flush();
writer.close();
}
dao
public int findUserByAccountAndId(String account,String id) {
String hql = "from User where account ="+"'"+account+"'";
if(StringUtils.isNotBlank(id))
hql+=" and id != "+"'"+id+"'";
List list = getSession().createQuery(hql).list();
return list.size();
}
14.异常和返回结果类型
15.角色与权限
角色与权限是多对多的关系。但是由于权限没有对应的实体和表,是固定的5个值,所以角色和角色权限(中间表)是一对多的关系。RolePrivilege只有一个属性RolePrivilegeId,RolePrivilegeId作为联合主键类,必须要实现Serializable接口并且重写hashcode和equals方法。
Role
public class Role {
private String roleId;
private String name;
private String state;
private Set<RolePrivilege> rolePrivileges;
public static String ROLE_STATE_VALID = "1";
public static String ROLE_STATE_INVALID = "0";
get...
set...
}
Role.hbm.xml
<hibernate-mapping>
<class name="com.juaner.nsfw.role.entity.Role" table="t_role">
<id name="roleId" type="java.lang.String">
<column name="r_id" length="32"/>
<generator class="uuid"/>
</id>
<property name="name" type="java.lang.String">
<column name="r_name" length="20" not-null="true"/>
</property>
<property name="state" type="java.lang.String">
<column name="r_state" length="1"/>
</property>
<set name="rolePrivileges" inverse="true" lazy="false" cascade="save-update,delete">
<key>
<column name="r_id" />
</key>
<one-to-many class="com.juaner.nsfw.role.entity.RolePrivilege"/>
</set>
</class> </hibernate-mapping>
RolePrivilege
public class RolePrivilege implements Serializable{
private RolePrivilegeId id;
get...
set...
}
RolePrivilegeId
public class RolePrivilegeId implements Serializable{
private String code;
private Role role;
get...
set...
equals...
hashcode...
}
RolePrivilege.hbm.xml
<hibernate-mapping>
<class name="com.juaner.nsfw.role.entity.RolePrivilege" table="t_roleprivilege">
<composite-id name="id" class="com.juaner.nsfw.role.entity.RolePrivilegeId">
<key-many-to-one name="role" lazy="false" class="com.juaner.nsfw.role.entity.Role">
<column name="r_id"/>
</key-many-to-one>
<key-property name="code" type="java.lang.String">
<column name="p_code" length="20"/>
</key-property>
</composite-id>
</class>
</hibernate-mapping>
跳转到添加页面和修改页面都要在域中设置权限map
public String addUI(){
ActionContext.getContext().getContextMap().put("privilegeMap", Constant.PRIVILEGE_MAP);
return "addUI";
}
添加角色
public String add()throws Exception{
if(role != null){
if(privilegeIds!=null){
Set<RolePrivilege> set = new HashSet<>();
for(String code:privilegeIds){
set.add(new RolePrivilege(new RolePrivilegeId(code,role)));
}
role.setRolePrivileges(set);
}
roleService.save(role);
}
return SUCCESS;
}
跳转到修改页面
public String editUI(){
if(role != null && role.getRoleId()!= null) {
role = roleService.findObjectById(role.getRoleId());
ActionContext.getContext().getContextMap().put("privilegeMap", Constant.PRIVILEGE_MAP);
if(role.getRolePrivileges().size()>0){
privilegeIds = new String[role.getRolePrivileges().size()];
int i=0;
for(RolePrivilege roleprivilege:role.getRolePrivileges()){
privilegeIds[i++] = roleprivilege.getId().getCode();
}
}
}
return "editUI";
}
修改角色,在设置新的权限之前要删掉旧的权限
public String edit()throws Exception{
if(role != null && role.getRoleId()!= null){
if(privilegeIds!=null){
Set<RolePrivilege> set = new HashSet<>();
for(String code:privilegeIds){
set.add(new RolePrivilege(new RolePrivilegeId(code,role)));
}
role.setRolePrivileges(set);
}
roleService.update(role);
}
return SUCCESS;
}
16.struts标签
遍历显示
<s:iterator value="roleList" status="st">
<tr <s:if test="#st.odd"> bgcolor="f8f8f8"</s:if>>
<td align="center"><input type="checkbox" name="selectedRow" value="<s:property value='roleId' />"/></td>
<td align="center"><s:property value="name" /> </td>
<td align="center">
<s:iterator value="rolePrivileges">
<s:property value="#privilegeMap[id.code]"/>
</s:iterator>
</td>
<td align="center"><s:property value="state='1'?'有效':'无效'" /></td>
<td align="center">
<a href="javascript:doEdit('<s:property value='roleId' />')">编辑</a>
<a href="javascript:doDelete('<s:property value='roleId' />')">删除</a>
</td>
</tr>
</s:iterator>
checkboxlist
<s:checkboxlist list="#privilegeMap" name="privilegeIds"></s:checkboxlist>
17.用户角色
用户类和角色类及其映射都无法再修改,所以需要将用户类和中间表类独立出来。用户和角色是多对多的关系。所以只要创建作为中间表的UserRole,它具有联合主键性质。因为可能有根据用户查询角色的需求,没有根据角色查询用户的需求,所以联合主键类的设计如下:
添加
<s:checkboxlist list="#roleList" name="userRoleIds" listKey="roleId" listValue="name"></s:checkboxlist>
添加用户角色关系时,虽然联合主键类中的对象是Role,但表中实际保存的是roleId,所以不需要查询出响应的Role,只要保存有roleId属性的Role就可以了。虽然保存时user的id属性不存在,但是hibernate在save或update方法之后会对user的其他属性进行回填,所以在save后可以使用id属性。
service
public void saveUserAndRole(User user, String... userRoleIds) {
save(user);
System.out.println(user.getId());
for(String roleId:userRoleIds){
UserRole userRole = new UserRole();
Role role = new Role(roleId);
userRole.setId(new UserRoleId(role,user.getId()));
userDao.saveUserRole(userRole);
}
}
修改时,跳转到修改页面之前,需要在域对象中放置当前用户的角色
public String editUI(){
ActionContext.getContext().getContextMap().put("roleList",roleService.findObjects());
if(user != null && user.getId()!= null) {
user = userService.findObjectById(user.getId());
List<UserRole> userRoles = userService.getUserRolesByUserId(user.getId());
if(userRoles!=null&&userRoles.size()>0){
userRoleIds = new String[userRoles.size()];
int i=0;
for(UserRole userRole:userRoles){
userRoleIds[i++] = userRole.getId().getRole().getRoleId();
}
}
}
return "editUI";
}
修改时,需要先删除旧的角色,再添加新的角色
public void updateUserAndRole(User user, String... userRoleIds) {
update(user);
userDao.deleteUserRoleByUserId(user.getId());
for(String roleId:userRoleIds){
UserRole userRole = new UserRole();
Role role = new Role(roleId);
userRole.setId(new UserRoleId(role,user.getId()));
userDao.saveUserRole(userRole);
}
}
18.异常
对特定异常类的结果映射,其他action的映射需要继承base-default。
对实现了StrutsResultSupport的类的结果映射(配置了对该类的结果映射名后,如果某个action方法返回该映射名,会由该类的doExecute()方法进行处理)。
public class SysResultAction extends StrutsResultSupport {
@Override
protected void doExecute(String s, ActionInvocation actionInvocation) throws Exception {
HttpServletRequest request = ServletActionContext.getRequest();
HttpServletResponse response = ServletActionContext.getResponse();
BaseAction action = (BaseAction) actionInvocation.getAction();
System.out.println("进入了SysResultAction......");
}
}
<package name="base-default" extends="struts-default">
<result-types>
<result-type name="errorAction" class="com.juaner.core.action.SysResultAction"></result-type>
</result-types>
<global-results>
<result name="errorAction" type="errorAction">/WEB-INF/jsp/error.jsp</result>
<result name="error">/WEB-INF/jsp/error.jsp</result>
<result name="input">/WEB-INF/jsp/error.jsp</result>
</global-results>
<global-exception-mappings>
<exception-mapping exception="com.juaner.core.exception.ActionException" result="error"></exception-mapping>
<exception-mapping exception="java.lang.Exception" result="input"></exception-mapping>
</global-exception-mappings>
</package>